看板升级: GT v0.5.0(20期叙事结构全覆盖) + schema加字段方案 + git清理

- ground-truth v0.5.0: 补完10期narrative_structure标注(MiMo跑批+制片人审定)
- summarize.py: 修复无标注期次格式化崩溃
- 003_add_ai_labels.sql: episodes表加7列(6打标+1置信度)迁移文件
- episode.py: Model同步加7个Optional字段
- CLAUDE.md: 项目主控文件入库
- doco/deliverables: 20期终版文稿md入库
- doco/programs: 中间产物从git移除(本地保留), .gitignore统一管理
- note/寄存条: 两个子项目寄存条入库
- .gitignore: 补充doco中间产物/Excel锁文件/临时文件规则

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
simonkoson
2026-06-26 09:14:29 +08:00
parent 81b331d6d7
commit d91c20a126
91 changed files with 4148 additions and 20891 deletions
+13 -13
View File
@@ -1,10 +1,10 @@
{
"version": "v0.4.2",
"locked_at": "2026-06-25",
"version": "v0.5.0",
"locked_at": "2026-06-26",
"locked_by": "制片人刘通 + Opus 顾问(逐期审定)",
"fields_covered": ["narrative_structure", "opening_hook", "program_format", "equipment_domain", "scene_tags", "tech_tags"],
"fields_reserved": [],
"changelog": "v0.1→v0.2: ep10/ep15 从并列改主线演进。v0.2→v0.2.1: ep12 经三家模型独立一致+制片人复审改为并列结构。v0.2.1→v0.3.0: 预留4分类字段骨架(null/[])。v0.3.0→v0.4.0: 期号重映射(旧ep3-15→新ep001-020按播出日期排序),从10期扩展至20期,4分类字段(program_format/equipment_domain/scene_tags/tech_tags)全部填入,制片人逐期审定。新增10期暂无narrative_structure/opening_hook标注(待Prompt 2/3跑批后补)。v0.4.0→v0.4.1: ep008马年装备图鉴补标跨域(制片人确认遗漏)。v0.4.1→v0.4.2: 新增10期opening_hook标注(制片人逐期审定,含钩子分析)ep004强/ep007中/ep009中/ep014中/ep015中/ep016中/ep017中/ep018强/ep019强/ep020中。",
"changelog": "v0.1→v0.2: ep10/ep15 从并列改主线演进。v0.2→v0.2.1: ep12 经三家模型独立一致+制片人复审改为并列结构。v0.2.1→v0.3.0: 预留4分类字段骨架(null/[])。v0.3.0→v0.4.0: 期号重映射(旧ep3-15→新ep001-020按播出日期排序),从10期扩展至20期,4分类字段(program_format/equipment_domain/scene_tags/tech_tags)全部填入,制片人逐期审定。新增10期暂无narrative_structure/opening_hook标注(待Prompt 2/3跑批后补)。v0.4.0→v0.4.1: ep008马年装备图鉴补标跨域(制片人确认遗漏)。v0.4.1→v0.4.2: 新增10期opening_hook标注(制片人逐期审定,含钩子分析)ep004强/ep007中/ep009中/ep014中/ep015中/ep016中/ep017中/ep018强/ep019强/ep020中。v0.4.2→v0.5.0: 新增10期narrative_structure标注(MiMo跑批+制片人审定)ep004并列/ep007并列/ep009并列/ep014并列/ep015主线演进/ep016并列/ep017主线演进/ep018并列/ep019并列(AI判主线演进,制片人改)/ep020并列。20期6字段全覆盖。",
"ep_number_migration": "v0.3.0旧编号→v0.4.0新编号: ep15→001, ep4→002, ep13→003, 新增→004, ep3→005, ep5→006, 新增→007, ep7→008, 新增→009, ep10→010, ep11→011, ep12→012, ep14→013, 新增→014, 新增→015, 新增→016, 新增→017, 新增→018, 新增→019, 新增→020",
"episodes": [
{
@@ -44,7 +44,7 @@
"ep": 4,
"title": "枪王对决",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "强",
"program_format": "人物牵引",
"equipment_domain": ["轻武器"],
@@ -77,7 +77,7 @@
"ep": 7,
"title": "大国巨舰反差",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "中",
"program_format": "横切类比",
"equipment_domain": ["海军舰船"],
@@ -99,7 +99,7 @@
"ep": 9,
"title": "重金造神器",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "中",
"program_format": "横切类比",
"equipment_domain": ["海军舰船", "陆战装备", "航空航天", "跨域"],
@@ -154,7 +154,7 @@
"ep": 14,
"title": "启程远航",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "中",
"program_format": "装备深解",
"equipment_domain": ["海军舰船"],
@@ -165,7 +165,7 @@
"ep": 15,
"title": "舰炮暴力美学",
"share": null,
"narrative_structure": null,
"narrative_structure": "主线演进",
"opening_hook": "中",
"program_format": "历史纵深",
"equipment_domain": ["海军舰船"],
@@ -176,7 +176,7 @@
"ep": 16,
"title": "无人舰艇",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "中",
"program_format": "前沿科技",
"equipment_domain": ["海军舰船"],
@@ -187,7 +187,7 @@
"ep": 17,
"title": "逆袭的鸭翼",
"share": null,
"narrative_structure": null,
"narrative_structure": "主线演进",
"opening_hook": "中",
"program_format": "横切类比",
"equipment_domain": ["航空航天"],
@@ -198,7 +198,7 @@
"ep": 18,
"title": "机枪双雄",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "强",
"program_format": "人物牵引",
"equipment_domain": ["轻武器"],
@@ -209,7 +209,7 @@
"ep": 19,
"title": "玩具总动员",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "强",
"program_format": "横切类比",
"equipment_domain": ["陆战装备", "航空航天", "海军舰船", "跨域"],
@@ -220,7 +220,7 @@
"ep": 20,
"title": "武器颜值洼地",
"share": null,
"narrative_structure": null,
"narrative_structure": "并列结构",
"opening_hook": "中",
"program_format": "横切类比",
"equipment_domain": ["航空航天", "海军舰船"],
Binary file not shown.
+20 -11
View File
@@ -94,11 +94,14 @@ def run(model, field="narrative"):
hit = pred_val == gt_val if pred_val is not None else False
rows.append({"ep": ep, "title": title, "gt": gt_val, "pred": pred_val or "解析失败", "hit": hit, "conf": conf})
elif field == "narrative":
gt_val = gt.get("narrative_structure", "?")
gt_val = gt.get("narrative_structure")
pred_val = result.get("narrative_structure") if result else None
conf = result.get("confidence", "?") if result else "?"
hit = pred_val == gt_val if pred_val is not None else False
rows.append({"ep": ep, "title": title, "gt": gt_val, "pred": pred_val or "解析失败", "hit": hit, "conf": conf})
if gt_val is None:
rows.append({"ep": ep, "title": title, "gt": "(无标注)", "pred": pred_val or "解析失败", "hit": None, "conf": conf})
else:
hit = pred_val == gt_val if pred_val is not None else False
rows.append({"ep": ep, "title": title, "gt": gt_val, "pred": pred_val or "解析失败", "hit": hit, "conf": conf})
elif field == "classification":
conf = result.get("confidence", "?") if result else "?"
sub = {}
@@ -134,22 +137,28 @@ def run(model, field="narrative"):
elif field == "narrative":
# 打印每行
for r in rows:
mark = "" if r["hit"] else ""
if r["hit"] is None:
mark = "-"
else:
mark = "" if r["hit"] else ""
conf_str = f'置信度:{r["conf"]}' if r["conf"] != "?" else ""
print(f' ep{r["ep"]:02d} {r["title"]:<10} | 标准:{r["gt"]:<8} | {model}:{r["pred"]:<8} | {mark} {conf_str}')
print(f' ep{r["ep"]:03d} {r["title"]:<12} | 标准:{r["gt"]:<6} | {model}:{r["pred"]:<6} | {mark} {conf_str}')
# 汇总
total = len(rows)
hits = sum(1 for r in rows if r["hit"])
hi_conf = [r for r in rows if r["conf"] == ""]
mid_low = [r for r in rows if r["conf"] in ("", "")]
# 汇总(跳过无标注)
scored = [r for r in rows if r["hit"] is not None]
hits = sum(1 for r in scored if r["hit"])
total = len(scored)
unlabeled = sum(1 for r in rows if r["hit"] is None)
hi_conf = [r for r in scored if r["conf"] == ""]
mid_low = [r for r in scored if r["conf"] in ("", "")]
hi_hit = sum(1 for r in hi_conf if r["hit"])
ml_hit = sum(1 for r in mid_low if r["hit"])
print(f"\n ===== {model} 命中情况 =====")
print(f" narrative_structure 命中: {hits}/{total} = {hits*100//total}%")
print(f" narrative_structure 命中: {hits}/{total} = {hits*100//total if total else 0}%")
print(f" 自评\"\"置信的命中率: {hi_hit}/{len(hi_conf)}")
print(f" 自评\"中/低\"置信的命中率: {ml_hit}/{len(mid_low)}")
print(f" 无标注(跳过): {unlabeled}")
print(f" 解析失败: {parse_fail}")
elif field == "classification":
field_names = ["program_format", "equipment_domain", "scene_tags", "tech_tags"]