Article
2026-08-12-tasuki-keifu-agent-批处理优化记录
tasuki-keifu-agent 批处理优化记录
这份文档记录真实 batch 运行后发现的问题和对应优化。后续每次有代表性运行结果时,按 Case 继续追加。
Case 1:首轮小批量运行被 profile 缺失占满
运行结果
- batchId:
03a417e1-ebe3-4a9b-9aea-5c52b67f2ea4 - 模式:dry-run
- 人数:5
- 失败:0
- 归一化合并:0
5 个 person 都只命中 profile_coverage_missing_fields,缺少出生日期、出身地、国籍和日文读音。
问题
- profile 缺失是当前数据导入的常见状态,不等同于已有数据错误。
- 原规则会把缺失 3 个以上字段标为
high,导致 batch 结果被低价值的缺失检查淹没。 - 原规则会为每个 profile 缺失生成
backfill_profile_fields,即使没有可靠来源可以补。 - 原 batch 会把这类停放结果当作最终治理,之后业务数据不更新时不会再次被选中。
优化
profile_coverage_missing_fields改为low,定义为观察项。- 新增
research_profile_wikipedia节点:- 只在 profile 有缺失时运行。
- 只允许 Wikipedia 作为来源。
- 只返回 Wikipedia 明确支持的缺失字段,不猜测、不扩大搜索范围。
- Wikipedia 未找到或不可用时:保留 profile 缺失 finding,但不生成 action。
- Wikipedia 找到明确字段时:追加
profile_wikipedia_data_availablefinding,才生成backfill_profile_from_wikipediaaction。 - 只有 profile 缺失的治理结果不计入 batch 的最终治理时间,后续调整 profile 策略或接入写入规则后仍可再次被捞取。
追加修正:Wikipedia 重定向安全边界
直接调用 MediaWiki API 后,需要防止同名消歧义、缺页或重定向到不同姓名页面时误补 profile。sato-aoi 的实际日文名是 佐藤碧,该页面命中属于合法结果。
因此补充规则:
- agent 使用 MediaWiki API,不再依赖 LLM web search。
- 网络出口优先使用标准代理环境变量;macOS 本地自动读取系统代理,因此会跟随 Clash Plus 的设置变化,不写死端口。
- API 最终页面标题必须与输入日文名在去空格、全半角统一后完全一致。
- 命中消歧义页、缺页或跳转到不同姓名页面时,一律不补全字段。
验证重点
- 只有 profile 缺失、且 Wikipedia 无可用资料时,不应出现
high风险或held。 - Wikipedia 查到明确字段时会生成 profile 回填动作;在 profile 写执行器接入前,预期为
medium / held,且不写入业务库。 - 无 Wikipedia 资料时 action bundle 应为空。
- 有其他 finding 的 person 不受 profile 观察项影响。
- 后续 batch 仍能重新选中仅 profile 缺失的 person。
Case 2:将内部异常从“只报告”收敛为保守写动作
问题
membership 和 PB 的内部异常此前只会生成 review action,执行器无法处理;即使数据已明显不可信,也会继续保留为普通 pending 状态。
优化
- Wikipedia 节点在一次单人治理中同时读取 profile 与 PB;页面标题不严格匹配、消歧义、缺页或解析不明确时不写入。
- Wikipedia profile 只回填空字段;Wikipedia PB 按项目新增或更新,并保留来源与审计。
- membership 时间线异常不猜测正确组织或日期,统一标记相关记录为
conflicting。 - 未被 Wikipedia 明确解决的 PB 冲突同样标记为
conflicting。 - 所有低风险 action 都在执行前重新锁定目标记录,并写入业务
AuditLog;身份不确定的归一化仍按整组高风险停放。
验证
- membership 异常样本
鬼塚翔太已生成mark_memberships_conflicting,风险为low / planned。 - PB 冲突样本
中野翔太已生成mark_personal_bests_conflicting,风险为low / planned。 limit=3的真实 batch dry-run 完成 3 人、失败 0、停放 0;该批未命中新动作。- 当前 macOS 系统代理关闭时,Wikipedia 查询会返回
unavailable并保留其他治理流程;不会生成猜测性写动作。
Case 3:真实写动作样本暴露解析与幂等边界
运行结果
- 单人样本
阿部陽樹:Wikipedia 明确返回国籍和 6 项 PB,生成 PB 写入与 profile 回填两个低风险动作。 - 单人样本
中野翔太:已有 3 条 PB 已是conflicting,保留 findings,但不再生成重复的冲突标记动作。 - 单人样本
木付琳:4 条当前企业队 membership 同时有效,聚合为 1 个mark_memberships_conflicting动作。
问题
- Wikipedia 的国籍字段可能是
{{JPN}}这类模板;如果按普通文本保存,会把模板语法写进业务数据。 - 已标记
conflicting的 PB 每次治理都重复生成写动作,会制造无效审计记录,也浪费批处理配额。 - 同一人的多个 membership 异常属于同一组治理意图,应聚合成一个写动作,而不是按 finding 重复写入。
优化
- 解析 Wikipedia 国籍时识别
{{JPN}}、{{国籍|JPN}}、{{flagicon|JPN}},统一提取为JPN。 - 只有重复 PB 等“尚未处置”的内部冲突才生成
mark_personal_bests_conflicting;已经是conflicting的记录只保留 finding。 - membership 冲突按 person 聚合成一个动作;动作执行顺序固定为:归一化、membership、PB、profile。
- 更新 smoke 样本,使其覆盖“membership 聚合写入”和“已冲突 PB 不重复写入”两个回归边界。
验证
nakano-shota诊断结果:3 条高优先级 PB findings,action bundle 为空。abe-haruki诊断结果:动作顺序为 Wikipedia PB 写入,再回填国籍;{{JPN}}被规范为JPN。kitsuki-rin诊断结果:4 条异常 membership 合并为 1 个低风险 planned action。
Case 4:小批量候选仍被低价值观察项占据
运行结果
- batchId:
2a862684-ef1c-4ac1-b348-96ccfa032e46 - 模式:dry-run
- 人数:10
- 完成:10
- 失败:0
- 停放:0
- 写动作:0
这 10 人均完成诊断,但都没有可安全执行的动作,主要是 profile 缺失且 Wikipedia 无可用补充。
问题
当前 batch 按业务更新时间从早到晚选人。对于首次大范围治理,历史较早、且只有 profile 观察项的人会持续排在前面,导致小批量很难覆盖 membership、PB 或归一化等更有治理价值的样本。
决策与优化
采用“已知异常优先”策略。是否需要重新治理仍由业务侧最大更新时间与最近治理时间决定;只有同一轮候选的排序发生变化:
- 归一化精确重名。
- 当前多重 membership。
- 尚未标记
conflicting的重复 PB。 - 其他 person,包括仅 profile 缺失的人。
这只使用业务库能够直接确认的规则信号,不把 LLM 判断带入候选 SQL。低价值 profile 观察项不会消失,只是不会继续挤占小批量的前排。
Case 5:归一化优先后,同一重名组重复占据批次
运行结果
- batchId:
2c6ac43d-d993-49cf-ad69-182c77b24175 - 模式:dry-run
- 人数:5
- 完成:0
- 停放:5
- 失败:0
新的排序正确把 5 个高风险归一化候选排到前面。但其中 桑原大地 的多条记录属于同一个精确重名组,逐条进入 graph 后都只会得到同一组的归一化 findings。
优化
对于优先级最高的精确重名候选,以标准化日文名作为组键,每个 batch 只选该组的一条 person。单人 graph 的归一化节点已经会回查并带出同组候选,因此这不会丢失判断信息;它只是避免同一批重复调用 LLM 和重复生成高风险停放记录。
membership、PB 和普通 person 仍以单个 person 为粒度,不做跨人去重。
Case 6:已治理候选被过滤后,浅窗口会错误得到空 batch
候选是否需要重新治理要在 agent 库中判断。原实现只从业务库取 limit * 4 个候选;当前排优先候选刚完成治理后,它们会被过滤掉,但窗口之外仍有未治理 person,最终可能得到空 batch。
已将候选扫描窗口扩大到 limit * 20,最多 400 人。优先级和重新治理规则不变,只确保过滤后仍能填满合理的小批量。
Case 7:首条真实治理写入
运行结果
- batchId:
3e557a1a-f295-4e88-882f-2e4a2d567466 - 模式:单人受控执行,
dryRun=false - 选手:
木付琳(kitsuki-rin) - 动作:
mark_memberships_conflicting - 结果:成功将 4 条同时有效的企业队 membership 从
pending标记为conflicting
agent 审计侧记录该 action 为 succeeded;业务库按每条 membership 写入了 4 条 AuditLog,没有删除记录、没有猜测正确组织或日期。
发现与优化
首次真实写入发现:原生 SQL 的 UPDATE 不会自动触发 Prisma 的 @updatedAt 语义,状态已经变更但 updatedAt 仍停在旧时间,会使后续 batch 的“业务最后更新时间”失真。
已统一为执行器的 Person、Membership、PersonalBest 更新语句显式写入 updatedAt = NOW(),并校正本次 4 条 membership 的更新时间。
写后复跑还确认:检测 finding 会保留,便于看到历史异常;但当相关 membership 已全部是 conflicting 时,action plan 不再重复生成冲突标记动作,不再依赖执行器末端的幂等跳过。
Case 8:同读音异汉字不应阻塞事实回填
阿部陽樹 因候选 阿部陽葵 读音相同,被归一化节点错误升级为身份不确定,导致 Wikipedia 已明确支持的 PB 和国籍动作被整组停放。
归一化规则调整为:汉字日文名必须在规范化后完全一致,才进入候选与 LLM 判断;读音只作为同汉字名候选的辅助证据。仅同读音、汉字不同默认视为不同 person,不再产生 name_identity_uncertain,也不阻塞 profile/PB 的低风险事实写入。
验证
佐藤碧已从同名 Wikipedia 页面回填出生日期1997-09-25与出身地大分県。阿部陽樹已从同名 Wikipedia 页面回填国籍JPN,并新增或校验 6 项 PB;读音相同的阿部陽葵不再阻塞这组事实写入。