Files
ZNJJ-api-server/docs/assignment6-compat.md
T
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

61 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 作业 6 兼容差异清单:LangGraph 业务状态 vs FastGPT 现状
> 范围:`/set_info`、`/get_info`、`/delete_session`、`/chat` 四个接口在
> `AGENT_BACKEND=langgraph` 下接入应用服务 + repository 后的行为差异。
> FastGPT 模式(`AGENT_BACKEND=fastgpt`)保留旧实现,不受影响。
## 接口响应契约(保持不变)
| 项 | 现状(FastGPT) | LangGraph(作业 6) |
|---|---|---|
| 请求/响应模型 | `ProcessRequest/Response_*` | 相同(endpoint 未改模型) |
| `get_info` 分组名 | `all` / `acdinfo` / `acdhuman1` / `acdhuman2` | 相同 |
| `get_info` 布尔外部表示 | `True→"1"`,`False→"0"`,未知→`""` | 相同(`to_external_string`) |
| `get_info` 未知 key | 返回 JSON 空串 `'""'` | **保持** `'""'`(现状兼容) |
| `includeInputInfo` 字段 | 触发 FastGPT 辅助对话 | 继续接受但**忽略**——新后端零辅助对话 |
## 有意的行为差异(新后端收紧)
| 项 | FastGPT 现状 | LangGraph | 理由 |
|---|---|---|---|
| `set_info` 未知 key | 任意 key 写入 state 变量 | **拒绝**(500 + "入参不规范:未知或受保护的字段 key") | 白名单保护;任意写入会污染图输入。上线前需审计旧调用方是否依赖任意 key 写入 |
| `set_info` 图内部键(`stage_code` 等) | 可写(state 是裸 dict) | **拒绝**(`INTERNAL_FIELD_KEYS` 保护) | 内部状态只允许图自己推进 |
| `set_info` 字段值 | 任意字符串原样存 | 按注册表类型解析(bool/int 严格),无法解析拒绝 | 保留 空/False/0/未知 区分,杜绝 `bool("0")` 陷阱 |
| 图表单键与业务键 | FastGPT state 为裸 dict,无映射概念 | 建立双向映射(作业 6):表单六键(`has_injury` 等)<-> acd 业务键(`ywrysw` 等);`bjrjs`/`ywmtc` 无表单来源,仅 `set_info` 可写 | 图的表单语义与 get_info 业务分组需要同一份事实 |
| LLM 调用 | set/get 走辅助对话 + 事后删记录 | **零 LLM 调用**(测试 spy 保证) | 成本与延迟;删除 race 消失 |
| 重复 `delete_session` | FastGPT SDK 行为未固定 | **幂等成功**(业务状态删除天然幂等;checkpoint 清理重复触发但缺失静默容忍) | 行为固定为测试 |
## 图表单键 <-> 业务键映射(作业 6 建立)
| 图表单键(accident_fields) | 业务键(acdinfo 分组) |
|---|---|
| `has_injury` | `ywrysw` |
| `has_non_motor_vehicle_hit` | `ywfjdc` |
| `is_on_scene` | `sfsgxc` |
| `vehicle_count` | `jdcsl` |
| `accident_time` | `sgfssj` |
| `accident_cause` | `sgyy` |
- chat 方向:repository 业务键经映射注入图为表单键(图只认表单语义)。
- 写回方向:图产出的表单键差量经映射落 repository 业务键,get_info 分组即可读到。
- `bjrjs`(报警人是否驾驶员)、`ywmtc`(是否撞摩托车)无表单来源:
不进入注入映射,仅支持 set_info 直写、get_info 直读。
## 待审计项(作业 6-7 要求的后续工作)
- [ ] 审计现有调用方是否存在对 `set_info` 任意 key 写入的依赖
(如动态自定义键)。存在则在注册表补登记或提供逃生口。
- [x] ~~流式 `chat` 的 `formUpdate` 差量写回 repository~~
(完整版已实现:FormUpdate 事件捕获后经映射写回,见 `app_service.stream`)。
- [ ] `get_info` 返回值中的敏感字段(证件号/手机号)回显边界:
注册表已记录 `SensitiveLevel`,访问控制随作业 9 落地。
## 验证
- `test/services/test_fields_registry.py`:注册表完整性、类型/敏感级别、
外部表示、`bool("0")` 防线。
- `test/services/test_app_service.py`:四接口组合(set→get→chat 注入→
差量写回→分组读→删除→无泄漏),set/get/delete 零模型调用 spy,
重复删除幂等。
- `test/api/test_assignment6_endpoints.py`:HTTP 层验收演示链路。