Commit 38b37e08 38b37e086d340ade289d9b15fd828001e1f346d9 by cnb.bofCdSsphPA

Why the schema docs need one song-centric story, not parallel histories

Constraint: New teammates must understand where slice/model/feature data lands without reading deprecated v2/planner-worker material
Rejected: Keep old docs with disclaimers | still leaves two competing mental models in the default docs path
Confidence: high
Scope-risk: narrow
Directive: Keep future docs anchored on the 4-table song-centric path unless the physical schema default truly changes
Tested: markdown link check on /workspace/docs; staged diff review; verified referenced wrapper script is present
Not-tested: No database or pipeline rerun was needed for this docs-only consolidation
1 parent 020702cc
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PYTHON_BIN="${PYTHON_BIN:-/usr/local/miniconda3/bin/python}"
DSN="${1:-${PG_DSN:-}}"
SCHEMA="${2:-${PG_SCHEMA:-acr_songcentric_test}}"
INPUT_ROOT="${3:-$ROOT_DIR/data/songcentric_builder_smoke}"
OUTPUT_DIR="${4:-$ROOT_DIR/data/pgvector_eval/music20}"
if [[ -z "$DSN" ]]; then
echo "usage: $0 <postgres-dsn> [schema] [input-root] [output-dir]" >&2
echo "or set PG_DSN before running this script" >&2
exit 1
fi
cd "$ROOT_DIR/.."
"$PYTHON_BIN" acr-engine/scripts/run_songcentric_directory_pipeline_live.py \
--dsn "$DSN" \
--schema "$SCHEMA" \
--input-root "${INPUT_ROOT#$ROOT_DIR/..\/}" \
--output-dir "${OUTPUT_DIR#$ROOT_DIR/..\/}"
# Changelog
## 2026-06-04
- 收敛 `docs/` 到当前 song-centric 主线,只保留 `README / start-here / session-handoff / postgresql-data-model / postgres_db_schema_samples / CHANGELOG` 六份核心文档,删除旧的 v2 / planner-worker / registry 扩展文档,避免新同学误入已退居次线的设计。
- 重写 `docs/postgresql-data-model.md`,明确 `保存切片的数据 + 模型 + feature` 的落表方案:`window``audio_object`,模型身份落 `feature_fact.model_name/model_version/feature_set_name`,具体 `fingerprint/embedding` 也统一落 `feature_fact`
- 重写 `docs/postgres_db_schema_samples.md` 与入口文档,补充当前 4 表主链的流程图、典型 SQL 样例、查询回溯路径与写入顺序,统一文档口径到 `media_entity -> audio_object -> feature_fact -> set_membership`
## 2026-06-04
- 新增 `acr-engine/scripts/start_songcentric_shortest_path.sh`,把当前默认主线再收敛成一条可直接复制执行的 shell 入口,并已用 fresh runner 结果再次验证。
-`run_songcentric_directory_pipeline_live.py` 提升为当前默认主线入口,并把 fresh runner 结果同步到 `docs/README.md``docs/start-here.md``docs/session-handoff.md`,降低下次 session 的恢复成本。
......
# ACR Docs Overview
> 当前仅保留与 **song-centric + 融合优先** ACR 设计直接相关的文档。
> 当前 docs 只保留与 **song-centric + 4 表融合 schema** 直接相关的文档。
---
## 0. 新同学先做什么
## 1. 先看什么
如果当前要继续 song-centric 主线,先跑
新同学接手顺序
```bash
cd /workspace
/usr/local/miniconda3/bin/python acr-engine/scripts/run_songcentric_directory_pipeline_live.py \
--dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \
--schema acr_songcentric_test \
--input-root acr-engine/data/songcentric_builder_smoke \
--output-dir acr-engine/data/pgvector_eval/music20
```
如果要回归旧的 planner/worker 合同,再跑:
```bash
cd /workspace/acr-engine
/usr/local/miniconda3/bin/python scripts/run_planner_validation_commands_live.py \
--dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \
--output data/pgvector_eval/music20/planner_validation_commands_runner_report.json
```
也可以用包装脚本:`acr-engine/scripts/start_phase1_shortest_path.sh 'postgres://d2:d2pass@127.0.0.1:5432/d2'`
当前 fresh evidence:
- `executed_count = 4`
- `all_passed = true`
1. [start-here.md](./start-here.md)
2. [session-handoff.md](./session-handoff.md)
3. [postgresql-data-model.md](./postgresql-data-model.md)
4. [postgres_db_schema_samples.md](./postgres_db_schema_samples.md)
5. [CHANGELOG.md](./CHANGELOG.md)
---
## 1. 当前默认设计口径
## 2. 当前默认设计口径
当前 Phase-1 默认按下面理解
逻辑语义
```text
song -> asset -> window -> fingerprint / embedding
```
对应融合优先物理表:
物理落表:
```text
media_entity -> audio_object -> feature_fact -> set_membership
```
核心目标:
- 最终稳定返回 `song_id`
- 同一个 `song` 下允许多个音频文件
- `window` 是切片/evidence/召回最小单元
- `feature_fact` 同时承载 exact lane 与 semantic lane
- Phase-1 直接复用开源 encoder,不先训练/微调
---
## 2. 必读文档
## 3. 一键验证主链
1. [start-here.md](./start-here.md)
2. [session-handoff.md](./session-handoff.md)
3. [acr-architecture.md](./acr-architecture.md)
4. [postgresql-data-model.md](./postgresql-data-model.md)
5. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md)
```bash
cd /workspace
/usr/local/miniconda3/bin/python acr-engine/scripts/run_songcentric_directory_pipeline_live.py \
--dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \
--schema acr_songcentric_test \
--input-root acr-engine/data/songcentric_builder_smoke \
--output-dir acr-engine/data/pgvector_eval/music20
```
---
包装脚本:
## 3. 实施相关文档
```bash
acr-engine/scripts/start_songcentric_shortest_path.sh 'postgres://d2:d2pass@127.0.0.1:5432/d2'
```
- [postgresql-data-model.md](./postgresql-data-model.md) — 当前唯一默认数据模型;含切片/模型/feature 落表说明与流程图
- [postgres_db_schema_samples.md](./postgres_db_schema_samples.md) — PostgreSQL 存储样例
- [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) — model/feature/reference set 初始化
- [phase1-worker-contract.md](./phase1-worker-contract.md) — worker、job、失败语义合同
- [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) — Phase-1 实施清单
- [production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md) — encoder-only 冻结策略
- [sota-evolution-guide.md](./sota-evolution-guide.md) — 当前 SOTA 演进主线
当前 fresh evidence:
- `song_count = 2`
- `asset_count = 2`
- `window_count = 5`
- `matcher_fingerprint_count = 5`
- `fallback_fingerprint_count = 0`
- `semantic_runtime_available = false`
- `import_counts.feature_fact = 24`
---
## 4. 当前稳定结论
## 4. 当前保留文档分别解决什么
- 最终归属对象当前只要求稳定返回 `song_id`
- 同一个 `song` 下允许有多个音频文件
- 当前暂不把 `recording/version` 作为必须返回对象
- `window` 仍然保留,因为它是 evidence / offset / 检索最小单元
- `feature_fact` 统一承载 `fingerprint``embedding`
- [start-here.md](./start-here.md):新同学 10 分钟接手入口
- [session-handoff.md](./session-handoff.md):下次启动从哪里继续
- [postgresql-data-model.md](./postgresql-data-model.md):表设计、字段语义、流程图、设计取舍
- [postgres_db_schema_samples.md](./postgres_db_schema_samples.md):DDL、样例数据、典型 SQL、导入查询链路
- [CHANGELOG.md](./CHANGELOG.md):变更历史
---
## 5. 文档维护命令
```bash
/usr/local/miniconda3/bin/python scripts/check_markdown_links.py --root docs
/usr/local/miniconda3/bin/python /workspace/scripts/check_markdown_links.py --root /workspace/docs
```
默认会跳过 `CHANGELOG.md` 这类历史归档文档。
......
# ACR 系统蓝图 / Architecture Blueprint
> 更新:2026-06-04
> 目标:把当前 ACR 原型、未来 SOTA 演进路径、以及不同角色的关注点统一到一份可读的系统蓝图里。
## 一页结论
当前仓库已经验证了一个可运行的混合识别原型:
- `Chromaprint / fingerprint`:负责 exact / near-duplicate 快速召回
- `ECAPA-style embedding`:负责当前语义向量召回 baseline
- `melody-aware rerank`:负责弱旋律补强
但未来面向 **版权保护 + 100w 音频 / 30w 歌曲** 的目标,系统应演进为:
1. **数据规范稳定**`canonical_song -> work -> recording -> recording_asset -> audio_window`
2. **底座模型可替换**`model_registry -> feature_set_registry -> embedding/index`
3. **检索链分层**:exact lane + semantic lane + version/cover lane + aggregation
4. **服务与运维分离**:离线建库、在线召回、审核归一、监控治理分别有清晰职责
---
## 1. 总体系统图
```mermaid
flowchart TD
A[Audio Sources\n官方母带 / 平台音频 / 抓取音频 / UGC / 录音] --> B[Asset Normalization]
B --> C[Canonical Data Model\nSong / Work / Recording / Asset / Window]
C --> D1[Exact Lane\nChromaprint / Neural AFP]
C --> D2[Semantic Lane\nFoundation Encoder]
C --> D3[Version/Cover Lane\nPhase-2+]
D1 --> E[Candidate Aggregation]
D2 --> E
D3 --> E
E --> F[Canonical Song Decision]
F --> G[Service / Review / Audit]
```
---
## 2. 当前实现 vs 目标实现
| 维度 | 当前实现 | 目标实现 |
|---|---|---|
| 底座向量模型 | ECAPA-style baseline | MERT / MuQ 等 foundation encoder 为主 |
| 检索结构 | chromaprint + embedding + melody | exact + semantic + version/cover + rerank |
| 数据主键 | 以 `song_id` 为核心 | `canonical_song / work / recording / asset / window` 分层 |
| 存储形态 | 原型式 pgvector schema + 文件产物 | PostgreSQL 主数据 + 可替换向量/索引层 |
| 服务目标 | 验证闭环 | 版权保护 / 归属判断 / 工业化运维 |
---
## 2.1 为什么现在会显得“层很多”
因为当前蓝图同时覆盖了 3 个维度:
1. **业务归属**`song/work/recording`
2. **音频实体**`asset/window`
3. **检索计算**`feature/index/candidate/decision`
把这三类问题放在一张总图中,会看起来像一条很长的链。
但在工程上,它们其实是不同职责:
- 业务归属层回答:**最后该归谁**
- 音频实体层回答:**命中的是哪段音频**
- 检索计算层回答:**这段音频是怎么被召回出来的**
---
## 2.2 当前最小可用架构可以收敛到什么程度
如果当前阶段只追求:
> 快速稳定地把 query 命中到正确 `song_id`
那 Phase-1 完全可以按下面这套最小骨架推进:
```text
song -> asset -> window -> fingerprint / embedding
```
保留原因:
- `window` 不能删:它是 offset/evidence/多段投票的最小单元
- `feature_set_registry` / `feature_fact` 不能删:否则未来换 MERT/MuQ 会把 schema 写死
- `asset` 不能删:同一个 `song` 下会有多个真实音频文件
可以延后:
- `recording`
- `work`
- 更重的 `retrieval_index_registry`
- 更细的全链路审计表
因此推荐口径不是“把所有层都砍掉”,而是:
> **Phase-1 先上 song-centric 最小可用层;未来版本归属/cover/work 治理再继续加层。**
---
## 3. 角色视图
## 3.1 产品 / 架构角色
关注:
- 版权保护是否能最终定位到 `canonical_song_id`
- `recording``work` 的区别是否明确
- 当前阶段是否坚持“先冻结规范、后迭代模型”
- 各团队之间接口是否清晰
最该读:
- 本文
- [sota-evolution-guide.md](./sota-evolution-guide.md)
- [postgresql-data-model.md](./postgresql-data-model.md)
---
## 3.2 开发角色(后端 / 检索 / 数据)
关注:
- 如何把音频导入统一实体模型
- 如何切窗、建 feature_set、挂索引
- 如何从 query 走到候选,再归一到 `canonical_song_id`
- 如何支持未来切换 `model_name / model_version / feature_set`
最该读:
- 本文
- [postgresql-data-model.md](./postgresql-data-model.md)
---
## 3.3 运维 / 平台角色
关注:
- 离线任务:抽特征、建索引、重建索引
- 在线服务:召回、聚合、缓存、可观测性
- 存储分层:对象存储、PostgreSQL、索引后端
- 版本化:encoder 变更如何灰度、回滚、双写/双索引
最该读:
- 本文
- [postgresql-data-model.md](./postgresql-data-model.md)
- [phase1-worker-contract.md](./phase1-worker-contract.md)
---
## 3.4 模型底座 / 研究角色
关注:
- Phase-1 先不用微调时,选哪个开源 encoder
- 如何定义 feature_set:窗长、hop、pooling、layer selection
- 未来如何从 encoder-only 升级到 version/cover lane
- 如何让新模型接入而不破坏数据层
最该读:
- [sota-evolution-guide.md](./sota-evolution-guide.md)
- [production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md)
- [postgresql-data-model.md](./postgresql-data-model.md)
---
## 4. 离线 / 在线职责拆分
```mermaid
flowchart LR
A[Offline\n数据治理/切窗/特征抽取/建索引] --> B[Registered Artifacts\nfeature_set / index / metadata]
B --> C[Online\nquery encode / retrieve / aggregate / decide]
```
### 离线职责
- 资产标准化
- 元数据归一
- 切窗
- 模型特征抽取
- fingerprint / embedding 建索引
- 回填 PostgreSQL 元数据
### 在线职责
- 接收 query
- query 切块 / 编码
- exact / semantic / version lane 召回
- recording/work/song 聚合
- 输出 `canonical_song_id` + 证据
---
## 5. 为什么必须把角色拆开
因为这个项目已经不是单一模型脚本,而是:
1. **数据治理系统**:谁的音频、属于哪个 recording/work/song
2. **检索系统**:如何从 query 找到候选
3. **判定系统**:最终输出哪一个 `canonical_song_id`
4. **服务系统**:如何对外提供 API 与可观测性
5. **演进系统**:底座模型会变,但数据规范不能跟着乱变
---
## 6. 当前阶段建议
### 当前最重要的不是继续改训练,而是:
1. 先把 PostgreSQL 数据规范稳定下来
2. 先把 `model_registry / feature_set_registry` 结构打稳
3. Phase-1 用开源 encoder 直接做 semantic lane baseline
4. 保留当前 ECAPA 作为历史 baseline / 对照组
### 当前系统中的保留项
- `Chromaprint`:保留
- `ECAPA baseline`:保留为对照组
- `melody rerank`:保留为补充 lane,不再作为主演进方向
### 当前系统中的升级项
- semantic lane 主 encoder -> foundation model
- pgvector 原型 schema -> 可扩展 PostgreSQL 数据模型
- 扁平 song_id -> canonical/work/recording/recording_asset/audio_window
---
## 7. 与代码的映射
| 代码/文档 | 当前角色 |
|---|---|
| `acr-engine/src/engines/chromaprint_matcher.py` | exact lane 原型 |
| `acr-engine/src/engines/ecapa_embedder.py` | current embedding lane baseline |
| `acr-engine/src/engines/hybrid_engine.py` | current aggregation prototype |
| `acr-engine/sql/pgvector_schema.sql` | 早期 pgvector prototype |
| `acr-engine/sql/acr_pg_schema_v2.sql` | 推荐的 PostgreSQL V2 schema |
| [postgresql-data-model.md](./postgresql-data-model.md) | V2 schema 设计说明 |
---
## 8. 阅读建议
如果你是:
- **架构负责人**:下一篇看 [sota-evolution-guide.md](./sota-evolution-guide.md)
- **数据/后端负责人**:下一篇看 [postgresql-data-model.md](./postgresql-data-model.md)
- **模型负责人**:先看 [sota-evolution-guide.md](./sota-evolution-guide.md) 再看 [production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md)
# Phase-1 实施清单 / Encoder-only Implementation Checklist
> 更新:2026-06-04
> 目标:把“先不上微调、先用开源 encoder”的 Phase-1 方案拆成可执行步骤,方便数据、检索、平台、运维团队并行推进。
## 一页结论
Phase-1 的交付目标不是“证明某个新模型绝对最优”,而是:
1.**PostgreSQL 主数据模型** 落稳
2.**reference 资产 / window / feature_set** 跑通
3.**MERT + MuQ** 建立 encoder-only baseline
4.**fingerprint lane + semantic lane** 的聚合链先跑通
5. 给 Phase-2 的 version/cover lane 留好接口
---
## 1. 交付范围
### 本阶段必须完成
- `canonical_song / work / recording / recording_asset / audio_window` 入库
- `model_registry / feature_set_registry` 初始化
- MERT/MuQ encoder-only 特征抽取
- hot reference set 建设
- semantic index 建设
- query -> candidate -> canonical_song 的基础闭环
### 本阶段不强求完成
- 底座微调
- cover 专项训练
- humming 专项 melody tower
- 全量冷数据统一进热索引
---
## 2. 角色分工
| 角色 | 主要交付 |
|---|---|
| 数据工程 | 资产清洗、去重、实体映射、切窗清单 |
| 后端/DBA | PostgreSQL DDL、索引、写入链、校验约束 |
| 检索工程 | fingerprint lane、semantic lane、聚合逻辑 |
| 模型工程 | MERT/MuQ 接入、feature_set 设计、抽特征脚本 |
| 平台/运维 | 离线任务编排、对象存储、热/冷索引治理 |
---
## 3. 分阶段 checklist
## Stage 1:主数据落库
### 目标
把业务事实层稳定下来,不依赖具体 encoder。
### Checklist
- [ ] 建库执行 `acr-engine/sql/acr_pg_schema_v2.sql`
- [ ] 初始化 `canonical_song`
- [ ] 初始化 `work`
- [ ] 初始化 `recording`
- [ ] 初始化 `recording_asset`
- [ ] 校验 lineage trigger 可用
- [ ] 用一小批 reference 数据做插入烟测
### 输出物
- PostgreSQL schema v2
- 初始实体数据
- 可复用的数据导入脚本
---
## Stage 2:reference 资产与切窗
### 目标
把“可被检索”的 reference 集合建出来。
### Checklist
- [ ] 选出 `is_reference=true` 的 recording
- [ ] 创建 `reference_set_registry`
- [ ] 回填 `reference_set_member`
- [ ] 统一标准化音频路径
- [ ] 生成 `audio_window`
- [ ] 标记 `active_for_index`
### 推荐规则
- 先只放主 reference 版本
- 默认先做 `5s / 2.5s hop`
- intro/outro 可先保留,后续再做 quality pruning
---
## Stage 3:模型与 feature_set 初始化
### 目标
把模型注册和特征版本定义稳定下来。
### Checklist
- [ ] 注册 `chromaprint`
- [ ] 注册 `mert v1-95m`
- [ ] 注册 `muq`
- [ ] 注册 `mert 5s/2.5s mean pool`
- [ ] 注册 `mert 10s/5s mean pool`
- [ ] 注册 `muq 5s/2.5s mean pool`
- [ ] 明确每个 feature_set 的 metric / quantization / dim
### 输出物
- `model_registry` 初始化数据
- `feature_set_registry` 初始化数据
- feature set 命名约定
---
## Stage 4:encoder-only 抽特征
### 目标
先不上训练,直接把 reference 集变成可检索 embedding。
### Checklist
- [ ] 抽取 MERT window embeddings
- [ ] 抽取 MuQ window embeddings
- [ ] 写入 `audio_embedding`
- [ ] 热数据写入 `audio_embedding_vector_768` 或对应物理表
- [ ] 冷数据落对象存储/parquet
- [ ] 回填 `is_indexed`
### 验证
- [ ] 随机抽样检查 `window -> embedding -> feature_set` 回链可用
- [ ] 检查向量 norm/缺失率/重复率
---
## Stage 5:索引与召回
### 目标
跑通 semantic lane 与 exact lane 的双路召回。
### Checklist
- [ ] 建 fingerprint index
- [ ] 建 semantic index
- [ ] 回填 `retrieval_index_registry`
- [ ] 做 query encode
- [ ] 返回 `retrieval_candidate`
- [ ] 聚合到 `recording / work / canonical_song`
- [ ]`phase1_prereq_audit`
- [ ]`phase1_worker_contract_smoke`
- [ ]`semantic_vector_negative_matrix`
- [ ]`asset_level_upsert_validation`
### 第一版聚合建议
- max score
- top-k average
- hit windows count
- exact lane / semantic lane agreement bonus
---
## Stage 6:基础评测与上线门禁
### 目标
先证明 Phase-1 结构可用。
### Checklist
- [ ] exact query bucket
- [ ] noisy/BGM bucket
- [ ] version-like bucket(即便暂时不训练 cover lane)
- [ ] Top1/Top3/MRR
- [ ] canonical_song recall
- [ ] work-level recall
- [ ] reference set 版本记录
---
## 4. 推荐时间顺序
```mermaid
flowchart TD
A[Schema v2 落库] --> B[实体导入]
B --> C[reference set 初始化]
C --> D[audio_window 生成]
D --> E[model/feature_set 初始化]
E --> F[MERT/MuQ 抽特征]
F --> G[semantic index]
C --> H[fingerprint index]
G --> I[candidate aggregation]
H --> I
I --> J[Phase-1 benchmark]
```
---
## 5. 第一版验收标准
### 数据层
- 能稳定插入 `canonical_song -> work -> recording -> recording_asset -> audio_window`
- 能支撑至少一套 `reference_set`
### 模型/特征层
- 能并行存在多个 `model_registry / feature_set_registry`
- 能跑通 MERT/MuQ encoder-only 抽特征
### 检索层
- 能同时返回 fingerprint lane 与 semantic lane 候选
- 能聚合输出 `canonical_song_id`
### 运维层
- 能重建 reference set
- 能重建 semantic index
- 能记录 feature_set 与 index version
---
## 6. 本阶段容易踩的坑
1. 先把 embedding 存储设计死到某个模型维度
2. 只保留 song_id,不保留 work/recording
3. reference set 没有版本化
4. query 结果无法回查具体 evidence window
5. exact lane 被过早删除
---
## 7. 当前建议结论
如果你要马上排计划,建议按这个优先级:
1. Schema v2 与主数据导入
2. reference set + audio_window
3. MERT/MuQ feature_set 初始化
4. encoder-only 抽特征
5. 双路召回与聚合
6. benchmark 与门禁
## 6.1 当前 planner 已提供的 validation entrypoints
`acr-engine/scripts/plan_phase1_extraction_jobs_live.py` 现在除了 job 级 `command_suggestions`,还会在 `phase1_extraction_plan_report.json` 里附带:
- `validation_commands.prereq_audit`
- `validation_commands.worker_contract_smoke`
- `validation_commands.semantic_vector_negative_matrix`
- `validation_commands.asset_level_upsert_validation`
这意味着下次启动时可以先跑“全局验证入口”,再决定是否执行具体 job,而不必手工拼测试命令。
## 6.2 当前推荐的一键验证入口
如果只是想先确认当前 host 是否具备继续推进 Phase-1 的条件,推荐优先执行:
```bash
cd /workspace/acr-engine
/usr/local/miniconda3/bin/python scripts/run_planner_validation_commands_live.py --dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' --output data/pgvector_eval/music20/planner_validation_commands_runner_report.json
```
它会直接读取 `phase1_extraction_plan_report.json``validation_commands`,并批量执行:
- `prereq_audit`
- `worker_contract_smoke`
- `semantic_vector_negative_matrix`
- `asset_level_upsert_validation`
当前 live 结果:
- `executed_count = 4`
- `all_passed = true`
# SOTA 演进方案说明 / SOTA Evolution Guide
> 更新:2026-06-04
> 目标:给出一个“先不上微调、先用开源 encoder”的 Phase-1 路线,并明确后续如何演进到更强的版权保护 / 版本归属系统。
## 一页结论
如果当前约束是:
- 先不微调底座
- 先要落数据规范
- 先解决 100w 音频 / 30w 歌曲的检索与归属基础问题
那么最合理的 Phase-1 路线不是“重训一套新模型”,而是:
1. **保留 exact lane**:Chromaprint / fingerprint
2. **semantic lane 主底座**:MERT-v1-95M
3. **semantic lane challenger**:MuQ
4. **数据库先稳住**`model_registry + feature_set_registry + audio_embedding + retrieval_index_registry`
5. **结果先按层聚合**:window -> recording -> work -> canonical_song
---
## 1. 为什么当前要走 encoder-only Phase-1
因为你当前最紧迫的问题不是“模型精度极限”,而是:
- 曲库很大:100w 音频 / 30w 歌曲
- 数据关系复杂:同曲可能有多录音、多版本、多来源资产
- 如果数据规范不稳,未来任何模型升级都会反复返工
所以 Phase-1 目标应该是:
```mermaid
flowchart LR
A[冻结数据规范] --> B[接入开源 encoder]
B --> C[建立 semantic baseline]
C --> D[做大规模索引与聚合验证]
D --> E[再决定是否进入微调 / version lane]
```
---
## 2. 推荐的阶段划分
## Phase-0:当前仓库阶段(已具备)
- `Chromaprint + ECAPA + melody rerank`
- 可跑通训练/建索引/评测/服务闭环
- 适合作为 baseline,而不是最终生产底座
## Phase-1:Encoder-only foundation baseline(当前推荐)
- exact lane:Chromaprint
- semantic lane:MERT-v1-95M
- challenger:MuQ
- 不微调底座
- 只做 feature extraction + index + aggregation
## Phase-2:Version / Cover lane
- 在 Phase-1 数据模型稳定后
- 引入 cover/version 专门分支
- 强化 work-level 归属
## Phase-3:Industrial retrieval stack
- ANN + reranker
- online/offline artifact registry
- 监控、回放、审计、人工复核
---
## 3. Phase-1 的推荐模型组合
## 3.1 Exact lane
### 选型
- Chromaprint / landmark hash
### 作用
- 原曲片段
- 平台转码
- near-duplicate
- 局部片段强匹配
### 为什么保留
版权保护不能只靠 semantic embedding。exact lane 在很多真实投诉/取证场景里仍然是最快且证据最强的第一条路径。
---
## 3.2 Semantic lane 主模型:MERT-v1-95M
### 推荐原因
- 是 music SSL foundation model
- 已有公开论文与实现
- 比自训小型 ECAPA 更符合音乐任务底座定位
- Phase-1 直接做 frozen encoder 成本与风险都更低
### Phase-1 中的角色
- 作为主 encoder 产出 window embedding
- 负责 noisy/BGM/一般跨域检索 baseline
- 后面可继续作为 teacher 或兼容旧索引版本
### 推荐 feature set
1. `mert_v1_95m__window_5s_hop_2.5s__meanpool__l2`
2. `mert_v1_95m__window_10s_hop_5s__meanpool__l2`
### 为什么先做两套
- `5s/2.5s`:更利于局部定位
- `10s/5s`:更利于整体语义稳定
---
## 3.3 Semantic lane Challenger:MuQ
### 推荐原因
- 更新、更接近下一代 music foundation model 路线
- 值得作为 challenger baseline
- 即使不开微调,也有希望在部分 MIR 任务上优于较早底座
### 当前建议
- Phase-1 先作为对照组,不立即替代 MERT
- 重点验证:向量分布稳定性、窗口级检索表现、内存/推理成本
---
## 3.4 为什么 Phase-1 不直接以 CoverHunter 为主线
因为 CoverHunter 的优势在:
- cover song identification
- alignment / refined attention / coarse-to-fine 训练
而你当前约束是:
- 先不用微调
- 先用开源 encoder
- 先把数据和检索规范落稳
所以它更适合作为 **Phase-2 的 version/cover lane 方向**,而不是 Phase-1 的主 baseline。
---
## 4. 角色关注点
## 4.1 模型底座角色
重点关注:
- 哪些 encoder 已注册到 `model_registry`
- 每个 encoder 的 input SR、window、pooling、embedding dim
- 哪些 feature set 是线上候选,哪些只是实验候选
## 4.2 检索角色
重点关注:
- 指纹 lane 与 semantic lane 如何组合
- `recording/work/song` 聚合规则
- top-k 候选如何稳定输出
## 4.3 数据角色
重点关注:
- 资产去重
- reference 资产选择
- window manifest
- 是否支持全量重建特征与索引
## 4.4 运维 / 平台角色
重点关注:
- encoder 版本切换是否可灰度
- 索引重建是否可并行
- 热/冷索引、历史索引是否可回滚
---
## 5. Phase-1 的实施顺序
```mermaid
flowchart TD
A[冻结 PostgreSQL 数据规范] --> B[导入 canonical/work/recording/asset/window]
B --> C[注册 model_registry / feature_set_registry]
C --> D[抽取 MERT 特征]
C --> E[抽取 MuQ 特征]
D --> F[构建 semantic index]
E --> F
F --> G[与 fingerprint lane 做聚合]
G --> H[输出 canonical_song_id / work_id / recording_id]
```
---
## 6. 每阶段解决的问题
| 阶段 | 解决的问题 | 暂不解决的问题 |
|---|---|---|
| Phase-1 | 数据规范、开源底座 baseline、索引可重建、song/work/recording 聚合 | 底座微调、cover 专项训练、melody tower |
| Phase-2 | version/cover 归属、work-level recall | 更复杂跨模态 humming |
| Phase-3 | 工业化服务、回放、监控、人工审核闭环 | 极致 research SOTA |
---
## 7. 与当前仓库的关系
### 当前保留
- `ECAPA baseline`:保留做对照,不作为长期主底座
- `Chromaprint`:保留,且在版权保护场景里非常重要
- `melody rerank`:保留为辅助 lane
### 当前新增
- `model_registry`
- `feature_set_registry`
- foundation encoder 特征抽取与注册
- 更清晰的 `canonical_song / work / recording` 数据结构
---
## 8. 当前推荐结论
如果今天就要给 Phase-1 定方案,我建议:
1. **先不改训练主线,不删 ECAPA**
2. **新增 MERT-v1-95M semantic lane**
3. **新增 MuQ challenger lane**
4. **只把 `is_reference=true` 的主参考窗口先做成热索引**
5. **先把 PostgreSQL 设计当成主交付**
换句话说:
> Phase-1 的核心不是“哪一个模型最终赢”,而是“数据规范 + 模型注册 + 特征注册 + 索引注册”这套长期结构先稳定下来。
# Start Here / 新同学接手入口
> 目标:让新来的同学在 **10 分钟内**知道:先跑什么、先读什么、当前卡在哪、下一步该做什么。
> 目标:让新同学在 **10 分钟内** 知道现在的主链、先跑什么、先看什么。
---
## 1. 先执行这条命令
如果当前目标是验证 **song-centric 真实目录 -> feature -> PostgreSQL** 主链,优先跑:
```bash
cd /workspace
/usr/local/miniconda3/bin/python acr-engine/scripts/run_songcentric_directory_pipeline_live.py \
......@@ -17,167 +15,116 @@ cd /workspace
--output-dir acr-engine/data/pgvector_eval/music20
```
或:
```bash
acr-engine/scripts/start_songcentric_shortest_path.sh 'postgres://d2:d2pass@127.0.0.1:5432/d2'
```
当前 fresh evidence:
- `song_count = 2`
- `asset_count = 2`
- `window_count = 5`
- `matcher_fingerprint_count = 5`
- `fallback_fingerprint_count = 0`
- `semantic_runtime_available = false`
- `import_counts.feature_fact = 24`
如果你当前目标是验证老的 Phase-1 planner/worker 合同,再跑下面这条:
```bash
cd /workspace/acr-engine
/usr/local/miniconda3/bin/python scripts/run_planner_validation_commands_live.py \
--dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \
--output data/pgvector_eval/music20/planner_validation_commands_runner_report.json
```
也可以用包装脚本:`acr-engine/scripts/start_phase1_shortest_path.sh 'postgres://d2:d2pass@127.0.0.1:5432/d2'`
### 当前 fresh evidence
- `executed_count = 4`
- `all_passed = true`
### 这条命令会执行
1. `prereq_audit`
2. `worker_contract_smoke`
3. `semantic_vector_negative_matrix`
4. `asset_level_upsert_validation`
### 看到下面这些结果时应该如何判断
如果你看到:
- `downloads_root_exists = false`
- `ready_jobs = 0`
- exact lane = `failed/unreadable_audio_assets`
- semantic lane = `4/4 failed`
说明当前优先级是:
1. 挂载 `/workspace/downloads`
2. 安装 `torch / torchaudio / transformers / speechbrain`
也就是说:
> 当前首要问题是运行环境前置条件,不是 PostgreSQL schema,也不是 worker contract 设计错误。
- `semantic_runtime_missing = [torch, torchaudio, transformers]`
- `import_counts = media_entity:9 / audio_object:22 / feature_fact:24 / set_membership:9`
---
## 2. 接手时只读这 5 份文档
## 2. 只读这 4 份文档
1. [README.md](./README.md)
2. [session-handoff.md](./session-handoff.md)
3. [acr-architecture.md](./acr-architecture.md)
4. [postgresql-data-model.md](./postgresql-data-model.md)
5. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md)
如果你负责算法或检索,再补:
- [sota-evolution-guide.md](./sota-evolution-guide.md)
- [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md)
- [phase1-worker-contract.md](./phase1-worker-contract.md)
3. [postgresql-data-model.md](./postgresql-data-model.md)
4. [postgres_db_schema_samples.md](./postgres_db_schema_samples.md)
---
## 3. 用一句话理解项目
## 3. 用一句话理解当前项目
我们在做的是一个面向 **版权保护 / 听歌识曲 / 版本归属** 的音乐 ACR 系统,
目标是`100w` 音频、约 `30w` 歌曲中,快速定位正确的 `song_id` 归属;当前阶段暂不把版本/recording 作为必须返回对象
我们当前做的是一个 **面向版权保护的 song-centric 音乐 ACR 系统**
目标是在约 `100w` 音频、约 `30w` 歌曲里,把录音、BGM、片段、翻唱相关查询尽快定位到应归属的 `song_id`
---
## 4. 当前主线方案
## 4. 当前最重要的设计结论
### 检索主线
- exact lane:`Chromaprint`
- semantic lane baseline:`MERT-v1-95M`
- semantic lane challenger:`MuQ`
- historical baseline:`ECAPA`
### 4.1 不再默认走旧的多层 v2 体系
当前默认只认 4 张核心物理表:
### 当前 Phase-1 最小主线
```text
song -> asset -> window
media_entity -> audio_object -> feature_fact -> set_membership
```
### 可演进完整版主线
```text
canonical_song -> work -> recording -> recording_asset -> audio_window
```
### 4.2 逻辑语义这样理解
### 模型主线
```text
model_registry -> feature_set_registry -> audio_embedding / audio_fingerprint -> retrieval_index_registry
song -> asset -> window -> fingerprint / embedding
```
---
### 4.3 切片 / 模型 / feature 到底落哪里
## 5. 当前哪些已经稳定
| 对象 | 表 | 关键字段 |
|---|---|---|
| song | `media_entity` | `entity_type='song'` |
| 原始音频文件 | `audio_object` | `object_type='asset'` |
| 切片窗口 | `audio_object` | `object_type='window'`, `parent_object_id=<asset_id>` |
| 指纹特征 | `feature_fact` | `feature_type='fingerprint'`, `fingerprint_value` |
| embedding 特征 | `feature_fact` | `feature_type='embedding'`, `embedding_uri/vector_table_name` |
| 模型信息 | `feature_fact` | `model_name`, `model_version`, `feature_set_name` |
| reference/eval/hot 集 | `set_membership` | `set_type`, `set_name` |
- PostgreSQL v2 schema 已落地
- registry bootstrap 已有 live 验证
- worker contract 已有 live 验证
- exact / semantic 的失败语义已可审计
- planner 已能输出 validation commands
- planner validation runner 已可一键执行
---
## 6. 当前哪些还没完成
## 5. 当前主链流程图
- 还没有真正跑通 MERT / MuQ inference
- 当前 host 没有 `/workspace/downloads`
- 当前 host 缺 `torch / torchaudio / transformers / speechbrain`
- 还没完成最终线上融合策略
- 还没接入更大规模真实 reference set
```mermaid
flowchart TD
A[media_entity\nentity_type=song] --> B[audio_object\nobject_type=asset]
B --> C[audio_object\nobject_type=window]
C --> D1[feature_fact\nfingerprint]
C --> D2[feature_fact\nembedding]
B --> E[set_membership\nreference_set / eval_set / hot_set]
C --> E
```
---
## 7. 如果你现在继续推进,按这个顺序
### 路线 A:先解环境
1. 挂载 `/workspace/downloads`
2. 安装 semantic runtime 依赖
3. 重跑 planner validation runner
4. 确认 `ready_jobs` 是否开始恢复
## 6. 当前哪些已经稳定
### 路线 B:先解实现
1. 阅读 [phase1-worker-contract.md](./phase1-worker-contract.md)
2. 阅读 `acr-engine/workers/run_embedding_job.py`
3. 用真实 inference adapter 替换 guarded failure path
4. 保持当前 PostgreSQL contract 不变
### 路线 C:先解数据
1. 阅读 [postgresql-data-model.md](./postgresql-data-model.md)
2. 阅读 [postgres_db_schema_samples.md](./postgres_db_schema_samples.md)
3. 准备更大的 reference set
4. 保持 `reference_set_registry / reference_set_member` 版本化
- live PostgreSQL schema 已真实建表通过
- 真实目录 -> manifest -> import 已打通
- 真实目录 -> fingerprint enrichment -> import 已打通
- semantic lane 已做成 runtime-aware
- 当前 host 无 `torch/torchaudio/transformers` 时会明确 fallback,不会伪装成功
- 当前 exact lane 已优先复用仓库内 `ChromaprintMatcher`
---
## 8. 当前不建议优先做的事
## 7. 当前最该继续什么
- 不要重新讨论要不要 `song/work/recording` 分层
- 不要回退到只有 `song_id` 的扁平表
- 不要先讨论重新训练底座
- 不要把当前问题误判成 PostgreSQL contract 设计问题
### 第一优先级
把 semantic lane 从 fallback 升级成真实 encoder adapter,且不破坏现有宿主链。
---
### 当前 host 事实
- `torch` 缺失
- `torchaudio` 缺失
- `transformers` 缺失
- 当前因此 `semantic_runtime_available = false`
## 9. 仓库常用入口
---
### 文档
- [README.md](./README.md)
- [session-handoff.md](./session-handoff.md)
- [postgresql-data-model.md](./postgresql-data-model.md)
- [postgres_db_schema_samples.md](./postgres_db_schema_samples.md)
- [phase1-worker-contract.md](./phase1-worker-contract.md)
## 8. 当前不要再绕回去的点
### 脚本
- `acr-engine/scripts/run_planner_validation_commands_live.py`
- `acr-engine/scripts/run_phase1_prereq_audit_live.py`
- `acr-engine/scripts/run_phase1_worker_contract_smoke_live.py`
- `acr-engine/scripts/run_embedding_vector_table_negative_matrix_live.py`
- `acr-engine/scripts/validate_audio_embedding_asset_upsert_live.py`
- `acr-engine/scripts/run_songcentric_directory_pipeline_live.py`
- 不要回退到旧的 v2 schema 作为默认口径
- 不要重新引入 `recording/work/version` 作为 Phase-1 必须返回对象
- 不要先讨论训练/微调
- 不要把“模型底座可替换”误解成“数据库要重新拆很多层”
---
## 一句话结论
> 新同学接手时,先跑 runner,再读 5 份核心文档;当前首要问题是环境前置条件,不是 schema/contract 本身
> 当前最重要的是守住 4 表 song-centric 主链,并在这个主链上把 semantic encoder 真正接起来
......