Files
Jyotisha/docs/tasks/TASK-rectification-jev-intent-classifier-research-v2-20260927.md
T
Jesse_ChenandClaude Fable 5.1 710c848b30 docs(tasks): Jev intent research v2 — put previous turn into state
Research brief reopening the 09-19 Jev evaluation: same model
(jev-1.13.0), only the state changes (previous turn + previous
decision + continuation Noul, per Magpie v0.1.142). Re-extract
source B with case_id; thresholds unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0199rbQDTsUbCVw84wc8BTFe
2026-09-27 11:15:07 +08:00

124 lines
11 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.
# TASK · Jev 意图分类研究 v2:把上一轮放进 state(2026-09-27)
- 类型:**研究单**(只离线测,不改线上代码路径)
- 基线:`origin/staging` @ `828aca0a`
- 执行分支:`codex/jev-intent-v2-20260927`,worktree `.worktrees/jev-intent-v2-20260927`
- 前序:`TASK-rectification-jev-intent-classifier-research-20260919.md`(含 `-fix` / `-fix2`),报告 `docs/research/jev_intent_2026_09_19.md`
- 产品指示(2026-09-27):"请你忽略上次用 jev 测试的结果 …… 写吧然后 push 我去拿 key"
## 1. 为什么重开
外部信号:Magpie v0.1.142 把 TypeSafe Jev 接成语义路由分类器后,作者称效果"比之前好太多",改动点是**把上一轮的决策加入决策链**——"只承接上一轮的消息(如「继续」)沿用上一轮的 kind 与 effort;新问题单独分类;路由视图显示 Jev 被告知了上一轮什么"(发布说明原文意译)。
核实结果(2026-09-27 查官方文档):
| 项 | 事实 | 来源 |
| --- | --- | --- |
| 模型 | TypeSafe 只有一个模型 `jev-1.13.0`;`jev-latest` / `jev-preview` 都指向它。**与 09-19 所测同一版本,模型没变** | docs.typesafe.ai/models |
| 上下文 | 64k tokens/请求;state 可为 string / object / array,官方建议"消息串用 array" | docs.typesafe.ai/concepts/state |
| 语言 | "English is primary; other languages have lower accuracy currently" | 同上 |
| 置信度 | Choice 的 confidence ≈ `(n·peak − 1)/(n − 1)`;建议 >0.9 自动、0.5–0.9 复核、<0.5 回退 | docs.typesafe.ai/confidence |
| 多轮 | 官方:Jev "holds no conversation",每次只看你送的 state;**没有**任何官方多轮指引。Magpie 的做法是把上一轮塞进 state | OpenRouter What-is-Jev;Magpie 发布说明 |
| 价格 / 限流 | $0.042 / M 输入,输出免费;250k tok/s、1200 req/min(动态) | docs.typesafe.ai/models |
所以博文里"效果好太多"只能来自**喂法**。而我们 09-19 给 Jev 的 state 与线上分类器输入完全一致,都没有上一轮。这一点是可测的新变量,重开有依据。
## 2. 事故实证(按符号定位,基线 828aca0a)
1. 线上分类器输入没有上一轮:`frontend/src/lib/rectification-agentic/v9/turn-intent-classifier.ts` `classifyRectificationTurnIntent`(L212);L252–256 送模型的 JSON 只有 `current_question / options / user_message / case_status`。
2. 09-19 的 Jev state 照抄线上:`scripts/research/jev_intent_questions.py` `build_state`(L204)返回同样四个字段。
3. 真人语料没抽上一轮:`scripts/research/jev_intent_samples/README.md` L16–33 的抽取 SQL 只取 `turn_id / user_message / created_at / case_status / question_id / expected_answer_schema`,**没有 `case_id`,也没有上一轮的 `assistant_message`**,因此本地 `source_b.jsonl` 无法反推上一轮,必须重抽。
4. 表里有可用字段:`frontend/supabase/migrations/20260812010000_agentic_rectification_v9_runtime.sql` L76–78 `agentic_rectification_turns` 有 `case_id / user_message / assistant_message`,索引 `(case_id, created_at)`(L88–89),可按案件顺序还原上一轮。
5. 09-19 挡住上线的数(`docs/research/jev_intent_2026_09_19.md` §代表性检验):真人 157 条 Jev intent 91.1% vs 线上 89.2%;**高置信错误 6.4%(无焦点层 12.1%)> 3%**;低置信召回 24% < 60%。无焦点层 Jev 7 条错全是 `gold=unclear → pred=answer_current_focus`。
6. 延迟:Jev 中位 908 ms / P95 1194 ms;线上 Flash 中位 685 ms。宣传的 70–500 ms 在本地区不成立。
## 3. 根因(研究假设,待本单验证)
无焦点层错例"unclear 被判成回答当前题"的共同点是:模型不知道上一轮问了什么、用户这句是接着上一轮说还是另起话头。上一轮的**题**和**判定**恰好是区分这两种情况的信息。09-19 置信度不可用(高置信错误 6.4%)可能部分源于这批错例——信息缺失时模型仍给高置信。
**不做假设的部分**:中文准确率天花板(官方明说非英语更差)与延迟不会因 state 改变而变,本单不指望这两项改善。
## 4. 决策记录
1. **推翻 09-19 关单里的"不再造语料"**:产品 2026-09-27 授权重抽真人来源 B(带 `case_id` 与上一轮),因为旧抽样结构上无法测本单变量。仍**不造**新的模拟语料(来源 C 不重造、不扩)。
2. 09-19 关单里"不接管、不影子双跑"**维持**:本单只离线测;过门后是否接入、是否影子双跑由产品另行拍板。
3. 09-15"分类只用贵模型"口径**维持**到本单出结论。
4. 门槛沿用 09-19,不放宽:高置信错误 ≤ 3%、低置信召回 ≥ 60%、intent 准确率 ≥ 现行 −3pp(同一样本)。
5. 模型固定 `jev-1.13.0`(不用 `jev-latest`),响应 `model` 字段落报告。
## 5. 硬红线
1. 不改 `frontend/src/**` 任何生产代码;不加 Jev 到线上调用链;不加环境变量到部署文件。
2. 真人来源 B 原文**不得提交**(延续 09-19:本地 `.cache/jev_intent/`,gitignore);报告只出计数、混淆矩阵、脱敏错例画像(≤3 条/类,已去姓名年份地名)。
3. 不得用正则或关键词表做任何标注、复核或"延续判定"(BUG-976/977 口径同样适用于研究代码)。
4. 不得用模型代标 gold;上一轮的 `previous_intent` 若来自 Jev 自己的上一轮输出,报告里必须标明"链式(自喂)",不得写成真值。
5. `docs/BUG_HISTORY.md` 只在发现研究脚本自身缺陷时记录;不得把研究结论写成 Bug。
6. 不得顺手升级 `typesafe-sdk` 以外的依赖;SDK 版本写进报告 meta。
7. 报告 JSON `rows` 必须含每条每个变体的原始输出,所有表内数字可由 `--offline` 重算(延续 09-19 验收方法)。
## 6. 任务分解
### T1 · 重抽真人来源 B(带上一轮)
- 改 `scripts/research/jev_intent_samples/README.md` 的 SQL:加 `t.case_id`、`t.assistant_message`,按 `(case_id, created_at)` 排;本地脚本按案件顺序为每条生成 `previous_turn = {assistant_message, user_message}`(案件第一轮为 `null`)。
- 旧 157 条的 gold 按 `turn_id` 对回;新增行由执行方人工标注(延续 09-19 标注规范,`runtime_intent` 只作参考)。
- **验收**:报告 meta 写明 n(总 / 有上一轮 / 无上一轮)、三层分布、gold 来源(对回 / 新标)计数;`n_有上一轮 ≥ 100`,否则 T3 只报数不判定。原文未入库(`git ls-files | grep source_b` 为空)。
### T2 · state 三个变体(只改 `jev_intent_questions.py`,加参数不删旧路径)
| 变体 | state | 问题 |
| --- | --- | --- |
| V0 | 09-19 原样(四字段) | intent / answer_class / has_new_dated_event(原样) |
| V1 | V0 + `previous_turn: {assistant_message, user_message}` | 同 V0 |
| V2 | V1 + `previous_decision: {intent, answer_class}` + 新增 Noul `continues_previous_turn`("这句是否只是承接上一轮,没有新的意思") | V0 三问 + 该 Noul;`continues_previous_turn ≥ 0.9` 时沿用 `previous_decision.intent`(Magpie 规则),否则按本轮 `intent` |
- `previous_decision` 取值顺序:链式(同案件上一条的 Jev V2 输出)为主;另跑一份用 gold 上一轮做上界,两份都进报告并分别标注。
- `enforce_combo` 的结构不变量对 V1/V2 照常生效。
- **验收**:`python3 -m unittest tests.test_jev_intent_research` 新增 ≥3 个用例(V1/V2 state 形状、continues 规则、案件首轮 `previous_turn=null`)全绿,旧 11 个不动;`test_criterion_map_covers_production_prompts` 仍过(说明 Choice 语义没漂)。
### T3 · 跑数与对照
- 来源 B 全量:Jev V0 / V1 / V2(链式 + gold 上界)各两次(自洽率);线上 Flash 顶生产提示各一次(V0 输入 = 生产原样;另加一列 Flash + V1 输入,用于区分"上下文对任何模型都有用"还是"Jev 特有"——Flash 提示不改,只在 JSON 里多给 `previous_turn`)。
- 来源 C(900 条)只跑 V0 一次做回归锚(state 未变,应与 09-19 一致 ±1pp);来源 C 没有上一轮,**不跑** V1/V2。
- 指标沿用 09-19:intent / answer_class / dated 准确率、高置信错误、低置信覆盖 / 召回、自洽率、中位 / P95 ms、次均 input tok、θ 曲线;**新增**:按"有上一轮 / 无上一轮"分组,以及无焦点层 `unclear→answer_current_focus` 计数逐变体对比。
- **验收**:报告 `docs/research/jev_intent_2026_09_27.md` + JSON;结论三选一:`过门`(三项门槛全过且 V2 相对 V0 在无焦点层高置信错误下降)/ `未过门` / `缺数据`(n 不足或 B/C 分层差 > 10pp)。任何一项写不出数字就写 `blocked`,不得写"通过"。
### T4 · 记录
- `docs/tasks/PROGRESS-rectification-jev-intent-classifier-research-v2-20260927.md`:SDK 版本、模型响应 `model`、token 总量与费用、每变体耗时、偏离项。
- `docs/tasks/README.md` 状态板改本单一行。
- 09-19 报告顶部加一行指向本报告(不改旧数)。
## 7. 让步顺序
1. 来源 B 重抽后 `n_有上一轮 < 100` → T3 照跑但只报数,结论写 `缺数据`,不得判"过门"。
2. gold 上界那份跑不了(旧 gold 对不回上一轮)→ 只跑链式,报告注明。
3. Flash + V1 那一列可省(它只是归因辅助),但 Flash V0 生产原样对照不可省。
4. `typesafe-sdk` 0.7.x 与 09-19 所用不兼容 → 固定到 09-19 报告 meta 里的版本,写进 BLOCKED.md。
5. API 限流 / 超时 → 复用 `call_jev_retry` 与缓存,`--offline` 聚合;不得降样本。
## 8. 开工前置命令
```bash
git fetch origin --prune
git worktree add -b codex/jev-intent-v2-20260927 .worktrees/jev-intent-v2-20260927 origin/staging
cd .worktrees/jev-intent-v2-20260927
python3 -m unittest tests.test_jev_intent_research # 基线 11 passed
pip install "typesafe-sdk==<09-19 报告 meta 版本或 0.7.2>" # 只装 SDK,版本写进 PROGRESS
export TYPESAFE_API_KEY=… # 只在 shell,不进任何文件
python3 scripts/research/jev_intent_probe.py --offline # 应能从 09-19 缓存重算旧报告,确认工具链完整
```
来源 B 抽取在执行方本机对 staging 库执行,SQL 见 T1;原文落 `.cache/jev_intent/source_b_v2.jsonl`。
## 9. BUG 编号起点
`docs/BUG_HISTORY.md` 当前最大号 **BUG-1059**;本单若发现研究脚本缺陷从 **BUG-1060** 起编,研究结论本身不编号。
## 10. 验收时 Claude 会做的事
- `origin/<执行分支>` 上跑 `python3 -m unittest tests.test_jev_intent_research`,对照 11 → ≥14。
- 用报告 JSON `rows` 以 `--offline` 重算全部表;抽 3 处数字核对。
- 核对 `git ls-files` 无来源 B 原文;报告错例画像无姓名 / 年份 / 地名。
- 对照 §4 门槛逐条给出 过门 / 未过门 / 缺数据 / blocked。