# AI 事故信息采集 API(LangGraph 迁移分支) 本分支把事故采集、拍照和信息核实从 FastGPT workflow 迁移到嵌入式 LangGraph。 文本四接口通过 `AGENT_BACKEND` 选择 FastGPT 或 LangGraph,HTTP schema 与 SSE 事件保持兼容。 迁移作业计划见 [docs/langgraph-backend-migration-plan.md](docs/langgraph-backend-migration-plan.md), 字段兼容约定见 [docs/assignment6-compat.md](docs/assignment6-compat.md)。 ## 环境与安装 Python 3.11 使用 Conda 环境 `py3.11`(见 [AGENTS.md](AGENTS.md))。 ```bash conda activate py3.11 pip install -r requirements.txt # 项目仍使用该 SDK 支持 FastGPT 路径;源码在独立仓库维护。 pip install -e /path/to/fastgpt-python-sdk ``` ## 配置与后端选择 复制 `.env.example` 为 `.env` 并填写配置;`.env` 不进入 Git。 - FastGPT:`AGENT_BACKEND=fastgpt`,填写 `ANALYSIS_SERVICE_URL`、`ANALYSIS_AUTH_TOKEN`、`APP_ID`。 - LangGraph:`AGENT_BACKEND=langgraph`,按 `.env.example` 填写命名 LLM 配置, 由 `LLM_PROVIDER` 选择模型;文本后端不要求 FastGPT 凭证。 - LangGraph 存储:`AGENT_STORAGE=memory|sqlite|postgresql`。每个实例只选一个,修改后重启。 `DATABASE_URL` 不控制 LangGraph 会话存储,切换数据库不自动搬迁旧数据。 本地 SQLite 示例: ```dotenv AGENT_BACKEND=langgraph AGENT_STORAGE=sqlite AGENT_SQLITE_PATH=./data/agent.sqlite3 AGENT_DB_AUTO_MIGRATE=false ``` 首次初始化和运行: ```bash conda run -n py3.11 python -m src.storage.migrate --backend sqlite conda run -n py3.11 python -m src.serve --port 8000 ``` PostgreSQL 的连接池、迁移、本地 compose 与多 worker 部署见 [docs/agent-storage.md](docs/agent-storage.md)。Windows 使用 `python -m src.serve`, 它为 psycopg 选择兼容的事件循环;Linux 也可用常规 uvicorn 命令启动。 ## 模型调用 LangGraph 文本后端通过 `langchain-openai.ChatOpenAI` 调用 OpenAI 兼容接口。 现有 `LLM_PROVIDERS` / `LLM_PROVIDER` 和各组环境变量继续生效;统一使用 Chat Completions API,`EXTRA_BODY` 中的关闭推理等扩展参数照常透传。 依赖固定为 `langchain-openai==1.1.9`、`langchain-core==1.5.1`, 与当前 LangGraph 和 OpenAI SDK 环境配套验证。 应用层控制重试:默认每次尝试 60 秒、最多额外重试 3 次,退避 1/2/4 秒; 底层 SDK 自动重试关闭。模型文本开始输出后不重试,提前停止消费会显式关闭 底层 HTTP 流。兼容网关默认不请求流式 usage;非流式返回的 usage 可供 LangChain callbacks 使用。 模型调用继承图的 callbacks、metadata 和 tags,并标记 `llm.complete` / `llm.stream` 及 `llm_attempt`。这是追踪集成的基础,日志、存储和整轮 SSE 的观测需分别接入。 事故采集使用 LangGraph 原生并行分支:`collect` 生成回复, `extract_accident_fields` 提取字段,二者经汇合边进入 `merge_collect`。 两个分支读取同一轮的参考时间和状态,各写独立通道,合并后统一提交。 人员核实的抽取依赖本轮回复,保持串行依赖。 增量输出由 LangChain 原生 `astream_events(version="v2")` 消费: `RunnableGenerator` 输出通过阶段前缀校验的文本;`validated_reply` 的 `on_chain_end` 表示整条回复已通过校验,立即刷新分句器最后一句。 抽取模型的事件不转成聊天正文;`formUpdate` 和 `done` 仍等待业务提交成功。 客户端关闭流时由原生事件流取消并等待图任务,公开 SSE 事件类型不变。 节点职责、事件映射和提交时序见 [docs/agent-streaming.md](docs/agent-streaming.md)。 ## HTTP 接口 - `GET /`:存活检查。 - `POST /chat`:对话;`?stream=true` 使用真实增量 SSE。 - `POST /set_info`、`POST /get_info`:业务字段读写,不调用模型。 - `DELETE /delete_session`:清理 checkpoint 和业务状态,真实存储错误返回失败。 - SQLite/PostgreSQL 模式可给 `/chat` 添加 `Idempotency-Key` 请求头, 重放已提交结果;复用 key 但请求内容不同返回业务码 409。 SSE 的 `error` 是失败终止,`done` 是成功结束。正文可以先流出, 调用方必须在收到 `done` 后才将本轮视为成功。`needFormUpdate=false` 只隐藏对外差量,不影响内部字段提交。 ## 测试 ```bash conda run -n py3.11 python -m pytest -q ``` 测试覆盖公共 schema、两后端适配、流式校验/取消、会话串行、字段别名、错误码与持久化恢复。 SQLite 集成测试使用临时真实文件;PostgreSQL 集成测试需要 `AGENT_TEST_POSTGRES_DSN` 指向隔离测试库。未配置时 PostgreSQL 用例会明确跳过。 两端都有直接退出子进程的恢复测试,不调用真实 LLM。 真实模型评测使用 `evals/run.py`,结果按每轮模型与代码版本单独保存, 历史轮次通过率不代替当前提交的业务验收。 ## 目录结构 ```text src/ api/endpoints.py # HTTP schema、阶段标签解析、SSE 协议 agent/ # 流程图、节点、版本化提示词与模型服务 backends/ # FastGPT / LangGraph 中立适配 services/ # 四接口应用服务、字段注册表、会话锁 storage/ # SQLite / PostgreSQL、轮次日志、migration core/fastgpt_client.py # 后端与存储生命周期、依赖注入 serve.py # 跨平台单 worker 启动入口 schemas/models.py # 公共请求/响应模型 test/storage/ # 两种数据库的真实集成与故障恢复测试 evals/ # 真实模型评测用例与 runner ``` ## 部署边界 - memory 是临时存储,重启丢失;SQLite 限定单实例、单 worker。 - PostgreSQL 使用数据库级会话锁、版本和 epoch 校验;仍需按目标负载验证池容量与吞吐。 - 业务快照是已提交状态的权威源,旧 checkpoint 执行进度在下一轮重建, 不承诺从未提交的 LLM 调用中途续跑。 - 语音 WebSocket 管线仍有独立配置,不由本次数据库选择自动迁移。 - 未知字段写入、敏感字段访问边界等兼容事项继续按兼容清单处理。