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.
This commit is contained in:
Eric Wang
2026-10-24 13:41:54 +08:00
parent 3caf17494f
commit 97de142e6d
30 changed files with 1368 additions and 333 deletions
+9 -4
View File
@@ -357,7 +357,7 @@ docs/langgraph/
| FastGPT 应用层配置(应用级系统提示词、思考模式开关)与线上部署差异 | 作业 4/5 验收对账前 | 移植代码、离线评测与差异记录 |
| 评测案例与工作流导出的分歧(“对”分流语义、2004 走向)的权威口径 | 作业 5 验收前 | 白名单双走向、逐字比对测试、失败证据留档 |
## 当前进度与已知差异(2026-10-21 更新)
## 当前进度与已知差异(数据库实现更新,模型评测为历史记录)
### 作业进度
@@ -368,15 +368,20 @@ docs/langgraph/
| 3. 领域状态与事件 | ✅ 完成 | 事件解析 14 例、白名单校验 24 例;`LEGAL_TRANSITIONS` 17 条均带 `source_ref` |
| 4. 采集 + LLM | ✅ 完成 | 真实模型 `collection_skip_known_info` 12/12;单测含逐字比对 |
| 5. 拍照与核实 | ✅ 完成 | 真实模型 4/4 + 12/12 + 2/2(20261021 基准) |
| 6—10 | 未开始 | — |
| 6. 四接口业务状态 | 已实现 | 应用服务、异步 repository、字段别名、会话串行与接口回归 |
| 7. 持久化 | SQLite/PostgreSQL 初版已实现 | `src/storage/`;真实两库集成、进程退出恢复、幂等和版本冲突;见 [agent-storage.md](agent-storage.md) |
| 8. 真流式 | 已实现核心路径 | 模型增量、前缀校验、取消与提交回调;流式终止事件回归 |
| 9—10 | 未完成 | 生产访问边界、容量验证与双后端等价性验收继续保留 |
全量单元测试 143 通过;七份提示词与 20261020 工作流逐字比对由参数化测试锁定。
本轮全量测试 315 通过,包含真实 SQLite/PostgreSQL 集成测试。提示词来源和
逐字比对见 `test/agent/test_workflow_prompts.py`。下方真实模型结果是此前轮次,
本次数据库开发未重新运行 46 条真实模型黄金评测。
### 已落地的架构决策
1. **LLM 提议、代码校验(propose-validate)**:所有 stage_code 由节点内 LLM 产出(提示词即程序),代码只做前缀解析、白名单校验(含 clientMode 出口)和落库;曾尝试的代码强制推进/短促词守卫已按此分工移除。
2. **依赖注入走 `context_schema`**:`GraphDeps(llm=...)` 经 `Runtime` 注入调用期,不进 state/checkpoint;`build_graph()` 与 LLM 解耦。
3. **与工作流逐字对齐**:提示词原文渲染(含 `{{$变量}}` 替换:系统时间按 Asia/Shanghai、人员预填字段缺失时显式标注“未提供”);聊天历史按 user/assistant 消息传递(上限 50 条),对齐 chatNode `history=50`;welcome 话术为 Assigned Reply#3 原文并计入对话历史。
3. **与工作流逐字对齐**:提示词原文渲染(含 `{{$变量}}` 替换:系统时间按 Asia/Shanghai、人员预填字段缺失时显式标注“未提供”);聊天历史按 user/assistant 消息传递(`AGENT_HISTORY_MESSAGES` 默认 50,0 为不截断);welcome 话术为 Assigned Reply#3 原文并计入对话历史。
4. **不引入 LangGraph Server / langgraph_sdk**:生产形态的 Agent Server 需要 LangSmith license key、外网 beacon 出网及 Postgres+Redis 全栈,与课程目标(作业 7 亲手实现持久化)和部署环境不符;`langgraph dev` 仅为内存态,无增量能力。自部署高并发方案 = 嵌入库模式:无状态 FastAPI 多副本 + AsyncPostgresSaver + 每会话 advisory lock 串行 + 连接池预算(社区参照:langgraph-agent-toolkit、agent-bakery)。
5. **2004 语义**:确认单车车牌;车牌已明确时可 2003→2005 跳过,未明确时 2003→2004→2005。两种走向均在白名单登记,由模型判断。