歌词查重系统
这是一个使用 PostgreSQL 作为数据存储和候选召回层的歌词查重项目。Python 侧只负责歌词规范化、候选打分和最终判定,不再构建或加载 .pkl 本地索引。
架构
PostgreSQL:
lyrics 保存原始歌词、规范化文本、原文/翻译文本、exact_hash
lyric_lines 保存规范化歌词行和 line_hash
exact_hash 索引 精确重复召回
pg_trgm 索引 可选的近似文本召回
line_hash 索引 行级重合召回
Python:
normalize_lyrics 歌词清洗、时间戳/平台噪声处理、繁简转换、翻译行拆分
DuplicateChecker 只对 PostgreSQL 召回的候选打分和排序
决策规则 输出 duplicate / review / new
核心原则:
数据库负责召回候选。
Python 负责最终判断。
不再使用 pickle、本地 MinHash 索引或 outputs/indexes/*.pkl 作为生产链路。
安装依赖
python -m pip install -r requirements.txt
初始化 PostgreSQL
创建数据库:
createdb lyric_dedup
初始化表结构和索引:
python scripts/init_postgres.py \
--dsn postgresql:///lyric_dedup
会创建:
lyrics
lyric_lines
pg_trgm extension
exact_hash / primary_text_trgm / line_hash 索引
导入曲库
python scripts/import_library_postgres.py \
--dsn postgresql:///lyric_dedup \
--lyrics-dir data/library
导入脚本会:
1. 扫描 data/library 下的 .lrc / .txt。
2. 读取并规范化歌词。
3. 写入 lyrics 和 lyric_lines。
4. 默认对 exact_hash 完全一致的记录做 soft delete,只保留质量更高的一条。
5. 输出重复报告到 outputs/results/postgres_exact_duplicates.csv。
如果只导入、不做 exact 去重:
python scripts/import_library_postgres.py \
--dsn postgresql:///lyric_dedup \
--lyrics-dir data/library \
--skip-dedup-exact
检查单个歌词文件
python -m lyric_dedup.cli check-file \
--dsn postgresql:///lyric_dedup \
--file data/incoming/new_song.lrc
常用参数:
--recall-limit 每个 PostgreSQL 召回层最多返回多少候选
--max-candidates 最终返回和排序多少候选
--enable-trgm 启用 pg_trgm 近似文本召回
--trgm-threshold pg_trgm similarity 阈值
--statement-timeout-ms PostgreSQL statement_timeout
返回字段:
decision duplicate / review / new
duplicate duplicate 或 review 时为 true,new 时为 false
confidence 当前判定置信度
reason 中文判定原因
candidate_count 参与最终排序的候选数
启动 API
export LYRIC_DEDUP_DSN=postgresql:///lyric_dedup
uvicorn lyric_dedup_server.app:app --host 0.0.0.0 --port 8000
接口:
POST /api/v1/check
请求示例:
{
"url": "https://example.com/song.lrc",
"title": "Song Title",
"artist": "Artist"
}
服务会下载 URL 对应的 .lrc / .txt 文件,使用 PostgreSQL 召回候选并判定。若结果为 new,且请求带有 URL,服务会把这首新歌词写入 PostgreSQL。
生成评估集
常规生产口径:
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
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
生成器只写:
评估 CSV
样本歌词文件
manifest.json
不会再生成 .index.pkl。评估时由 PostgreSQL 召回候选,并根据 CSV 里的 source_record_id 排除 holdout 样本自身。
使用 PostgreSQL 评估
严格自动拦截口径:只有 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
可疑样本召回口径: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
评估会生成:
outputs/results/*.csv
outputs/results/*.csv.summary.json
summary 重点看:
precision 自动拦截准确率,重点关注 false_positive
recall 应去重样本召回率,重点关注 false_negative
f1 precision 和 recall 的综合指标
duplicate/review/new 三类判定分布