From 98118520c9cdd00967501a2ad38f8d1fd4572008 Mon Sep 17 00:00:00 2001 From: zizi Date: Mon, 13 Jul 2026 23:14:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A1=86=E6=9E=B6:=20=E6=94=BE=E9=87=8F?= =?UTF-8?q?=E9=A6=96=E6=97=A5=E4=B8=89=E4=BF=AE=E2=80=94=E2=80=94usage?= =?UTF-8?q?=E5=B5=8C=E5=A5=97dict=E5=90=88=E5=B9=B6=E5=B4=A9=E6=BA=83/?= =?UTF-8?q?=E5=AE=9E=E4=BD=93=E5=9D=8F=E8=A1=8C=E5=AE=BD=E5=AE=B9(?= =?UTF-8?q?=E4=B8=80=E6=9D=A1null=E5=90=8D=E7=A7=B0=E6=9B=BE=E9=99=AA?= =?UTF-8?q?=E8=91=AC=E6=95=B4=E7=AB=A0)/=E7=AA=97=E8=A1=8C=E5=8D=A0?= =?UTF-8?q?=E4=BD=8D=E9=99=B7=E9=98=B1=E5=85=A5SKILL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/skills/parse-book/SKILL.md | 2 ++ .claude/skills/parse-book/scripts/parse_ingest.py | 15 ++++++++++----- .claude/skills/parse-book/scripts/parse_llm.py | 4 +++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.claude/skills/parse-book/SKILL.md b/.claude/skills/parse-book/SKILL.md index 5f874d2..75b7c2c 100644 --- a/.claude/skills/parse-book/SKILL.md +++ b/.claude/skills/parse-book/SKILL.md @@ -56,6 +56,8 @@ disable-model-invocation: true 试拆实测病理档(放量前须知):M3 细纲按比例会写超(治=绝对字数上限+压缩重试);type 一律标 craft 且串型混填(治=合同动态渲染+字段指纹改型+窗级聚类);重跑自噬(治=窗级幂等软删+0 卡不软删,章级判重名录已随 S3 废除);source 偷懒(治=出处由实例机械生成)。parse_ingest 的 patterns 命令是 S3 前章级出卡入口,仅留作回滚保险。 +**窗行陷阱(放量首日实测)**:`--window` 参数变化后重切,旧窗行会按 from_order 占位,新的大窗被「已有大纲跳过」→ 中间章域永远漏出卡(验收期 1–3 章小窗占住 from_order=1,放量 1–34 章大窗被跳过)。**换窗参数重切前必须先删该书全部窗行**(窗行是可再生中间产物;卡挂「窗起」,cards 重出时按窗软删重出)。 + ## 步骤(自底向上,与创作期规划的自顶向下互为镜像) 1. 静态分章:import skill(规则,LLM 不参与); diff --git a/.claude/skills/parse-book/scripts/parse_ingest.py b/.claude/skills/parse-book/scripts/parse_ingest.py index 985e587..1df3856 100644 --- a/.claude/skills/parse-book/scripts/parse_ingest.py +++ b/.claude/skills/parse-book/scripts/parse_ingest.py @@ -235,10 +235,14 @@ def scaffold(work_id, chapter_order, file_): error_message=f"细纲比例超标 {ratio:.1%}>8%") conn.commit() raise click.ClickException(f"细纲比例 {ratio:.1%} 超标(>8%),已记失败退回重解析") - ents = data.get("实体") or [] - for e in ents: - if not e.get("名称") or not e.get("型"): - raise click.ClickException(f"实体缺 名称/型: {e}") + # 实体坏行宽容(放量实测:M3 偶发报 名称=null 的实体,一条坏行不该陪葬整章—— + # 细纲/线索/其余实体全丢且任务无失败记录,窗切分会报缺章) + ents, n_bad_ent = [], 0 + for e in data.get("实体") or []: + if e.get("名称") and e.get("型"): + ents.append(e) + else: + n_bad_ent += 1 # 范式候选线索(B4-S3):候选层宽容处置——坏行丢弃计数,不整批拒 hints, n_bad = [], 0 for h in data.get("线索") or []: @@ -257,7 +261,8 @@ def scaffold(work_id, chapter_order, file_): set_task(conn, work_id, ch_id, scaffold_status="done", error_message=None) conn.commit() click.echo(f"scaffold✓ work={work_id} ch#{chapter_order}: 细纲{len(outline)}字({ratio:.1%}) " - f"实体{len(ents)} 线索{len(hints)}" + (f"(丢弃坏行{n_bad})" if n_bad else "")) + f"实体{len(ents)}" + (f"(弃坏行{n_bad_ent})" if n_bad_ent else "") + + f" 线索{len(hints)}" + (f"(弃坏行{n_bad})" if n_bad else "")) @cli.command() diff --git a/.claude/skills/parse-book/scripts/parse_llm.py b/.claude/skills/parse-book/scripts/parse_llm.py index b5c1730..8fd9233 100644 --- a/.claude/skills/parse-book/scripts/parse_llm.py +++ b/.claude/skills/parse-book/scripts/parse_llm.py @@ -155,7 +155,9 @@ def m3_json(prompt, model, need_keys, system=IDENTITY): if retry == 0: content, u2 = chat(prompt + f"\n\n【重试提示】上次输出无法解析({err}),请严格按输出规则只输出一个 JSON 对象。", model=model, system=system) - usage = {k: usage.get(k, 0) + u2.get(k, 0) for k in set(usage) | set(u2)} + # 只合并数值键:上游 usage 带嵌套 dict(如 *_tokens_details),dict+dict 会崩(放量实测) + usage = {k: usage.get(k, 0) + u2.get(k, 0) for k in set(usage) | set(u2) + if isinstance(usage.get(k, 0), (int, float)) and isinstance(u2.get(k, 0), (int, float))} raise RuntimeError(f"JSON 形状重试仍失败: {err}")