TEST_WORKFLOW.md
5.52 KB
歌词查重测试流程
本文档记录当前项目的 PostgreSQL-only 测试流程。当前链路不再使用 outputs/indexes/*.pkl,也不再生成 *.index.pkl 评估索引。
1. 准备数据
已有曲库:
data/library/
支持文件:
.lrc
.txt
生成的评估样本目录:
data/generated_eval/incoming/
data/generated_eval/hard_incoming/
评估结果目录:
outputs/results/
2. 初始化 PostgreSQL
创建数据库:
createdb lyric_dedup
初始化 schema:
python scripts/init_postgres.py \
--dsn postgresql:///lyric_dedup
检查表:
psql postgresql:///lyric_dedup -c '\dt'
3. 导入曲库
python scripts/import_library_postgres.py \
--dsn postgresql:///lyric_dedup \
--lyrics-dir data/library
导入完成后检查数量:
psql postgresql:///lyric_dedup -c 'select count(*) from lyrics where deleted_at is null;'
psql postgresql:///lyric_dedup -c 'select count(*) from lyric_lines;'
导入脚本默认会 soft delete exact_hash 完全一致的重复记录,并输出:
outputs/results/postgres_exact_duplicates.csv
如果要额外查看高行级覆盖的疑似重复:
python scripts/import_library_postgres.py \
--dsn postgresql:///lyric_dedup \
--lyrics-dir data/library \
--line-duplicate-report outputs/results/postgres_line_duplicates.csv
4. 检查单个文件
python -m lyric_dedup.cli check-file \
--dsn postgresql:///lyric_dedup \
--file test_api/test_lyric.txt
如需启用 trigram 文本召回:
python -m lyric_dedup.cli check-file \
--dsn postgresql:///lyric_dedup \
--file test_api/test_lyric.txt \
--enable-trgm \
--trgm-threshold 0.3
5. 生成 standard 评估集
python -m lyric_dedup.cli generate-eval-set \
--library-dir data/library \
--lyrics-dir data/generated_eval/incoming \
--csv data/generated_eval/eval_5000.csv \
--size 5000 \
--positive-ratio 0.3
standard 口径:
应去重: 30%
不应去重: 70%
样本类型:
positive_* = 应去重,全曲歌词样式变化,例如时间戳、标点、平台噪声、空行、重复副歌次数变化、附加翻译、少量错别字
negative_real_holdout_full_song = 不应去重,完整真实歌词,从评估候选里排除自身
negative_fragment = 不应去重,单曲片段
negative_shared_chorus = 不应去重,重复副歌碰撞
negative_translation_only = 不应去重,仅翻译相似
negative_same_theme_synthetic = 不应去重,同主题新歌词
edge_short_or_placeholder = 不应去重,短歌词/占位边界样本
6. 生成 hard 评估集
python -m lyric_dedup.cli generate-eval-set \
--profile hard \
--library-dir data/library \
--lyrics-dir data/generated_eval/hard_incoming \
--csv data/generated_eval/eval_hard_5000.csv \
--size 5000 \
--positive-ratio 0.3
hard 口径强调真实业务边界,不故意制造反常输入:
positive_realistic_variant = 应去重,同曲平台版本噪声、较完整缺段、整段翻译附加、真实录入/OCR 错
negative_near_neighbor_holdout_full_song = 不应去重,和曲库有较多行重合的真实 holdout 新歌
negative_long_fragment = 不应去重,较长但不完整的单曲片段
negative_catalog_mashup = 不应去重,多首真实歌词片段组成的串烧/混剪式输入
7. 严格评估
严格口径只把 duplicate 算作预测应去重:
python scripts/evaluate_postgres.py \
--dsn postgresql:///lyric_dedup \
--csv data/generated_eval/eval_hard_5000.csv \
--base-dir data/generated_eval \
--out outputs/results/postgres_eval_hard_5000.csv
适合看自动拦截质量,重点关注:
precision
false_positive
8. 召回评估
召回口径把 duplicate 和 review 都算作抓到可疑样本:
python scripts/evaluate_postgres.py \
--dsn postgresql:///lyric_dedup \
--csv data/generated_eval/eval_hard_5000.csv \
--base-dir data/generated_eval \
--positive-decisions duplicate,review \
--out outputs/results/postgres_eval_hard_5000_review_positive.csv
适合看漏召风险,重点关注:
recall
false_negative
9. 查看 summary
cat outputs/results/postgres_eval_hard_5000.csv.summary.json
cat outputs/results/postgres_eval_hard_5000_review_positive.csv.summary.json
指标含义:
accuracy 总正确率
precision 预测应去重的样本里,有多少是真的应去重
recall 真实应去重的样本里,有多少被系统抓到
f1 precision 和 recall 的综合指标
true_positive 应去重且预测应去重
false_positive 不应去重但预测应去重,误杀
true_negative 不应去重且预测不应去重
false_negative 应去重但预测不应去重,漏召
10. 查看失败样本
严格口径失败样本:
python -c 'import csv; rows=csv.DictReader(open("outputs/results/postgres_eval_hard_5000.csv", encoding="utf-8")); [print(r["id"], r["expected_duplicate"], r["decision"], r["reason"], sep=" | ") for r in rows if r["correct"] == "False"]'
按样本类型统计:
python -c 'import csv,collections; meta={r["id"]:r for r in csv.DictReader(open("data/generated_eval/eval_hard_5000.csv", encoding="utf-8-sig"))}; rows=csv.DictReader(open("outputs/results/postgres_eval_hard_5000.csv", encoding="utf-8")); c=collections.Counter(meta.get(r["id"],{}).get("sample_type","") for r in rows if r["correct"]=="False"); print(c)'