Name Last Update
lyric_dedup Loading commit data...
scripts Loading commit data...
tests Loading commit data...
.gitignore Loading commit data...
README.md Loading commit data...
TEST_WORKFLOW.md Loading commit data...

Lyric Duplicate Checker

第一版用于“新增歌词查重”:先用已有 .lrc / .txt 歌词建立索引,再把新增歌词拿来查询,返回 duplicatereviewnew

建立索引

假设已有曲库在 data/library/

python -m lyric_dedup.cli build-index \
  --lyrics-dir data/library \
  --index outputs/indexes/lyrics.pkl

检查单个新增歌词

python -m lyric_dedup.cli check-file \
  --index outputs/indexes/lyrics.pkl \
  --file data/incoming/new_song.lrc

批量检查新增目录

python -m lyric_dedup.cli batch-check \
  --index outputs/indexes/lyrics.pkl \
  --lyrics-dir data/incoming \
  --out outputs/results/incoming_check.csv

CSV 里重点看这些列:

  • decision: 总判断。
  • best_candidate_id: 最像的已有歌词。
  • best_candidate_jaccard: n-gram 字面相似度。
  • best_candidate_line_coverage: 行级覆盖率。
  • matched_unique_lines: 命中的规范化歌词行。
  • best_candidate_reason: 中文判定原因,说明为什么判重、复核或判新。

生产判断建议:duplicate 可自动拦截;review 进人工池;new 入库前仍可抽样检查。

原文 + 中文翻译歌词的防护规则

当前会把歌词拆成三类行:

  • primary_lines: 原文行,自动判重主要依赖这部分。
  • translation_lines: 中文翻译行,只用于召回和复核解释。
  • unknown_lines: 无法稳定判断的行。

高置信拆分包括:

  • 同一个时间戳下出现外文行和中文行。
  • 多组稳定的外文行 + 中文行交替。

中置信拆分包括:

  • 同一行内明显的外文 / 中文翻译,例如 I miss you / 今晚我想你

低置信拆分包括:

  • 先整段外文,再整段中文翻译。

判定策略:

  • 原文高度一致,即使新增歌词多了中文翻译,也可以 duplicate
  • 只有翻译行相似,原文相似不足,只能 review,不自动判重。
  • 疑似整段翻译结构属于低置信拆分,即使原文 hash 一致,也先 review
  • 普通中文歌没有检测到翻译结构时,全部有效行按原文处理。

由于索引里会保存拆分后的原文/翻译特征,修改拆分规则后需要重建索引。

用标注 CSV 评估正确率

可以先从已有曲库自动生成一批评估样本:

python -m lyric_dedup.cli generate-eval-set \
  --library-dir data/library \
  --lyrics-dir data/generated_eval/incoming \
  --csv data/generated_eval/eval_10.csv \
  --size 10 \
  --positive-ratio 0.6

生成器的业务口径:

  • 应去重 样本只生成全曲歌词的样式变化,例如时间戳、标点、平台噪声、空行、LRC 样式、附加中文翻译。
  • 不应去重 样本包含片段歌词、短句碰撞、不同歌曲片段混合、同主题新歌词、仅翻译相似。
  • 片段歌词即使命中已有歌曲的一部分,也不应该输出 duplicate;最多进入 review

先准备一个 CSV,例如 data/eval/eval.csv

id,file,expected
case-001,incoming/song_a.lrc,应去重
case-002,incoming/song_b.txt,不应去重

也可以不用文件路径,直接把歌词放在 lyrics 列:

id,lyrics,expected
case-003,"我爱你在每个夜里\n听风说话也听见你",duplicate
case-004,"南方的雨穿过街心\n你把故事说给云听",new

expected 支持这些写法:

  • 应去重:应去重重复duplicate1trueyes
  • 不应去重:不应去重不重复new0falseno

运行评估:

python -m lyric_dedup.cli evaluate-csv \
  --index outputs/indexes/lyrics.pkl \
  --csv data/eval/eval.csv \
  --base-dir data \
  --out outputs/results/eval_result.csv

默认只有系统输出 duplicate 才算“预测应去重”。这适合评估自动拦截的准确率,误杀会更明显。

如果你想评估“可疑样本召回率”,也就是 duplicatereview 都算命中:

python -m lyric_dedup.cli evaluate-csv \
  --index outputs/indexes/lyrics.pkl \
  --csv data/eval/eval.csv \
  --base-dir data \
  --positive-decisions duplicate,review \
  --out outputs/results/eval_result_review_as_positive.csv

会生成两个文件:

  • outputs/results/eval_result.csv: 每条样本的预测、候选、原因和是否正确。
  • outputs/results/eval_result.csv.summary.json: 总体指标。

summary 里重点看:

  • accuracy: 总正确率。
  • precision: 预测应去重的样本里,有多少是真的应去重。自动拦截优先看这个。
  • recall: 真实应去重的样本里,有多少被系统抓到。
  • f1: precision 和 recall 的综合指标。
  • false_positive: 不应去重但被判为应去重,属于误杀。
  • false_negative: 应去重但没抓到,属于漏召。