Files
admin afa7cce938 feat(aqua): unlock normalized KB identity via env with plant fallback
- normalized_release EXPECTED_RELEASE defaults to NORMALIZED_RELEASE_ID (plant value)
- from_env falls back to constant on empty env; backend_guard uses env-or-constant
- start.sh sources env/active_library.env after prod.env (qa + legacy-rag)
- build_all.sh --library <name|dir> renders library identity (no name whitelist)
- add kb-libraries skeleton (plant/aqua identity cards) and tooling/aqua_kb
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-12 19:10:08 +08:00

157 lines
5.7 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""qc_sample.py — 抽取 manifest.csv 三种状态样本并做可核验的规则检查。
用法: qc_sample.py [--manifest build/manifest.csv] [--source aqua/source]
[--n 20] [--seed 42]
规则(任一不通过 exit 1):
paired: md_path、pdf_path 都存在;md 文本 grep 到 doi_norm(斜杠或下划线形态
任一命中);PDF 文件名归一化后等于该 doi_norm。
md_only: pdf_path 为空;PDF正文 目录下无 *<doi_norm 下划线形态>* 与
*<斜杠换成下划线>* 文件;DOI汇总.txt 中 grep 到该 DOI(两种形态)。
pdf_only: md_path 为空;题目摘要_MD 目录下 grep 不到该 DOI(两种形态)。
只依赖标准库。
"""
from __future__ import annotations
import argparse
import csv
import random
import re
import sys
from pathlib import Path
def norm_doi(d: str) -> str:
"""DOI 归一化(与 pair_aqua_sources 同规则)。"""
return d.strip().lower().rstrip(".,;)]")
def slug_form(doi_norm: str) -> str:
"""斜杠换下划线 + 点换下划线:文件名 DOI 段的下划线形态。"""
return doi_norm.replace("/", "_").replace(".", "_")
def grep_pdf_norm(filename: str, doi_norm: str) -> bool:
"""PDF 文件名归一化后是否等于 doi_norm(复用 pair 的解码算法,取等值判定)。"""
stem = filename[:-4] if filename.lower().endswith(".pdf") else filename
cands: list[str] = []
for pos in reversed([m.start() for m in re.finditer(r"10\.", stem)]):
segs = stem[pos + 3:].split("_")
if not segs or not re.fullmatch(r"\d{4,9}", segs[0]):
continue
parts = [segs[0]]
for i in range(1, len(segs)):
seg = segs[i]
if i == len(segs) - 1 and re.fullmatch(r"[0-9a-fA-F]{8}", seg):
break
if seg and seg[0].isalnum():
parts.append(seg)
else:
break
for k in range(1, len(parts) + 1):
cands.append(norm_doi("10." + "/".join(parts[:k])))
return doi_norm in cands
def grep_file_text(f: Path, needle_slash: str, needle_under: str) -> bool:
if not f.is_file():
return False
text = f.read_text(encoding="utf-8", errors="replace")
return needle_slash in text or needle_under in text
def main() -> int:
ap = argparse.ArgumentParser(description="manifest 状态样本质量抽检")
ap.add_argument("--manifest", default="build/manifest.csv")
ap.add_argument("--source", default="aqua/source")
ap.add_argument("--n", type=int, default=20)
ap.add_argument("--seed", type=int, default=42)
args = ap.parse_args()
manifest = Path(args.manifest)
src = Path(args.source)
md_dir = src / "题目摘要_MD"
pdf_dir = src / "PDF正文"
doi_txt = src / "DOI汇总.txt"
rows = list(csv.DictReader(manifest.open(encoding="utf-8", newline="")))
groups: dict[str, list[dict]] = {"paired": [], "md_only": [], "pdf_only": []}
for r in rows:
if r["status"] in groups:
groups[r["status"]].append(r)
rng = random.Random(args.seed)
samples = {st: rng.sample(groups[st], min(args.n, len(groups[st]))) for st in groups}
def check_md_text(doi_norm: str, md_path: str) -> bool:
text = (src / md_path).read_text(encoding="utf-8", errors="replace")
return doi_norm in text or slug_form(doi_norm) in text
def check_md_dir_grep(doi_norm: str) -> bool:
n_slash = doi_norm
n_under = slug_form(doi_norm)
for f in md_dir.glob("*.md"):
t = f.read_text(encoding="utf-8", errors="replace")
if n_slash in t or n_under in t:
return True
return False
fails = 0
checked: dict[str, int] = {}
print("== qc_sample ==")
print(f"manifest={manifest} rows={len(rows)} "
f"(paired={len(groups['paired'])} md_only={len(groups['md_only'])} "
f"pdf_only={len(groups['pdf_only'])}) seed={args.seed} n={args.n}\n")
for st in ("paired", "md_only", "pdf_only"):
print(f"--- {st} (抽 {len(samples[st])} 条) ---")
for r in samples[st]:
dn = r["doi_norm"]; md = r["md_path"]; pdf = r["pdf_path"]
ok = True
if st == "paired":
if not (md and pdf and (src / md).is_file() and (src / pdf).is_file()):
ok = False
elif not check_md_text(dn, md):
ok = False
elif not grep_pdf_norm(Path(pdf).name, dn):
ok = False
elif st == "md_only":
if pdf:
ok = False
else:
has_glob = any(
pdf_dir.glob("*" + slug_form(dn) + "*")
) or any(
pdf_dir.glob("*" + dn.replace("/", "_") + "*")
)
if has_glob:
ok = False
elif not grep_file_text(doi_txt, dn, slug_form(dn)):
ok = False
else: # pdf_only
if md:
ok = False
elif check_md_dir_grep(dn):
ok = False
if not ok:
fails += 1
print(f"[{'PASS' if ok else 'FAIL'}] {st:8s} "
f"doi={dn[:46]:46s} md={Path(md).name if md else '-':20s} "
f"pdf={Path(pdf).name if pdf else '-'}")
checked[st] = len(samples[st])
print("\n== 结果 ==")
print(f"checked={sum(checked.values())} fails={fails}")
for st in ("paired", "md_only", "pdf_only"):
print(f" {st}: {checked[st]} 条")
print("PASS" if fails == 0 else "FAIL")
return 1 if fails else 0
if __name__ == "__main__":
sys.exit(main())