ai-labeling: ground-truth v0.3.0 + 脚本扩展 --field 支持 Prompt 1

- ground-truth.json 新增 4 分类字段骨架(program_format/equipment_domain/scene_tags/tech_tags)
- equipment_domain 类型修正为数组(对齐 v2 快照多选定义)
- run_labeling.py 新增 --field 参数,文件名含 field 标记
- summarize.py 新增 --field 参数 + 老文件向后兼容
- CLAUDE.md 补入 v1-v4 快照精华:象限图规格、6 字段枚举、三层交付策略

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
simonkoson
2026-06-24 17:53:05 +08:00
parent bdc59bf787
commit 30931d4446
4 changed files with 174 additions and 62 deletions
+48 -27
View File
@@ -39,11 +39,21 @@ def latest_per_ep(files):
return {ep: info[0] for ep, info in latest.items()}
def run(model):
pattern = str(EXPERIMENTS_DIR / f"*_{model}_*.json")
files = sorted(Path(p) for p in glob.glob(pattern))
def run(model, field="narrative"):
# 文件匹配:新格式有 field 标记,老格式(无 field)向后兼容
pattern_new = str(EXPERIMENTS_DIR / f"*_{model}_{field}_*.json")
files_new = sorted(Path(p) for p in glob.glob(pattern_new))
# 如果是 narrative 且新格式文件为空,尝试匹配老格式(无 field 标记)
if field == "narrative" and not files_new:
pattern_old = str(EXPERIMENTS_DIR / f"*_{model}_ep*.json")
files_old = [f for f in sorted(Path(p) for p in glob.glob(pattern_old))
if len(f.name.replace(".json", "").split("_")) == 3] # 老格式: ts_model_epNN.json
files = files_old
else:
files = files_new
if not files:
print(f"未找到 {pattern}")
print(f"未找到 {pattern_new}")
return
ep_files = latest_per_ep(files)
@@ -61,36 +71,47 @@ def run(model):
result = data.get("result")
title = gt.get("title", "?")
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 field == "narrative":
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})
elif field == "classification":
# 骨架预留:等 ground-truth 标注就绪后实现具体比对逻辑
rows.append({"ep": ep, "title": title, "gt": "?", "pred": "classification 待实现", "hit": False, "conf": "?"})
# 打印每行
for r in rows:
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}')
if field == "narrative":
# 打印每行
for r in rows:
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}')
# 汇总
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 ("", "")]
hi_hit = sum(1 for r in hi_conf if r["hit"])
ml_hit = sum(1 for r in mid_low if r["hit"])
# 汇总
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 ("", "")]
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" 自评\"\"置信的命中率: {hi_hit}/{len(hi_conf)}")
print(f" 自评\"中/低\"置信的命中率: {ml_hit}/{len(mid_low)}")
print(f" 解析失败: {parse_fail}")
print(f"\n ===== {model} 命中情况 =====")
print(f" narrative_structure 命中: {hits}/{total} = {hits*100//total}%")
print(f" 自评\"\"置信的命中率: {hi_hit}/{len(hi_conf)}")
print(f" 自评\"中/低\"置信的命中率: {ml_hit}/{len(mid_low)}")
print(f" 解析失败: {parse_fail}")
elif field == "classification":
print(f"\n ===== {model} classification =====")
print(f" classification 比对逻辑待实现(等 ground-truth 标注就绪)")
print(f" 解析失败: {parse_fail}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--model", required=True, help="模型键名,如 mimo-v2.5-pro / deepseek-v4-pro")
parser.add_argument("--field", default="narrative", choices=["narrative", "classification"],
help="打标字段: narrative(叙事结构) / classification(4分类)")
args = parser.parse_args()
run(args.model)
run(args.model, args.field)