Files
Jyotisha/docs/tasks/TASK-rectification-jev-intent-classifier-research-fix-20260919.md
T

11 KiB
Raw Blame History

TASK · Jev 意图分类研究修复单:来源 C 必须由真实模型生成与复核(2026-09-19)

  • 基线:origin/staging @ d6fc4fb8(含 fde541c2 研究首版 + d6fc4fb8 DeepSeek Flash 对照)
  • 原单:docs/tasks/TASK-rectification-jev-intent-classifier-research-20260919.md
  • 分支:codex/rectification-jev-intent-research-fix-20260919(从 origin/staging 新建)
  • 性质:研究单修复;不改线上代码;不立 BUG(无线上缺陷)

1. 验收结论(对照原单逐条)

结论 证据
红线 1 · 不改线上 通过 git diff --stat d9722d56..d6fc4fb8 只有 scripts/research/**tests/test_jev_intent_research.pydocs/**.gitignoreBLOCKED.md
红线 2 · key 不进仓库 通过 仓库与报告 JSON grep 无 token;两脚本只读 TYPESAFE_API_KEY / DEEPSEEK_API_KEY 环境变量
红线 3 · 真实消息不提交 通过 来源 B = 0 条,仓库无真实原文
红线 4 · 真值 sha256 固化 通过 三份 sha256 与提交文件实算一致(a8611e75… / 79d53a95… / b4aed856…
红线 5 · 快速门 通过(Python/ 环境缺口(npm test 无 Docker pytest tests/test_jev_intent_research.py 9 passedquick 门 Python 段全绿,npm test 段为既知 27 条无 Docker 失败
T0 来源 A 通过(含偏差说明) 测试文件没有 10 条逐句夹具,执行方按 schema + 两条真实夹具凑 10 条,进度记录已写明
T0 来源 B 环境缺口 执行机(Windows)无 staging 库凭据;代表性检验缺席
T0 来源 C 未通过 见 §2:生成器是模板拼接(agent-template-v1),复核是正则(agent-rule-v1),没有任何模型调用;与原单「让会话模型按人设写回复 + 独立复核」及产品「让 agent 模拟、不怕消耗 token」的授权相悖
T1 题目改写 通过 jev_intent_questions.py 固定 jev-1.13.0CRITERION_MAP 逐条对应提示词、enforce_combo 在代码里保证组合合法
T2 对照跑 通过(Jev/ 偏差(现行) Jev 来源 A+C 各两次;现行分类器用 deepseek-flash 顶生产提示词、来源 C 抽 33%不是线上会话模型(模型目录在数据库,代码里无默认值)
T3 指标与结论 未通过 指标算法本身没问题,但输入语料不成立,「不可接」结论无效;正确结论应为缺数据
T4 记录 通过 PROGRESS / BLOCKED / README 状态行齐全;未立 BUG 正确

2. 事故实证(scripts/research/jev_intent_corpus_build.py @ d6fc4fb8

  1. GENERATOR_NAME = "agent-template-v1"REVIEWER_NAME = "agent-rule-v1"(文件头常量)。全文件无 http / SDK / Agent 调用;import 只有标准库。
  2. 生成器 _choice_answer:每个 answer_class 只有一个 5 词词库(yes = 有的 / 发生了 / 确实有 / 就是那段 / 明显有过),人设靠 DIALECT 4 条前缀、FILLER 4 条填充随机拼接。_collect_answer 同理。
  3. 复核 review_sampleSTOP_RE / ASK_RE / NO_RE / UNSURE_RE / YES_RE / WEAK_RE 六个正则,词表与生成词库完全相同——复核不可能独立,「争议率 8.5%」只是模板与正则的自洽度,不是标签质量。
  4. 语料实测(900 条):去重后只有 489 条;长度 min/中位/P90/max = 1/11/48/76;人设分布 terse 409、dialect_netspeak 215、rambling 189,其余五种人设合计 87 条(<10%);「没这回事」重复 21 次、「中午吃面还是米饭,这跟校正没关系。」重复 17 次。
  5. 标签自相矛盾的例子(均来自报告错例表):C-choice-0016「emmm 感觉一般般就是那段」gold = yes(「一般般」是 weak 语义);C-choice-0006「就是那段」gold = yes(脱离选项文本无法判定);C-choice-0179「没有,……就是那种说不上来特别大但也不是完全没有的感觉」gold = no(后半句是 weak_yes 语义)。Jev 在这些条目上「答错」不能计为 Jev 的错。
  6. 报告 §T3「高置信错误 7.0%」「低置信召回 34%」「answer_class 65%」三个决定结论的数字,全部建立在上述语料之上。

3. 根因

执行方在「本机无会话模型凭据」时,选择用模板+正则顶替 Agent 生成,而不是按让步 4 停在 T0/T1 回报。但 BLOCKED 第三条又写明产品当天就提供了 DeepSeek key(用于对照跑)——同一把 key 足以做生成与复核,凭据缺口在跑 T2 前就已解除,语料却没有重造。

4. 决策记录

  1. 产品 2026-09-19 原话:「能不能让 agent 模拟生时流程来得语料……不怕消耗 token」。这是来源 C 的授权来源,模板拼接不满足;本单据此要求全量重造来源 C。
  2. 生成与复核模型:用执行机上已有凭据的真实对话模型(DeepSeek 或产品另行提供的任一模型),生成与复核可用同一家模型但提示不同、复核看不到标签(原单已允许)。若能用两家不同模型更好,不强求。
  3. 现行分类器对照:生产会话默认模型由数据库模型目录决定,代码里没有;产品在本单开工前告知模型名(或确认 deepseek-flash 就是线上默认)。未告知前,对照继续用 DeepSeek,但报告必须继续标「不是线上会话模型」。
  4. 来源 B:执行机拿不到 staging 库。若产品授权,由 Claude 会话在 staging 主机 docker exec … psql 只读抽取、脱敏后交给执行方本地文件;未授权则维持让步 1(只报数、不判定)。本单不阻塞在来源 B 上。
  5. 原报告结论「不可接」撤回改为「缺数据」docs/tasks/README.md 状态行同步改;不得保留「不可接」字样误导后续拍板。

5. 硬红线

原单 §4 五条全部继续生效,另加:

  1. jev_intent_corpus_build.py 的生成与复核必须各有一次真实模型调用并把模型名、版本、提示原文写进 scripts/research/jev_intent_samples/README.mdGENERATOR_NAME / REVIEWER_NAME 必须是模型标识,不得再出现 template / ruletests/test_jev_intent_research.py 新增断言:构建脚本中不得存在把 answer_class 映射到固定词表的生成函数(检查源码里无 bank = { 式字面量词库),复核函数不得调用 re.search 判标签。
  2. 来源 C 去重后唯一条数 ≥ 810(≥ 90%);单条重复不得超过 5 次;八种人设每种 ≥ 60 条(点选+采集合计)。不满足即重跑,不得进 T2。
  3. 现行分类器对照不得再抽样:来源 C 全量跑一次(自洽率第二次可抽 1/3,与原单让步 2 一致)。

6. 任务分解

F1 · 重写 jev_intent_corpus_build.py 的生成与复核

  • 问题池 question_pool.json 保留(来源是真实引擎,已通过),不重建。
  • 生成:对每道题 × 目标标签 × 人设,调用模型写回复。提示里必须包含:当前题干与四个选项 label(点选层)、目标 intent / answer_class / has_new_dated_event 的自然语言解释(不是枚举名)、人设描述、长度上限、「不得逐字复述选项 label」「不得出现姓名 / 地名 / 单位名」。温度 ≥ 0.8。同一(题, 标签, 人设)组合最多重试 3 次以通过复核。
  • 复核:另一提示,只给题干、选项、用户回复,要求输出 intent / answer_class / has_new_dated_event(结构化 JSON),看不到目标标签;一致者进 simulated.jsonl,不一致进 disputed.jsonl(保留生成标签与复核标签两列)。
  • 争议率按层与按标签写进 README;> 15% 先改生成提示再重跑(最多两轮),仍超则按实际通过条数跑并如实报。
  • 缓存:每次模型调用结果落 .cache/jev_intent/(已 gitignore),脚本可断点续跑。
  • 验收:红线 7 的三项统计由脚本打印并写入 README;simulated.jsonl ≥ 900;三层配额偏差 ≤ 20%;新 sha256 三份写入 READMEassert_no_pii 继续对 20 例 holdout 姓名做拒绝。

F2 · 重跑 T2

  • Jev jev-1.13.0 来源 A + 新来源 C 各两次(原单 T2)。
  • 现行分类器(红线 8)来源 C 全量一次 + 1/3 抽样第二次;模型名按 §4 第 3 条。
  • 验收:.cache/jev_intent/jev_runs.json 与现行 runs 的样本 id 集合与 simulated.jsonl 完全一致(脚本打印校验);429 记 unavailable 计入分母。

F3 · 重出报告

  • docs/research/jev_intent_2026_09_19.md/.json 覆盖重写(保留旧版为 jev_intent_2026_09_19_v1_template.md,文首标「已作废:语料为模板拼接」)。
  • 结论三选一:可接 / 不可接 / 缺数据,附 T3 全表、θ 曲线、错例画像(改写后)。来源 B 仍为 0 时,结论最高只能给到「可接(待真机代表性检验)」或「不可接」,不得写成无条件可接。
  • 验收:报告「模型」一节列出生成模型、复核模型、对照模型三行各自的模型名 / 版本 / 是否线上会话模型。

F4 · 来源 B(条件项)

  • 仅当产品授权且 Claude 会话交付脱敏文件后执行:执行方逐条人工标注 ≥ 30 条,跑代表性检验(原单 T3)。
  • 未授权:BLOCKED 条目保持 open,报告写「代表性检验缺席」。

F5 · 记录

  • PROGRESS-rectification-jev-intent-classifier-research-20260919.md 追加「修复轮」段:三项统计、争议率、两轮提示修改(若有)、token 消耗(生成 / 复核 / Jev / 对照分列)。
  • BLOCKED.md:「无会话模型凭据」条目改写为已解除(生成与复核已用真实模型);来源 B 条目按实际。
  • docs/tasks/README.md:状态行改为本单结论。
  • 不立 BUG。

7. 让步顺序

  1. 争议率两轮提示后仍 > 15%:按实际通过条数跑,配额偏差如实报;不得回退到模板生成补数。
  2. 单条生成三次重试仍不过复核:丢弃该组合,换人设重抽;红线 7 三项仍须满足。
  3. 模型调用限流:退避重试,脚本断点续跑;不得缩小样本。
  4. 现行对照模型名产品未告知:用 DeepSeek 顶,报告标明。
  5. 来源 B 未授权:维持让步 1。

8. 开工前置命令

git fetch origin --prune
git worktree add -b codex/rectification-jev-intent-research-fix-20260919 .worktrees/rectification-jev-intent-research-fix-20260919 origin/staging
cd .worktrees/rectification-jev-intent-research-fix-20260919
export TYPESAFE_API_KEY=DEEPSEEK_API_KEY=# 只在 shell 里,不进文件
.venv/bin/python -m pytest tests/test_jev_intent_research.py -q
grep -n "GENERATOR_NAME\|REVIEWER_NAME\|bank = {" scripts/research/jev_intent_corpus_build.py   # 改前留证

9. BUG 编号

本单不立 BUGdocs/BUG_HISTORY.md 当前最大号 BUG-969,若执行中发现现行分类器的确定性错误再从 BUG-970 起。