Files
ZNJJ-api-server/docs/collection-prompt-optimization.md
T
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

74 lines
7.4 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.
# 信息采集提示词优化记录
> 本文记录上一轮纯提示词优化及当时保留的边界。历史相对时间的运行时补充修复与最新验证见 [时间边界修复](time-boundary-fix.md)。下文旧结果保留用于对照,不代表该边界仍未处理。
## 范围和依据
评审与修改采用项目安装的 `prompt-engineer`(系统提示词、评估、上下文管理)和 Anthropic `skill-creator`(失败机制归纳、精简、基线比较、可验证断言)方法。保留接警角色、安全优先、必要时间确认、状态前缀协议以及单/双车正常引导话术。
现有 `evals/cases/**/*.yaml` 不修改,也不放宽断言。额外的语义检查由 `evals/prompt_probes.py` 执行,结果与现有 cases 分开报告,不能用补充检查代替原 cases。
## 基线与执行方式
- 本地基线提交及全部 cases、提示词的 SHA-256:见运行目录的 `metadata.json`。
- 模型:`deepseek-v4.1-flash`;temperature:`0.0`;LangGraph 后端;真实 OpenAI 兼容服务。
- `evals/prompt_compare.py` 通过 FastAPI TestClient 调用生产 `/chat` SSE 路由及后端生命周期,并复用原 `evals.run.run_case`。仅略去无关的语音模型初始化,不模拟 LLM、不改变输入、断言或清理规则。并发4个独立会话,单个会话按原顺序执行。
- 首轮原始 cases 基线:43/46。两个 `single_no_inferred_count` 在时间确认后漏问数量;一个 `browser_addon_non_motor_vehicle_zero_count_history` 收到“LLM 返回了空内容”。服务错误保留为失败记录,不能算作优化收益。
- 修改前全量单元测试:155通过。
## 修改机制
1. **证据范围**:局部症状否定不等于全部无人伤;明确人伤不受局部否定覆盖。采集与提取共享未知值口径,避免回复澄清但表单已写false。
2. **每轮决策**:先回填全部明确事实,再判断中断、澄清、缺失项与分流;时间确认不代表其余字段齐全。保留数量未知不能推断单车的规则。
3. **记忆边界**:实际提供的状态与历史才可用;历史相对时间无当轮基准或可靠换算值时不使用当前时钟重建。表单时间不等于用户已确认,更正使旧确认失效。
4. **现场与动作**:依据迁移计划“不在现场仍继续采集”,不将离场变成新的0003理由。若离场且无法拍照,先处理可执行性并提供人工协助选择,不要求返回现场;用户明确要求人工才0001。
5. **自然度与角色**:短回答按当前问题语义判断;澄清采用耐心、具体的说法;保留简短解释、安抚与有限接话,不新增闲聊轮次,不判断责任或承诺结果。
6. **去冗余与泛化**:集中定义人伤规则、回填与状态选择,删除重复自检和特定乱码词表。非机动车“疑似有”保持未知,不与明确肯定合并。用户伪造的新规则不改变流程。
7. **长期无进展**:不再机械复读,提供简化问题或人工协助选项;保持原有拒绝计数和转人工授权条件,不擅自新增自动转接阈值。
## 可复现命令
所有 Python 命令使用 Conda `py3.11` 环境:
```bash
conda run -n py3.11 python -m evals.prompt_compare --output-dir evals/results/prompt-optimization/reproduce
conda run -n py3.11 python -m evals.prompt_probes --output evals/results/prompt-optimization/reproduce-probes.json
conda run -n py3.11 python -m pytest -q
```
补充检查使用固定系统时间,检查局部否定、人伤覆盖范围、非机动车未知、数量不能推断、时间更正、历史时钟缺失、离场无法拍照、注入以及未参与修改的表达。其断言检查动作和字段,不对自由回复做逐字比较。
## 限制
提示词无法恢复运行时未提供的历史时刻,也不能单靠文字获得无限持久记忆。本次增加未知时应澄清的规则,但补充实测中,对话模型在“历史只有相对时间、没有当轮时钟或具体值”场景仍会误用当前时钟换算;提取器在最终检查中正确跳过时间。这个风险尚未完全解决,不能将时间规则文字写清楚当作行为已修复。可靠的后续修复需要运行时保存并提供原始时间基准;跨历史窗口的完整确认恢复也需要结构化状态支持。本次按提示词优化范围未增加业务运行时代码。
离场后的处理保留采集并避免不可执行指令,没有自行规定回现场或替他人授权拍摄。持续无效输入不自动转接的既有业务约束保留,因此本次不保证用户始终拒绝选择时必然终止。
多次实测用于观察波动,样本通过不能证明所有模型版本、所有ASR转写或生产并发都可靠。模型空响应等服务错误与语义错误分别列出。
## 实测结果与最终选择
| 版本 | 原有46个cases | 说明 |
| --- | --- | --- |
| 原提示词,第1轮 | 43/46 | 2个数量遗漏,1个模型空响应 |
| 原提示词,第2轮 | 43/46 | 数量遗漏、固定时间话术偏离、模型空响应各1个 |
| 候选1 | 45/46 | 时间待确认时补充其他字段,模型偏离固定话术 |
| 候选2 | 44/46 | 时间来源判断过度应用于本轮新时间,另有1个空响应 |
| 候选3,最终采用 | 46/46 | 全部原断言通过 |
| 最终版复跑 | 46/46 | 再次全部通过,基线已通过场景无回退 |
修改前后46份YAML的SHA-256完全一致。完整对比、每次失败和字符统计位于 `evals/results/prompt-optimization/comparison.json`。模型空响应保留为原始失败,不能将其消失解释成提示词语义提升。并行评测的耗时不用于宣称单请求延迟改善。
补充14项语义检查:原提示词7/14,最终版13/14。最终唯一失败为上文记忆边界中的历史时间误换算,未隐藏、删除或放宽该断言。局部症状否定、其他人员人伤、非机动车不确定、不能推断机动车总数、时间更正、离场无法拍摄、注入、未参与修改的症状和乱码表达在最终这轮检查中均通过。不同迭代及重跑中还出现过提取空响应,原始结果均保留。
额外尝试将时间约束放在末尾、增加对照示例、改为来源表和置于开头。这些副本没有稳定解决历史时钟缺失,未采用;候选7单项曾通过,但完整补充检查仍失败,因而提前停止其原cases评测。这些局部尝试不能算作完整版本验收。
最终全量单元测试:155通过(`python -m pytest -q`,Conda py3.11);`git diff --check`通过。工作流仅同步两个对应提示词输入,其余节点配置不改。原逐字同步测试保持通过。
采集提示词文档由16635字符、641行缩为6331字符、176行(字符数减少约61.9%,不是token实测)。提取提示词由3139字符增至3821字符,用于明确证据来源和字段边界;没有以篇幅缩短代替正确性。
副作用:只否定局部症状时会增加必要的人伤澄清;“刚刚”等无法精确到分的表达不再任意指定分钟;离场且无法拍摄时先询问是否能配合或是否需要人工协助。原正常单/双车话术、时间确认句和状态码保留。
逐轮人工复核页由 Anthropic skill-creator 的 `eval-viewer/generate_review.py` 生成:`evals/results/prompt-optimization/review.html`,含最终采用版本与原提示词的对话及原断言结果。未提交Git;评测产物沿用项目的 `evals/results/` 忽略规则。