Commit Graph
30 Commits
Author SHA1 Message Date
Eric Wang e6a96ed135 fix(storage): finish SQLite transactions before propagating cancellation 2026-10-26 16:50:57 +08:00
Eric Wang d8d48c26a3 feat(llm): migrate model calls to LangChain ChatOpenAI 2026-10-24 17:08:46 +08:00
Eric Wang 97de142e6d feat(storage): add selectable SQLite and PostgreSQL persistence
- Select one storage backend per instance via AGENT_STORAGE, retaining
  memory as the backward-compatible default. Manage the selected async
  repository, official checkpointer and connection pools in lifespan;
  fail startup on unavailable or uninitialized storage without fallback.
- Add SQLite and PostgreSQL adapters, schema initialization CLI, sample
  PostgreSQL compose configuration and a Windows-compatible serve entry.
  SQLite enforces single-instance file ownership; PostgreSQL uses a
  dedicated pool for session advisory locks plus version/epoch fencing.
- Make repository IO and commit callbacks awaitable. Persist business
  fields, a complete committed graph snapshot and turn result/version in
  one business transaction before success. Rebuild execution checkpoints
  from that snapshot, discarding uncommitted progress after interruption.
- Support optional Idempotency-Key on durable chat requests. Replay
  committed results and return 409 on changed request content; delete
  removes business/history data and replay records while retaining only
  an epoch/version tombstone to reject stale commits.
- Document migration, database switching boundaries, backup/deployment
  expectations and crash recovery. Ignore generated database files.

Validation: 315 tests passed with real SQLite and isolated PostgreSQL,
including abrupt child-process exits before/after business commit;
both backends passed CLI migration and actual HTTP server restart smoke.
Existing API tests were rechecked after isolating them from user storage.
An initial Windows CreateProcess permission failure did not recur in the
full diagnostic run; failure assertions were not skipped or relaxed.
2026-10-24 13:41:54 +08:00
Eric Wang 3caf17494f fix(api): report checkpoint deletion failures and classify SSE errors
Delete checkpoints before removing business fields. Suppress only an
explicit CheckpointNotFoundError; propagate storage failures and
cancellation so the endpoint cannot report false success. Prefer async
checkpoint deletion and fail clearly when cleanup is unsupported.

Classify SSE error events as 401 for authentication, 429 for rate limits,
and 500 for other failures, using the same fixed messages as non-stream
responses. Errors terminate the stream without a success done event or
provider exception text in the response.

Validation: 286 offline tests passed (19 added), including failed-delete
HTTP retry with preserved business/checkpoint state, explicit missing
threads, cancellation, missing cleanup capability, and HTTP SSE errors
before and after text output.
2026-10-23 19:48:29 +08:00
Eric Wang 24e2cfbe10 fix(backends): make streamed replies and session state consistent
- Validate stage prefixes before forwarding model tokens. Invalid prefixes
  may use the existing repair budget; once output starts, validation failure
  aborts the turn without appending a regenerated reply. Bound the token
  queue and close inner streams when consumption stops.
- Replace delete-time lock eviction with reference-counted session locks
  covering holders and waiters. Serialize set/get with chat/stream/delete
  and release cancelled waiters without replacing a live lock.
- Store person synonyms under workflow-native driver keys and expose
  consistent alias views to single/group reads and graph prompt injection.
- Separate committed field patches from public formUpdate visibility.
  Commit callbacks keep repository fields synchronized even when updates
  are hidden or the consumer closes after graph completion.
- Disable OpenAI SDK automatic retries. Own bounded retry attempts in the
  application, use 1/2/4 second backoff, retry streams only before text is
  emitted, enforce attempt timeouts, and close upstream/client resources.
- Translate FastGPT SDK max_retries (total attempts) from the configured
  extra-retry count, and verify the real SDK loop uses four attempts.
- Document the per-LLM budget and streaming failure semantics without
  claiming the whole multi-call HTTP turn has the same timeout.

Validation: 267 offline tests passed, including actual SDK requests through
MockTransport, stream repair/abort, timeout/close, lock races, aliases and
formUpdate visibility; existing four dependency deprecation warnings.
2026-10-23 15:54:51 +08:00
Eric Wang 20e151b097 feat(services): register workflow-native driver keys in field registry
Workflow reconciliation (see previous commit) showed the 20261022
state variable really stores person identity under driver{i}ID /
driver{i}Phonenumber (x2), while the API get_info group keys
(sfzmhm{i}/sjhm{i}) have zero references in any workflow version -
the legacy group read always returned empty for workflow-produced data.

- registry: +4 keys (driver1/2ID, driver1/2Phonenumber) in
  human1/human2 groups, SENSITIVE, documented as synonymous with
  sfzmhm{i}/sjhm{i}; 24 -> 28 specs
- driver{i}License deliberately NOT registered: the sandbox reads
  state.hphm{i} and only renames the output for confirmation prompts -
  it is not a state key, set_info rejects it as unknown (workflow
  never consumes it)
- intentional diff documented: acdhuman1/2 group output now includes
  the driver keys (legacy FastGPT output did not) - fixes the legacy
  'workflow person data unreadable by group' gap; synonym merging
  (driver1ID vs sfzmhm1) deferred pending caller confirmation
- tests: registry size 28, driver keys present with sensitive level,
  License alias excluded

Verified: 230 unit tests
2026-10-22 23:40:27 +08:00
Eric Wang 2bbbaf07af docs(services): workflow 20261022 field reconciliation for assignment 6
Reconciled the field registry against workflow/20261022 (synced with
main@c7ca781) and historical versions 20250419-20261021:
- form six keys match the workflow form variable (bNJkeXot) and the
  更新表单 whitelist semantics exactly
- acd business keys originate from the 20250419 extraction schema
  (dropped by the workflow since 20251015, kept as the API contract)
- person group keys (xm1/sfzmwh1/sjwh1/csbw1...) exist in no workflow
  version - they are the API server's own contract
- the form<->business key mapping is migration-new semantics bridging
  both sides, fixed by bidirectional tests
Finding: workflow 20261022 state uses driver1ID/driver1License/
driver1Phonenumber naming, which never matched the API get_info group
keys - existing behavior read empty; recorded in the audit backlog to
confirm which naming live callers actually use
2026-10-22 21:38:10 +08:00
Eric Wang 7f52f1c4d0 feat(services): assignment 6 full - form/business key mapping and stream write-back
- fields_registry: FORM_TO_BUSINESS_KEY bidirectional mapping between
  the graph's six form keys (has_injury...) and the acd business keys
  (ywrysw...); bjrjs/ywmtc have no form source (set_info only);
  business_patch_from_form maps graph diffs to whitelisted business keys
  and filters internal/unknown keys
- app_service: chat injection now maps repository business keys back to
  form keys; both complete() and stream() write back field diffs
  (FormUpdate events captured in stream, closing the skeleton gap);
  form keys never leak into the business repository
- docs/assignment6-compat.md: mapping table documented, stream write-back
  backlog item resolved
- tests: mapping coverage, write-back mapping end-to-end, reverse
  mapping injection (bjrjs/ywmtc excluded), stream FormUpdate write-back

Verified: 205 unit tests
2026-10-22 21:07:01 +08:00
Eric Wang 8717d9066c feat(services): assignment 6 skeleton - app service, field registry, in-memory repository
- fields_registry: 24 business keys in acd/human1/human2 groups with
  value_type, writable and SensitiveLevel metadata; strict bool/int
  parsing (no bool('0') trap); INTERNAL_FIELD_KEYS protection list
- repository: SessionRepository protocol + InMemorySessionRepository
  (idempotent delete; PostgreSQL swap-in is assignment 7)
- AccidentAppService: chat/set_info/get_info/delete_session share one
  business state - chat injects latest repository fields into the graph
  and writes back validated field diffs; set/get/delete make zero LLM
  calls and zero helper conversations (includeInputInfo accepted but
  unused); unknown get keys keep the '' JSON-empty-string contract,
  unknown set keys are rejected by whitelist
- ChatInput.injected_fields neutral contract extension; LangGraphBackend
  merges injected fields into graph input (set_info visible next chat)
- endpoints: thin layer - langgraph mode routes business state through
  the app service (fastgpt mode keeps the legacy path); delete cleans
  repository + graph checkpoint, idempotent
- tests: registry completeness (sfzmwh/sjwh/csbw included), app service
  combos with LLM-call spy, HTTP acceptance flow (set -> get -> chat ->
  groups -> delete -> no leak, idempotent re-delete)
- docs/assignment6-compat.md: behavior diff list vs FastGPT status quo
  and the audit backlog (arbitrary set_info key usage, stream formUpdate
  write-back, sensitive-field display boundary)

Verified: 200 unit tests (172 existing + 28 new)
2026-10-22 20:50:10 +08:00
Eric Wang e72d9c9bc0 feat(agent): align with workflow@20261022 - turn_context messages and prompt tails
- merge main (b0ff2e0..c7ca781): workflow/20261022 moves dynamic context
  out of fixed prompts - collection/extraction prompts carry no inline vars;
  reference time and current form travel in the user message <turn_context>
  block; photo/confirm data kept at prompt tails
- prompts: all 8 files regenerated from 20261022 (byte-identity tests
  point at the new export)
- collect: user message = <turn_context>(本轮参考时间) + <user_input>;
  extraction message adds 当前表单; single trusted clock per turn threads
  through reply/extraction/repair
- photo: raw input only (20261022 photo nodes use system_text, no wrapper)
- workflow fake llm: unwraps <user_input> before event parsing
- fields: accident_time normalized to extraction format (YYYY年M月D日H点m分,
  strip zero padding) - fixes form assertion mismatch with padded output
- evals/run.py: trust_env=False - bypass Windows system proxy (registry
  proxy at 192.168.0.4:7897 was intercepting localhost and returning 503)
- verified: 172 unit tests; ALL golden suites pass on real model
  (46/46): collection_skip 12/12, photo_skip 4/4, no_false 2/2,
  button_guidance 12/12, non_motor_vehicle 14/14, time_confirmation 2/2
2026-10-22 12:28:24 +08:00
Eric Wang 9e28f69b3c feat(agent): trusted time evidence and collection prompt optimization
- time_context.py: server-side observation clocks for relative-time
  evidence (anti client-forgery); resolves X分钟前/小时前 against the
  observation timestamp of the turn that produced them, never re-basing
  history on the current clock; flags historical references without a
  reliable baseline
- state: dialogue_timestamps keyed by dialogue message index, persisted
  with checkpoint; welcome seeds index 0
- collect: single clock per turn shared by reply/extraction/repair;
  time_evidence injected into runtime context; reply_validator hook
  rejects time claims lacking evidence (one shared repair budget);
  model still interprets facts and chooses actions
- prompts: collection prompt restructured (shorter, state-bound-to-action
  table, gatekeeper principle, time source rules); extraction prompt
  aligned; workflow@20261021 json updated to match
- evals: prompt_probes / prompt_compare / time_boundary probe scripts
  (supplementary checks, original cases untouched)
- docs: collection-prompt-optimization.md (method + baselines),
  time-boundary-fix.md (problem, design, verification)
- gitignore: editor artifact dirs (.agents/.claude/.vscode, skills-lock)

Verified: 171 unit tests pass (16 new time-context tests)
2026-10-22 09:41:32 +08:00
Eric Wang a890f41f6f chore(prompts): regenerate collection prompt from workflow@20261021-r2
- merge main (fb9271e): collection prompt restructured (state-bound-to-action,
  gatekeeper principle); fill_missing eval cases relaxed to semantic regexes
- prompts/collection.md regenerated; byte-identity test updated and passing
- rerun golden evals: collection_skip 11/12, time_confirmation 1/2
  (inter-run variance; only single_no_inferred_count fails consistently -
  model routes without asking vehicle count after time confirmation)
2026-10-21 17:28:44 +08:00
Eric Wang 74db6be385 feat(agent): form pipeline + collection prompt workflow@20261021
- merge main: workflow/20261021 (collection prompt adds step-5 mandatory
  time readback-confirm before routing; non-motor/0003 branch rework;
  accident_cause unified schema), updated eval suites (photo_skip/
  button_guidance rewritten, no_false trimmed to asr, new
  non_motor_vehicle + time_confirmation with form/reply assertions),
  runner gains form/formMatches/replyMatches expectations
- prompts/collection.md regenerated from 20261021; extraction prompt
  archived (contentExtract description, 6-key whitelist)
- collect: extraction call per turn (extraction.md + current time/form
  injected), merge follows 更新表单 semantics (meaningful values only,
  number/string equality, diff -> turn_patch); accident_fields now uses
  external form keys
- backend: form_update flows to ChatResult and SSE formUpdate event
  (stream emits prefix, FormUpdate, body)
- fields: FORM_FIELDS whitelist with strict type validation
- verified: 155 unit tests; golden evals on real model - photo_skip 4/4,
  no_false 2/2, photo_button_guidance 12/12, non_motor_vehicle 14/14,
  collection_skip 10/12, time_confirmation 1/2; remaining 3 failures are
  model sequence/literal-template adherence, recorded in plan appendix
2026-10-21 17:10:33 +08:00
Eric Wang 11cffa01c9 docs: record progress, decisions and open questions in migration plan
- plan: assignment status table, five landed architecture decisions
  (propose-validate, context_schema DI, verbatim alignment, no LangGraph
  Server/SDK with rationale, 2004 semantics), real-model eval results
  (collection 12/12; photo_skip 0/4 and no_false 2/8 share the '对'
  routing pattern), three open questions with next actions, code map
- 2004 task rewritten as plate-confirm with both paths whitelisted
- graduation requirement reworded: illegal transitions never committed
- README: current status section pointing to plan appendix
2026-10-21 15:11:19 +08:00
Eric Wang 8323d53a70 feat(agent): domain events and transition whitelist validation (assignment 3)
Architecture (mirrors workflow/20261016 chatNode structure):
- events.py: client markers parsed to typed ClientEvent (sources
  verified against workflow JSON); plain text like '拍好了' is not an event
- transitions.py: LEGAL_TRANSITIONS whitelist drafted from chatNode
  prompts and Condition edges (16 entries, each with source_ref);
  is_legal_transition rejects unlisted/terminal-violating moves
- graph.py: multi-node graph (collect/single_photo/dual_photo/...
  matching workflow chatNodes), route_by_stage conditional edges,
  _fake_llm_propose simulates LLM stage-code proposals (assignment 4
  replaces with real LLM); code only keeps context bookkeeping
  (no_reply_count) and validation
- state.py: expanded domain fields (pending_question, accident/
  person fields, clarify/no-reply counts, turn_patch, state_version)

Key finding: 单车拍照#6/双车拍照#7 are browser_addon branches ending
at 0000, so 2005/2015 allow both 300x (direct) and 0000.

Verified: pytest 87 passed (24 transition/event tests newly green).
Known limit: stage proposals come from a fake LLM; per-stage scripts
and real LLM integration are assignments 4-5.
2026-10-19 16:25:04 +08:00
Eric Wang a6ce570499 docs: add project README, env guide and assignment baseline notes 2026-10-19 13:32:31 +08:00
Eric Wang 81b2335d9e docs: rewrite LangGraph migration plan as staged assignments 2026-10-16 16:15:18 +08:00
Eric Wang 34d09f53bb Merge branch 'main' of http://182.92.86.220:8300/wx44wx/ZNJJ-api-server
# Conflicts:
#	docs/视频快处智能信息采集机器人交互接口文档V1.0.10.docx
#	src/api/endpoints.py
#	src/core/fastgpt_client.py
2026-10-11 21:39:49 +08:00
Xin Wang bfc91b6f66 Remove outdated document for version 1.0.10 of accident reporting AI, streamlining the repository and eliminating unnecessary files. 2026-07-30 14:20:21 +08:00
Xin Wang f40643dd87 Refine prompts and evaluation cases for accident reporting AI
- Updated prompts to enhance clarity and consistency in user interactions, particularly focusing on safety prioritization and accurate information collection.
- Introduced new YAML evaluation cases to test various user input scenarios, ensuring robust handling of short, ambiguous, or irrelevant responses.
- Enhanced guidelines for transitioning to human assistance, emphasizing strict conditions for triggering state changes based on user responses.
2026-07-30 14:19:57 +08:00
Xin Wang 776f6e82b3 Add new documentation for version 1.0.10
- Introduced a comprehensive document detailing the interaction interface design for the intelligent information collection robot.
- Updated version history with new features, including the addition of the clientMode parameter and its impact on output formatting.
- Enhanced clarity in the API request and response structures, including examples for better understanding of the interaction flow.
2026-07-28 11:10:50 +08:00
Eric Wang 893eb2f2f7 Update environment variables and add LangGraph backend migration plan
- Updated ANALYSIS_AUTH_TOKEN and APP_ID in the .env file for enhanced security and configuration.
- Added a comprehensive migration plan document for transitioning the LangGraph backend, detailing the background, scope, goals, and architectural decisions for the project.
2026-07-26 07:24:30 +08:00
Eric Wang 88ba48ac77 Update docs 2026-07-24 17:33:34 +08:00
Eric Wang 6f91f45065 Add new state code for photo recognition failure in chat stream mode
- Updated documentation and API endpoint to include a new state code '0005' for handling cases where photo recognition fails consecutively, directing to human assistance.
- Ensured consistency between documentation and code for improved clarity in state management.
2026-07-23 23:34:13 +08:00
Xin Wang 3836b443b1 Update structured form update content in documentation for version 1.0.8
- Revised the formUpdate section to clarify the conditions under which structured updates are pushed.
- Added specific examples for accident vehicle count and cause of the incident to enhance understanding.
- Adjusted text_delta examples for improved clarity in response handling.
2026-06-18 11:07:20 +08:00
Xin Wang 83353c54d1 Remove outdated document for version 1.0.8 and replace it with an updated version containing comprehensive interface design details and enhancements. The new document includes additional parameters and examples for improved clarity on the chat interface and structured information handling. 2026-06-18 10:27:52 +08:00
Xin Wang 30c413b6d4 Refactor voice websocket documentation to clarify input handling and remove deprecated sections. Updated the demo process to indicate that image uploads are no longer required, streamlining user interaction with the voice service. 2026-06-01 11:24:31 +08:00
Xin Wang 0ef5de399a Add voice ws docs 2026-06-01 11:18:41 +08:00
Xin Wang 87e616ab55 提示词添加车辆预先提取和手机号多次拼接输入 2026-02-03 17:33:45 +08:00
Xin Wang c6869f773e Add document 2025-06-20 13:57:51 +08:00