From 9f90f399accf94fde20ab15889b6461cadbcc88f Mon Sep 17 00:00:00 2001 From: zizi Date: Sat, 18 Jul 2026 03:35:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A1=86=E6=9E=B6:=20=E8=AF=AD=E4=B9=89?= =?UTF-8?q?=E5=88=A4=E9=87=8D=E5=B0=8F=E6=A0=B7=E6=A0=A1=E5=87=86=E2=80=94?= =?UTF-8?q?=E2=80=94=E9=98=88=E5=80=BC0.78=E2=86=920.60=E5=AE=9E=E6=B5=8B?= =?UTF-8?q?=E5=AE=9A+=E7=BB=88=E5=88=A4=E8=BF=91=E9=82=BB=E5=B8=A6?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E8=AF=81=E6=8D=AE+=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E4=BA=92=E5=90=AB=E5=88=A4=E6=8D=AE;=20=E6=89=B99c=E6=94=B6?= =?UTF-8?q?=E5=B0=BE=E5=B0=8F=E6=A0=B7=E8=AE=B0=E5=BD=95=E5=85=A5=E9=94=9A?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parse-book/scripts/parse_upgrade.py | 31 ++++++++++++------- .../scripts/test_parse_upgrade_offline.py | 8 +++++ docs/2026-07-16-升格卡改造设计.md | 6 ++-- docs/2026-07-16-批9c-收官与优化方案.md | 6 ++++ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/.claude/skills/parse-book/scripts/parse_upgrade.py b/.claude/skills/parse-book/scripts/parse_upgrade.py index 74e4955..2b5b097 100644 --- a/.claude/skills/parse-book/scripts/parse_upgrade.py +++ b/.claude/skills/parse-book/scripts/parse_upgrade.py @@ -63,7 +63,11 @@ MILESTONE_FIELDS = {"演变历程"} # 生命周期枚举(设计稿 §4.2):每条里程碑「周期」的取值域。 LIFECYCLE = ("登场", "成长", "高光", "退场", "结局") # 语义判重(P1,设计稿 §8.2):召回同书近邻相似度 ≥ 此阈值才交 M3 终判。 -DEDUP_SIM_THRESHOLD = 0.78 +# 0.78→0.60(2026-07-18 补3洞零落库小样实测校准):改名场景(洞① 病例)查询侧是初观察薄快照、 +# 存储侧是长成的厚卡,文本不对称压低余弦——同实体改名对实测 0.63-0.66("联邦生物机甲技术"vs +# 卡「生物机甲」0.6565),0.78 永不触发语义层;无关对实测 ≤0.51,0.60 落在分离带内留边距。 +# 放宽只增终判候选量,并卡仍须 M3 终判"同型同一实体"才发生(跨型/无关由终判把关)。 +DEDUP_SIM_THRESHOLD = 0.60 CHAP_BIG = 10 ** 9 # 章号缺失/待人工的里程碑,排序时排到最后 STEP_MAX = 80 # 里程碑「台阶」机械字数上限(洞③):提示词目标 ≤40 字,机械上限 80,双层防跑飞长文 @@ -785,35 +789,40 @@ def _entity_embed_text(ent): def recall_neighbors(conn, vec, work_id, top=6): """用**现成向量**在 example_knowledge_embedding 召回同书 ≥阈值 近邻卡。 - 返回 [(did, 型, 名称, 摘要, 相似度)…] 按相似度降序、过滤 <阈值。 + 返回 [(did, 型, 名称, 摘要, 字段摘选, 相似度)…] 按相似度降序、过滤 <阈值。 + 字段摘选(2026-07-18 小样校准):终判证据不能只有一句话摘要——实测 M3 在"改名候选 vs 厚卡"上 + 因近邻证据太薄保守判无关(境界阶梯/力量来源这类字段才是同一实体的强证据),故召回时带出 + 字段 JSON 截断 300 字随近邻进终判 prompt(与候选侧字段 600 字对称)。 三段式连接(洞①核心红线):嵌入已在预判段批量算好并挪出——本函数只跑向量召回 SQL、不再发嵌入 HTTP, 调用方用短连接查完即关(不再沿用窗内长连接跨 LLM/嵌入调用存活,这正是本次要治的连接红线)。 嵌入表无同书向量(试跑期未 embed)时返回 []——优雅降级,判重回退纯机械,绝不阻断主流程。""" qvec = json.dumps(vec) rows = conn.execute( """SELECT d.id, d.draft_payload->>'type', d.draft_payload->>'名称', - d.draft_payload->>'一句话摘要', 1 - (e.embedding <=> %s::vector) AS score + d.draft_payload->>'一句话摘要', d.draft_payload->>'字段', + 1 - (e.embedding <=> %s::vector) AS score FROM example_knowledge_embedding e JOIN muse_knowledge_draft d ON d.id = e.draft_id WHERE e.tenant_id=%s AND e.deleted=FALSE AND d.deleted=FALSE AND d.source_type=%s AND d.work_id=%s ORDER BY score DESC LIMIT %s""", (qvec, TENANT, SOURCE_TYPE, work_id, top)).fetchall() - return [(r[0], r[1], r[2], r[3], float(r[4])) for r in rows - if float(r[4]) >= DEDUP_SIM_THRESHOLD] + return [(r[0], r[1], r[2], r[3], (r[4] or "")[:300], float(r[5])) for r in rows + if float(r[5]) >= DEDUP_SIM_THRESHOLD] def dedup_judge_prompt(ent, neighbors): - """M3 终判 prompt:候选新实体 vs 每个同书近邻,判 同一实体 / 前身 / 后继 / 无关。""" - nb = "\n".join(f"{i + 1}. 卡号{did}|{t}|{nm}|{brief or ''}" - for i, (did, t, nm, brief, _s) in enumerate(neighbors)) + """M3 终判 prompt:候选新实体 vs 每个同书近邻,判 同一实体 / 前身 / 后继 / 无关。 + 近邻带字段摘选(小样校准):只给一句话摘要时模型证据不足会保守判无关,字段是强证据。""" + nb = "\n".join(f"{i + 1}. 卡号{did}|{t}|{nm}|{brief or ''}|字段摘选:{fs or '(无)'}" + for i, (did, t, nm, brief, fs, _s) in enumerate(neighbors)) return f"""【功能指令(parse-book 作品面升格·语义判重终判)】 下面是一个"候选新实体"和若干"同书既有卡"(向量召回的近邻)。逐一判断候选与每张近邻卡的关系,四选一: - 同一实体:同一对象的改名/化名/不同侧面(如"影杀者"与"IV代纯机械机甲·影杀者")——**仅同型可判**。 - 前身:候选是该近邻卡的上一代/来源(同一条进化链的相邻代际,如"铁头(一代)"之于"铁卫(二代)")。 - 后继:候选是该近邻卡的下一代/继承者。 - 无关:只是题材相近,各自独立。 -判据:看名称/摘要/字段是否指向同一对象或同一条演变链;**跨型(如具体机甲 item vs 整套体系 power_system)绝不判同一实体,最多判前身/后继**——一整套体系不等于其中一台机体。 +判据:看名称/摘要/字段是否指向同一对象或同一条演变链;**同型且名称互含(如"生物机甲"与"联邦生物机甲技术")通常是同一实体的简称/全称,除非字段证据明确指向不同对象**;名称不互含但摘要/字段描述同一套力量来源、同一条境界阶梯、同一批代表单位的,也应判同一实体(改名不改实质);**跨型(如具体机甲 item vs 整套体系 power_system)绝不判同一实体,最多判前身/后继**——一整套体系不等于其中一台机体。 【候选新实体】 型={ent.get("型", "")}|名称={ent.get("名称", "")}|摘要={ent.get("一句话摘要", "")} @@ -841,8 +850,8 @@ def semantic_dedup(ent, neighbors, call): data, _ = call(dedup_judge_prompt(ent, neighbors), ("判定",)) except (SensitiveHardStop, RuntimeError): return "new", None - nb_type = {did: t for did, t, _, _, _ in neighbors} - nb_name = {did: nm for did, _, nm, _, _ in neighbors} + nb_type = {did: t for did, t, _, _, _, _ in neighbors} + nb_name = {did: nm for did, _, nm, _, _, _ in neighbors} ent_type = ent.get("型", "") chain = [] for j in [x for x in (data.get("判定") or []) if isinstance(x, dict)]: diff --git a/.claude/skills/parse-book/scripts/test_parse_upgrade_offline.py b/.claude/skills/parse-book/scripts/test_parse_upgrade_offline.py index 0cf28aa..9bae2ed 100644 --- a/.claude/skills/parse-book/scripts/test_parse_upgrade_offline.py +++ b/.claude/skills/parse-book/scripts/test_parse_upgrade_offline.py @@ -179,6 +179,14 @@ def test_prompts_disciplines(): [(10, {"名称": "张三"}), (11, {"名称": "李四"})], []) check("relation-构造器可渲染", "人物关系增量" in rel) + # 判重终判 prompt(小样校准后):近邻六元组带字段摘选进证据 + 名称互含判据 + nbs = [(6223, "power_system", "生物机甲", "机甲体系", '{"境界阶梯":"IV代→V代"}', 0.66)] + jp = pu.dedup_judge_prompt({"型": "power_system", "名称": "联邦生物机甲技术", + "一句话摘要": "s", "字段": {}}, nbs) + check("judge-近邻字段摘选入证据", "字段摘选:" in jp and "境界阶梯" in jp) + check("judge-名称互含判据", "同型且名称互含" in jp) + check("judge-跨型禁判同一实体仍在", "绝不判同一实体" in jp) + if __name__ == "__main__": for fn in (test_classify_new_name, test_debut_milestone, test_clean_milestone_guard, diff --git a/docs/2026-07-16-升格卡改造设计.md b/docs/2026-07-16-升格卡改造设计.md index 2a4d00f..7ace05f 100644 --- a/docs/2026-07-16-升格卡改造设计.md +++ b/docs/2026-07-16-升格卡改造设计.md @@ -65,7 +65,7 @@ flowchart TB end subgraph P1["第二步 P1:串链 + 语义判重(治病根 3、4)"] B1["加『前身/后继』链接字段
把碎卡串成一条进化链"] - B2["判重打开语义近邻(≥0.78)
+ M3 终判 → 治改名/跨型漏并"] + B2["判重打开语义近邻(≥0.60·小样实测校准)
+ M3 终判 → 治改名/跨型漏并"] end subgraph FIX["两点硬性细化(贯穿全程)"] C1["① 里程碑用真实章号索引
绝不用运行时窗号 [窗N]"] @@ -231,7 +231,7 @@ flowchart TB 在判重步,除现有的名字精确匹配/子串外,新增(就是打开 v6 已设计、暂时关着的那级): -1. 对候选新实体算向量(走 `embed` skill),用 `search` 召回**同书同型**相似度 ≥ 0.78 的近邻卡。 +1. 对候选新实体算向量(走 `embed` skill),用 `search` 召回**同书同型**相似度 ≥ 0.60 的近邻卡(原定 0.78,2026-07-18 零落库小样实测校准:同实体改名对余弦 0.63-0.66、不同体系对 ≤0.58,0.78 永不触发语义层;依据详见 parse_upgrade.py 阈值注释)。 2. 召回的近邻交给 M3 终判(走 `parse_llm.py` 的 `m3_json` 入口,构造"这两张卡是不是同一实体 / 是不是前身后继关系"的判断),判定三选一:**同一实体**(并卡)/ **前身后继**(不并卡但串链)/ **无关**(各自立卡)。 这样"影杀者"和"IV 代纯机械机甲·影杀者"这种改名、以及跨型指代同一条线的,都能被语义召回并正确处理。 @@ -246,7 +246,7 @@ flowchart TB 1. **条目从字符串变对象,合并逻辑改动面不小**。`parse_upgrade.py` 现有一大套针对字符串条目的守卫(剥前缀、剥尾残、拦垃圾、拆粘连、窗序归位),全要跟着改造成处理里程碑对象;存量卡还是字符串,迁移要兼容。→ 缓解:分两步落,先补字段和提示词(新卡受益),再做存量迁移;对象结构压到三字段降低崩坏面。 2. **模型抽结构化对象比抽字符串更容易格式崩**。→ 缓解:三字段极简;保留降级——抽不出完整对象就退化成"章号 + 一句话"最小对象,别整条丢。 -3. **语义判重增加调用量和跨型误并风险**。→ 缓解:0.78 阈值 + 同型才自动并 + 跨型仅提示;判重近邻可像 v6 说的那样批量做、不逐条烧。 +3. **语义判重增加调用量和跨型误并风险**。→ 缓解:0.60 阈值(实测校准) + 同型才自动并 + 跨型仅提示;判重近邻可像 v6 说的那样批量做、不逐条烧。 4. **存量迁移精度损失**:无内嵌章号的条目只能靠窗映射到 12 章宽区间。→ 接受为存量固有局限,新卡不受影响。 5. **改 schema 后必须重跑种子**,否则库里字段合同和 YAML 不一致,抽取会按旧合同把新字段裁掉。→ 实施清单里钉死"改 YAML 后重跑 `seed_schemas.py`"这一步。 diff --git a/docs/2026-07-16-批9c-收官与优化方案.md b/docs/2026-07-16-批9c-收官与优化方案.md index 5319742..af1c077 100644 --- a/docs/2026-07-16-批9c-收官与优化方案.md +++ b/docs/2026-07-16-批9c-收官与优化方案.md @@ -92,3 +92,9 @@ ## 批9d 插入记录(2026-07-17/18) 批9c 全量重抽启动前,创始人插入方向级任务:第一性原理分析各类卡是否符合要求,抽最重要的点完善 SoT。已完成并落 design-docs(提交 2124a793):新增专题-07(知识消费契约与质量闭环,"以用定卡")+ 七册配套拍板(含 aiContext 值域升级、参照作品面、双层拍板、purpose 枚举统一)。分析证据链见 `2026-07-17-卡的第一性原理与知识效用闭环.md`。**批9c 收尾已由创始人下"继续"口令启动(2026-07-18),compact 恢复后从这里接**:下一步 = **派 fable5 实现子代理补 3 洞**(尚未派出;任务清单 #9-12 已建)。子代理提示词要点:改 parse_upgrade.py——②观察/更新提示词令实体首现必立"登场"里程碑且归并不丢;③体系卡演变历程只收体系级变化、单位/个体事件归各自实体卡、台阶一句话限长;①语义判重连接改读-算-写三段式(opus 审计点名:现持窗级连接跨嵌入与 M3 调用)+ 新卡/更新卡写段增量嵌入落 example_knowledge_embedding(重抽期间判重才有向量可召回)+ 接入重抽流程。红线:三段式连接、软删、LLM 走 chat_governed(M3)、绝对章号、中文注释、最小改动面、不跑库写。之后顺序:主代理逐段核验 → 零落库小样验 3 洞(深空样窗:生物机甲/铁头判同归线、登场里程碑在、体系卡无单位事件)→ 呈报样张等创始人放行全量。**创始人 2026-07-18 拍板通过重抽后路线:批10 = 消费最小闭环 + 回放评测首跑**——顺序:①升格卡向量落库(补齐可命中)→②统一读取器 read-context 从设计桩变实(8587 张卡第一次被创作流消费)→③单书规划线回放首跑(冻结前 N 章知识推演下一台阶、对照原书评分,验收对齐专题-07 §4/§7);不再继续扩书拆卡。 + +## 批9c 收尾执行记录(2026-07-18,补3洞→小样全过,待创始人放行全量) + +- **补洞实现(fable5 子代理)+ 主代理逐段核验 ✅**:`parse_upgrade.py` 每窗重构为 读1(短连)→观察(无连)→预判段(嵌入/召回/终判无长连)→写(窗事务)→嵌段(commit后三段式增量嵌入落 example_knowledge_embedding,软删旧活行+upsert);机械判重判据抽 `_classify_new_name` 纯函数预判/写段共用;四条归并路径换 `_merge_material`(演变历程完整不截);`new_card` 接 `_debut_milestone` 登场机械兜底;观察/更新提示词加登场硬约束+体系级纪律+台阶≤40字;`_clean_milestone` 加 80 字硬闸(主代理修复:截断必须放在内嵌章号抽取与周期推断**之后**,防截丢兜底线索);`build_embed_text` 补 type 键型修正(升格卡型认出)。离线自测 43 项全绿(`test_parse_upgrade_offline.py`)。提交 `2173c8f` + 校准提交。 +- **零落库小样 ✅(深空窗35-37,观察3+终判若干+嵌入2批,≈$0.15,零卡表写入)**:报告 `/tmp/muse_upgrade_smoke3_report.txt` + probe4。洞② 登场:172 张适用型新卡 100% 有登场(模型自给 114+机械兜底 58,双保险成立)。洞③:299 条台阶 0 条超 80 字硬闸(>40 软目标 29 条);体系卡「联邦生物机甲技术」2 条里程碑均体系级、当前态字段干净。洞①:**阈值 0.78 实测证伪**——同实体改名对余弦仅 0.63-0.66("联邦生物机甲技术"vs 卡6223 = 0.6565)永不触发语义层,不同体系对 ≤0.58 → **阈值校准 0.78→0.60**;终判证据不对称修复(recall_neighbors 近邻带字段摘选 300 字入终判 prompt + 判据补"同型名称互含≈简称全称""改名不改实质")。校准后五探针全对:互含改名×2 → merge 6223;**非互含改名**("卡依斯反应驱动战械体系",语义层真正要接的残余缺口,机械子串层接不住)→ 0.6128 过阈 → merge 6223;反向安全(帝国4代纯机械体系)→ 0.576 不过阈 → new(误并方向守住);铁头 → 0.9456 → merge 1154;跨型全部未并。边距诚实说明:非互含 0.613 vs 反向 0.576 分离带窄,第二道守门=终判 M3(带字段证据)+ 同型才并 + 别名审计行(verdict_by='semantic')可回溯。 +- **待办=呈报创始人放行全量重抽(任务#12)**。全量执行时注意本文档上方"全量重抽的管线坑"三条(清串行状态表 / cid 冲突吞卡 / 勿用 --redo-window 破串行),跑法:`run --work-id N --semantic-dedup` 逐书串行。