Reduce ACR handoff time with a single doc chain
Constraint: Preserve the current Phase-1 runner, PostgreSQL v2 contract, and live validation narrative while removing duplicate doc entrypoints. Rejected: Keep multiple parallel handoff docs | They force new contributors to diff stale narratives before they can act. Confidence: high Scope-risk: narrow Directive: Treat README -> start-here -> session-handoff as the only first-read path unless a newer handoff chain fully replaces it. Tested: git diff --check on touched docs/script; rg for deleted-doc residual refs outside CHANGELOG; reran scripts/run_planner_validation_commands_live.py with executed_count=4 and all_passed=true Not-tested: Markdown link rendering in external viewers
Showing
11 changed files
with
395 additions
and
2686 deletions
| 1 | #!/usr/bin/env bash | ||
| 2 | set -euo pipefail | ||
| 3 | |||
| 4 | ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | ||
| 5 | PYTHON_BIN="${PYTHON_BIN:-/usr/local/miniconda3/bin/python}" | ||
| 6 | DSN="${1:-${PG_DSN:-}}" | ||
| 7 | OUTPUT="${2:-$ROOT_DIR/data/pgvector_eval/music20/planner_validation_commands_runner_report.json}" | ||
| 8 | |||
| 9 | if [[ -z "$DSN" ]]; then | ||
| 10 | echo "usage: $0 <postgres-dsn> [output-json]" >&2 | ||
| 11 | echo "or set PG_DSN before running this script" >&2 | ||
| 12 | exit 1 | ||
| 13 | fi | ||
| 14 | |||
| 15 | cd "$ROOT_DIR" | ||
| 16 | "$PYTHON_BIN" scripts/run_planner_validation_commands_live.py \ | ||
| 17 | --dsn "$DSN" \ | ||
| 18 | --output "$OUTPUT" |
| 1 | ## 2026-06-04 | 1 | ## 2026-06-04 |
| 2 | 2 | ||
| 3 | - 收敛文档入口链路,新增 `docs/start-here.md`,统一新同学接手路径为:`README -> start-here -> session-handoff`。 | ||
| 4 | - 重写 `docs/README.md`,按“接手 / 方案 / 实施 / 运行 / 角色”重组导航,降低首次阅读成本。 | ||
| 5 | - 重构 `docs/session-handoff.md`,把最新 Phase-1 runner、稳定结论、blocker 与下一步动作收口到单页文档。 | ||
| 6 | - 清理重复或过期文档:删除 `docs/acr-design.md`、`docs/open-dataset-plan.md`、`docs/external-manifest-template.md`、`docs/roadmap.md`、`docs/changelist-2026-06-02.md`、`docs/delivery-handoff-2026-06-02.md`。 | ||
| 7 | - 历史记录仍保留在 `docs/CHANGELOG.md`,当前有效入口以上述主链为准。 | ||
| 8 | |||
| 9 | ## 2026-06-04 | ||
| 10 | |||
| 3 | - 更新 `docs/README.md` 顶部为与 `session-handoff` 一致的“最短启动路径”,并再次用该入口命令重跑 `run_planner_validation_commands_live.py`,确认 fresh 结果仍为 `executed_count=4`、`all_passed=true`。 | 11 | - 更新 `docs/README.md` 顶部为与 `session-handoff` 一致的“最短启动路径”,并再次用该入口命令重跑 `run_planner_validation_commands_live.py`,确认 fresh 结果仍为 `executed_count=4`、`all_passed=true`。 |
| 4 | - 重构 `docs/session-handoff.md` 顶部为“首选启动流程(最短路径)”,直接给出 `run_planner_validation_commands_live.py` 的一条启动命令,以及基于 fresh runner 报告(`executed_count=4`, `all_passed=true`)的结果判断逻辑,减少下次 session 的恢复成本。 | 12 | - 重构 `docs/session-handoff.md` 顶部为“首选启动流程(最短路径)”,直接给出 `run_planner_validation_commands_live.py` 的一条启动命令,以及基于 fresh runner 报告(`executed_count=4`, `all_passed=true`)的结果判断逻辑,减少下次 session 的恢复成本。 |
| 5 | - 新增 `scripts/run_planner_validation_commands_live.py` 与 `planner_validation_commands_runner_report.json`,可直接读取 `phase1_extraction_plan_report.json` 中的 `validation_commands` 并批量执行;当前 4 条 entrypoints 已全部执行成功,`executed_count=4`、`all_passed=true`。 | 13 | - 新增 `scripts/run_planner_validation_commands_live.py` 与 `planner_validation_commands_runner_report.json`,可直接读取 `phase1_extraction_plan_report.json` 中的 `validation_commands` 并批量执行;当前 4 条 entrypoints 已全部执行成功,`executed_count=4`、`all_passed=true`。 | ... | ... |
| 1 | # ACR Docs Overview | 1 | # ACR Docs Overview |
| 2 | 2 | ||
| 3 | > 面向“版权保护 / 听歌识曲 / 版本归属”的音乐 ACR 文档入口。默认先看主路径,历史细节文档作为补充材料保留。 | 3 | > 面向“版权保护 / 听歌识曲 / 版本归属”的音乐 ACR 文档总入口。 |
| 4 | 4 | ||
| 5 | ## 最短启动路径(推荐) | 5 | --- |
| 6 | |||
| 7 | ## 0. 新同学先做什么 | ||
| 6 | 8 | ||
| 7 | 如果下次启动的目标是:**先判断当前 host 能不能继续推进 Phase-1**,不要先手工翻很多文档,先直接跑: | 9 | ### 先跑,不要先读一堆文档 |
| 8 | 10 | ||
| 9 | ```bash | 11 | ```bash |
| 10 | cd /workspace/acr-engine | 12 | cd /workspace/acr-engine |
| 11 | /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 | 13 | /usr/local/miniconda3/bin/python scripts/run_planner_validation_commands_live.py \ |
| 14 | --dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \ | ||
| 15 | --output data/pgvector_eval/music20/planner_validation_commands_runner_report.json | ||
| 12 | ``` | 16 | ``` |
| 13 | 17 | ||
| 14 | 当前这条命令的 fresh evidence 已有: | 18 | 也可以用包装脚本:`acr-engine/scripts/start_phase1_shortest_path.sh 'postgres://d2:d2pass@127.0.0.1:5432/d2'` |
| 15 | 19 | ||
| 20 | 当前 fresh evidence: | ||
| 16 | - `executed_count = 4` | 21 | - `executed_count = 4` |
| 17 | - `all_passed = true` | 22 | - `all_passed = true` |
| 18 | 23 | ||
| 19 | 它会一次性执行: | 24 | ### 再按这条阅读链路走 |
| 20 | 25 | 1. [start-here.md](./start-here.md) | |
| 21 | 1. `prereq_audit` | 26 | 2. [session-handoff.md](./session-handoff.md) |
| 22 | 2. `worker_contract_smoke` | 27 | 3. [acr-architecture.md](./acr-architecture.md) |
| 23 | 3. `semantic_vector_negative_matrix` | 28 | 4. [postgresql-data-model.md](./postgresql-data-model.md) |
| 24 | 4. `asset_level_upsert_validation` | 29 | 5. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) |
| 25 | |||
| 26 | 如果结果仍是: | ||
| 27 | - `downloads_root_exists = false` | ||
| 28 | - `ready_jobs = 0` | ||
| 29 | - exact = `failed/unreadable_audio_assets` | ||
| 30 | - semantic = `4/4 failed` | ||
| 31 | 30 | ||
| 32 | 那么说明当前优先级应该是: | 31 | --- |
| 33 | 32 | ||
| 34 | 1. 解决 `/workspace/downloads` 挂载 | 33 | ## 1. 文档总导航 |
| 35 | 2. 安装语义模型 runtime 依赖 | ||
| 36 | 34 | ||
| 37 | 而不是继续怀疑 PostgreSQL contract。 | 35 | ### A. 接手项目 / 恢复上下文 |
| 36 | - [start-here.md](./start-here.md) — 新同学 10 分钟接手入口 | ||
| 37 | - [session-handoff.md](./session-handoff.md) — 当前状态、阻塞、下一步 | ||
| 38 | - [CHANGELOG.md](./CHANGELOG.md) — 变更记录 | ||
| 38 | 39 | ||
| 39 | ## 一页结论 | 40 | ### B. 系统方案 / 设计主线 |
| 41 | - [acr-architecture.md](./acr-architecture.md) — 总体架构与分层 | ||
| 42 | - [sota-evolution-guide.md](./sota-evolution-guide.md) — SOTA 演进路径 | ||
| 43 | - [postgresql-data-model.md](./postgresql-data-model.md) — PostgreSQL 主数据/特征模型 | ||
| 44 | - [production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md) — encoder-only 冻结策略 | ||
| 40 | 45 | ||
| 41 | 当前项目已经从“原型是否能跑通”转向“**如何把 100w 音频 / 30w 歌曲做成可演进的版权检索系统**”。 | 46 | ### C. 第一个阶段怎么落地 |
| 42 | 默认阅读顺序不再按“训练脚本 -> demo”,而按: | 47 | - [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) — Phase-1 执行清单 |
| 48 | - [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) — model/feature/reference set 初始化 | ||
| 49 | - [phase1-worker-contract.md](./phase1-worker-contract.md) — worker、job、失败语义合同 | ||
| 50 | - [postgres_db_schema_samples.md](./postgres_db_schema_samples.md) — PostgreSQL 存储样例 | ||
| 43 | 51 | ||
| 44 | 1. **系统蓝图**:当前系统是什么、未来要演进成什么 | 52 | ### D. 运行 / 服务 / 数据治理 |
| 45 | 2. **SOTA 演进**:Phase-1 不微调底座时怎么做,后面如何升级 | 53 | - [runbook.md](./runbook.md) — 运维/运行手册 |
| 46 | 3. **PostgreSQL 数据模型**:资产、窗口、特征、索引、匹配结果如何落盘 | 54 | - [service-api.md](./service-api.md) — 服务 API |
| 47 | 4. **现有实现对照**:当前仓库代码和文档分别在哪 | 55 | - [training-data-and-pgvector-guide.md](./training-data-and-pgvector-guide.md) — 训练/向量检索说明 |
| 56 | - [open-dataset-workflow.md](./open-dataset-workflow.md) — 开源数据接入流程 | ||
| 48 | 57 | ||
| 49 | --- | 58 | --- |
| 50 | 59 | ||
| 51 | ## 主阅读路径(推荐) | 60 | ## 2. 按角色阅读 |
| 52 | 61 | ||
| 53 | ### 1. 管理 / 架构 / 跨团队负责人 | 62 | ### 产品 / 业务 / 版权策略 |
| 54 | 1. [acr-architecture.md](./acr-architecture.md) | 63 | 1. [start-here.md](./start-here.md) |
| 55 | 2. [sota-evolution-guide.md](./sota-evolution-guide.md) | 64 | 2. [acr-architecture.md](./acr-architecture.md) |
| 56 | 3. [postgresql-data-model.md](./postgresql-data-model.md) | 65 | 3. [project-responsibility-map.md](./project-responsibility-map.md) |
| 57 | 4. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | 66 | 4. [business-export-cookbook.md](./business-export-cookbook.md) |
| 58 | 5. [session-handoff.md](./session-handoff.md) | ||
| 59 | 67 | ||
| 60 | ### 2. 开发 / 数据 / 检索工程师 | 68 | ### 数据 / 平台 / PostgreSQL |
| 61 | 1. [postgresql-data-model.md](./postgresql-data-model.md) | 69 | 1. [postgresql-data-model.md](./postgresql-data-model.md) |
| 62 | 2. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | 70 | 2. [postgres_db_schema_samples.md](./postgres_db_schema_samples.md) |
| 63 | 3. [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) | ||
| 64 | 4. [training-data-and-pgvector-guide.md](./training-data-and-pgvector-guide.md) | ||
| 65 | 5. [acr-architecture.md](./acr-architecture.md) | ||
| 66 | 6. [runbook.md](./runbook.md) | ||
| 67 | |||
| 68 | ### 3. 运维 / 平台 / 服务工程师 | ||
| 69 | 1. [acr-architecture.md](./acr-architecture.md) | ||
| 70 | 2. [postgresql-data-model.md](./postgresql-data-model.md) | ||
| 71 | 3. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | ||
| 72 | 4. [service-api.md](./service-api.md) | ||
| 73 | 5. [runbook.md](./runbook.md) | ||
| 74 | |||
| 75 | ### 4. 模型 / 底座 / 研究工程师 | ||
| 76 | 1. [sota-research-2026.md](./sota-research-2026.md) | ||
| 77 | 2. [sota-evolution-guide.md](./sota-evolution-guide.md) | ||
| 78 | 3. [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) | 71 | 3. [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) |
| 79 | 4. [production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md) | 72 | 4. [runbook.md](./runbook.md) |
| 80 | 5. [training-data-and-pgvector-guide.md](./training-data-and-pgvector-guide.md) | ||
| 81 | |||
| 82 | --- | ||
| 83 | 73 | ||
| 84 | ## 新的核心文档分工 | 74 | ### 算法 / 检索 / 模型 |
| 75 | 1. [sota-evolution-guide.md](./sota-evolution-guide.md) | ||
| 76 | 2. [production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md) | ||
| 77 | 3. [phase1-worker-contract.md](./phase1-worker-contract.md) | ||
| 78 | 4. [sota-research-2026.md](./sota-research-2026.md) | ||
| 85 | 79 | ||
| 86 | | 文档 | 作用 | 适合谁先读 | | 80 | ### 开发 / 实施 / 交付 |
| 87 | |---|---|---| | 81 | 1. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) |
| 88 | | [acr-architecture.md](./acr-architecture.md) | 当前系统蓝图、角色分工、在线/离线链路 | 架构、开发、运维 | | 82 | 2. [session-handoff.md](./session-handoff.md) |
| 89 | | [sota-evolution-guide.md](./sota-evolution-guide.md) | SOTA 演进路径、Phase-1 encoder-only 方案、后续升级路线 | 架构、模型、检索 | | 83 | 3. [CHANGELOG.md](./CHANGELOG.md) |
| 90 | | [postgresql-data-model.md](./postgresql-data-model.md) | PostgreSQL 数据字典、DDL 设计意图、流程图、查询路径 | 数据、后端、检索、平台 | | 84 | 4. [release-checklist.md](./release-checklist.md) |
| 91 | | [postgres_db_schema_samples.md](./postgres_db_schema_samples.md) | PostgreSQL 实际落库样例、live pgvector 测试链路、召回/混淆结果 | 数据、后端、检索、平台 | | ||
| 92 | | [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | Phase-1 落地 checklist,按阶段拆执行项 | 架构、开发、平台 | | ||
| 93 | | [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) | 模型、feature set、reference set 初始化手册 | 模型、检索、数据 | | ||
| 94 | | [training-data-and-pgvector-guide.md](./training-data-and-pgvector-guide.md) | 当前训练/manifest/pgvector 原型链说明 | 开发、数据 | | ||
| 95 | | [session-handoff.md](./session-handoff.md) | 最新状态与续跑上下文 | 新 session 接手人 | | ||
| 96 | 85 | ||
| 97 | --- | 86 | --- |
| 98 | 87 | ||
| 99 | ## 当前实现与未来目标的关系 | 88 | ## 3. 当前最重要的稳定结论 |
| 100 | 89 | ||
| 101 | ```mermaid | 90 | - 目标场景不是普通歌曲推荐,而是 **版权保护 / 听歌识曲 / 版本归属**。 |
| 102 | flowchart LR | 91 | - Phase-1 先走 **encoder-only** 路线,不先微调底座。 |
| 103 | A[当前实现\nChromaprint + ECAPA + Melody Rerank] --> B[Phase-1\nEncoder-only Foundation Backbone] | 92 | - exact lane:`Chromaprint`。 |
| 104 | B --> C[Phase-2\nVersion/Cover Lane + Better Aggregation] | 93 | - semantic baseline:`MERT-v1-95M`。 |
| 105 | C --> D[Phase-3\nIndustrial Retrieval + Reranker + Governance] | 94 | - semantic challenger:`MuQ`。 |
| 95 | - `ECAPA` 保留为 historical baseline,不再作为长期主底座。 | ||
| 96 | - PostgreSQL 主链固定为: | ||
| 97 | |||
| 98 | ```text | ||
| 99 | canonical_song -> work -> recording -> recording_asset -> audio_window | ||
| 106 | ``` | 100 | ``` |
| 107 | 101 | ||
| 108 | - **当前实现** 已验证基础链路可运行。 | 102 | - 模型/特征主链固定为: |
| 109 | - **Phase-1** 目标是:不微调底座,直接上更强开源 encoder,并把 PostgreSQL 数据规范先落稳。 | 103 | |
| 110 | - **Phase-2** 目标是:增强 version / cover / hard-case 归属能力。 | 104 | ```text |
| 111 | - **Phase-3** 目标是:多索引、多角色协作、数据治理、服务化上线。 | 105 | model_registry -> feature_set_registry -> audio_embedding / audio_fingerprint -> retrieval_index_registry |
| 106 | ``` | ||
| 112 | 107 | ||
| 113 | --- | 108 | --- |
| 114 | 109 | ||
| 115 | ## 现有实现入口 | 110 | ## 4. 当前不要浪费时间的方向 |
| 116 | 111 | ||
| 117 | ### 代码入口 | 112 | - 不要回退到只用一个 `song_id` 的扁平结构。 |
| 118 | - `acr-engine/src/engines/chromaprint_matcher.py` | 113 | - 不要把 embedding 存成固定列(如 `mert_embedding` / `muq_embedding`)。 |
| 119 | - `acr-engine/src/engines/ecapa_embedder.py` | 114 | - 不要在 Phase-1 先讨论重新训练底座。 |
| 120 | - `acr-engine/src/engines/hybrid_engine.py` | 115 | - 不要把当前阻塞误判成 PostgreSQL schema 问题;当前主要 blocker 是音频挂载与 runtime 依赖。 |
| 121 | - `acr-engine/src/service/app.py` | ||
| 122 | - `acr-engine/sql/pgvector_schema.sql`(原型版) | ||
| 123 | - `acr-engine/sql/acr_pg_schema_v2.sql`(本轮新增的推荐版) | ||
| 124 | |||
| 125 | ### 历史/补充文档 | ||
| 126 | - [sota-research-2026.md](./sota-research-2026.md) | ||
| 127 | - [production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md) | ||
| 128 | - [project-responsibility-map.md](./project-responsibility-map.md) | ||
| 129 | - [industrialization-roadmap.md](./industrialization-roadmap.md) | ||
| 130 | 116 | ||
| 131 | --- | 117 | --- |
| 132 | 118 | ||
| 133 | ## 如何理解当前文档体系 | 119 | ## 5. 补充但不建议作为第一入口 |
| 134 | |||
| 135 | - **主文档**:优先保证“读完就知道怎么推进” | ||
| 136 | - **历史文档**:保留实验上下文、旧方案与补充解释 | ||
| 137 | - **SQL 文件**:保证可以直接落地数据库原型 | ||
| 138 | 120 | ||
| 139 | 如果你只读 3 份: | 121 | 以下文档保留用于专题补充,不建议新同学第一轮就读: |
| 140 | 1. [acr-architecture.md](./acr-architecture.md) | 122 | - [dataset-spec.md](./dataset-spec.md) |
| 141 | 2. [sota-evolution-guide.md](./sota-evolution-guide.md) | 123 | - [dataset-sources-and-licensing.md](./dataset-sources-and-licensing.md) |
| 142 | 3. [postgresql-data-model.md](./postgresql-data-model.md) | 124 | - [references-and-sources.md](./references-and-sources.md) |
| 125 | - [current-capability-map.md](./current-capability-map.md) | ||
| 126 | - [industrialization-roadmap.md](./industrialization-roadmap.md) | ||
| 127 | - [industrial-benchmark-spec.md](./industrial-benchmark-spec.md) | ||
| 128 | - [benchmark-report-template.md](./benchmark-report-template.md) | ||
| 129 | - [model-card-template.md](./model-card-template.md) | ||
| 130 | - [report-layout.md](./report-layout.md) | ... | ... |
docs/acr-design.md
deleted
100644 → 0
| 1 | # Audio Content Recognition (ACR) System — 听歌识曲引擎设计文档 | ||
| 2 | |||
| 3 | > 版本: v1.0 | 更新: 2026-06-02 | 状态: Draft | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | ## 目录 | ||
| 8 | |||
| 9 | 1. [概述与背景](#1-概述与背景) | ||
| 10 | 2. [解决的问题](#2-解决的问题) | ||
| 11 | 3. [技术原理](#3-技术原理) | ||
| 12 | 4. [系统架构设计](#4-系统架构设计) | ||
| 13 | 5. [数据准备与增强](#5-数据准备与增强) | ||
| 14 | 6. [模型设计](#6-模型设计) | ||
| 15 | 7. [训练细节](#7-训练细节) | ||
| 16 | 8. [推理与匹配策略](#8-推理与匹配策略) | ||
| 17 | 9. [使用方法](#9-使用方法) | ||
| 18 | 10. [SOTA 调研与对比](#10-sota-调研与对比) | ||
| 19 | 11. [Roadmap](#11-roadmap) | ||
| 20 | 12. [Checklist](#12-checklist) | ||
| 21 | 13. [Changelog](#13-changelog) | ||
| 22 | 14. [Handoff 交付清单](#14-handoff-交付清单) | ||
| 23 | 15. [参考与引用](#15-参考与引用) | ||
| 24 | |||
| 25 | --- | ||
| 26 | |||
| 27 | ## 1. 概述与背景 | ||
| 28 | |||
| 29 | ### 1.1 项目目标 | ||
| 30 | |||
| 31 | 构建一个**音频内容识别(Audio Content Recognition, ACR)引擎**,能够根据一段**BGM(背景音乐)**、**哼唱(Humming)**、**录音片段**等音频输入,在歌曲库中快速准确地识别出对应的歌曲。核心能力对标 Shazam、SoundHound、网易云音乐"听歌识曲"等工业级产品。 | ||
| 32 | |||
| 33 | ### 1.2 核心能力 | ||
| 34 | |||
| 35 | | 能力 | 说明 | | ||
| 36 | |------|------| | ||
| 37 | | **BGM 识别** | 输入一段背景音乐,识别原曲 | | ||
| 38 | | **哼唱识别** (Query-by-Humming) | 输入用户哼唱的旋律,识别匹配的歌曲 | | ||
| 39 | | **录音片段识别** | 输入现场录音(含环境噪声),匹配库中歌曲 | | ||
| 40 | | **抗噪鲁棒性** | 在嘈杂环境、低码率、压缩失真下保持准确率 | | ||
| 41 | | **快速检索** | 亿级曲库下毫秒级响应 | | ||
| 42 | | **增量扩展** | 歌曲库可动态增加,无需全量重训练 | | ||
| 43 | |||
| 44 | ### 1.3 命名规范 | ||
| 45 | |||
| 46 | | 术语 | 含义 | | ||
| 47 | |------|------| | ||
| 48 | | **Song / Track** | 库中原始歌曲 | | ||
| 49 | | **Reference** | 歌曲在库中的指纹/特征表示 | | ||
| 50 | | **Query** | 用户输入的待识别音频片段 | | ||
| 51 | | **Fingerprint** | 音频指纹(特征向量或哈希序列) | | ||
| 52 | | **Landmark** | 频谱图中的峰值点,用于构建指纹 | | ||
| 53 | | **Candidate** | 匹配候选歌曲列表 | | ||
| 54 | | **Segment** | 一个Query对应的录音片段或BGM片段 | | ||
| 55 | |||
| 56 | --- | ||
| 57 | |||
| 58 | ## 2. 解决的问题 | ||
| 59 | |||
| 60 | ### 2.1 核心问题域 | ||
| 61 | |||
| 62 | | 问题 | 描述 | 技术挑战 | | ||
| 63 | |------|------|---------| | ||
| 64 | | **音频退化** | Query 可能经过压缩(MP3/AAC)、降采样、远场录制 | 特征需对退化具有不变性 | | ||
| 65 | | **时间截断** | Query 仅为歌曲的中间某一小段(3-15s) | 指纹需支持局部匹配 | | ||
| 66 | | **哼唱偏差** | 用户哼唱的音高、节奏、音色与原曲不同 | 需旋律归一化与音高轮廓匹配 | | ||
| 67 | | **环境噪声** | 录音含背景人声、街道噪声、混响 | 特征提取需有一定抗噪性 | | ||
| 68 | | **速度变化** | Query 播放速度可能快于或慢于原曲(±15%) | 指纹对时间伸缩不敏感 | | ||
| 69 | | **键位偏移** | Query 的调性可能不同于原曲(哼唱场景常见) | 需相对旋律表示而非绝对音高 | | ||
| 70 | | **曲库规模** | 曲库可能达到百万至亿级 | 检索必须依赖哈希/近似最近邻索引 | | ||
| 71 | |||
| 72 | ### 2.2 与现有方案对比 | ||
| 73 | |||
| 74 | | 维度 | 传统指纹法 (Shazam-like) | 深度学习 embedding 法 (本方案) | 混合方案 | | ||
| 75 | |------|------------------------|-------------------------------|---------| | ||
| 76 | | 哼唱识别 | 不支持 | 支持(训练时加入哼唱数据) | 支持 | | ||
| 77 | | 抗噪性 | 中等 | 高(数据增强可大幅提升) | 高 | | ||
| 78 | | 检索速度 | 极快(哈希表) | 快(ANN 索引) | 极快 | | ||
| 79 | | 曲库扩展 | 容易 | 容易(增量索引) | 容易 | | ||
| 80 | | 硬件要求 | 低 | 中等(需 GPU 训练) | 中等 | | ||
| 81 | | 调音适应性 | 差 | 好(对比学习可学到不变性) | 好 | | ||
| 82 | | 时间碎片适应性 | 好 | 好(滑窗机制) | 好 | | ||
| 83 | |||
| 84 | --- | ||
| 85 | |||
| 86 | ## 3. 技术原理 | ||
| 87 | |||
| 88 | ### 3.1 音频信号处理基础 | ||
| 89 | |||
| 90 | #### 3.1.1 短时傅里叶变换 (STFT) | ||
| 91 | |||
| 92 | 音频信号经 STFT 转化为时频表示: | ||
| 93 | |||
| 94 | ``` | ||
| 95 | X(t, f) = Σₙ x[n]·w[n-t]·e^{-j2πfn/N} | ||
| 96 | ``` | ||
| 97 | |||
| 98 | 其中 `w[n]` 为窗函数(Hamming/Hann),典型窗长 1024-4096 samples,步长 256-512 samples。 | ||
| 99 | |||
| 100 | #### 3.1.2 Mel 频谱 | ||
| 101 | |||
| 102 | 将 STFT 的线性频率通过 Mel 滤波器组映射到 Mel 刻度: | ||
| 103 | |||
| 104 | ``` | ||
| 105 | Mel(f) = 2595 · log₁₀(1 + f/700) | ||
| 106 | ``` | ||
| 107 | |||
| 108 | 得到 Mel 频谱图作为模型的 2D 输入特征。Mel 频谱更符合人耳听觉感知,且对高频噪声有一定抑制作用。 | ||
| 109 | |||
| 110 | #### 3.1.3 色谱图 (Chroma Feature) | ||
| 111 | |||
| 112 | 色谱图将频谱能量投影到 12 个半音(C, C#, D, ..., B),对音色和音高变化具有不变性,特别适合哼唱识别。 | ||
| 113 | |||
| 114 | ``` | ||
| 115 | Chroma(t, p) = Σ_{f ∈ pitches_in_class_p} |X(t, f)|² | ||
| 116 | ``` | ||
| 117 | |||
| 118 | #### 3.1.4 谱峰提取 (Spectral Peaks) | ||
| 119 | |||
| 120 | 在频谱图中提取能量峰值点(landmarks),每个 landmark 定义为 `(t, f, energy)`。Shazam 算法基于这些 landmark 构建哈希指纹。 | ||
| 121 | |||
| 122 | #### 3.1.5 哼唱旋律轮廓 (Melody Contour) | ||
| 123 | |||
| 124 | 对于哼唱输入,使用基频(F0)估计提取旋律轮廓线。常用算法: | ||
| 125 | |||
| 126 | - **PYIN** (Probabilistic YIN):基于 YIN 算法的概率改进版 | ||
| 127 | - **CREPE**:基于深度学习的基频估计 | ||
| 128 | - **TorchCREPE**:CREPE 的 PyTorch 实现 | ||
| 129 | |||
| 130 | 旋律轮廓经归一化后得到相对音高序列:`ΔP(t) = P(t) - P(t-1)`。 | ||
| 131 | |||
| 132 | ### 3.2 音频指纹技术 | ||
| 133 | |||
| 134 | #### 3.2.1 传统指纹法 (Shazam Algorithm) | ||
| 135 | |||
| 136 | 1. 对音频做 STFT 得到频谱图 | ||
| 137 | 2. 在时频平面提取能量峰值(landmarks) | ||
| 138 | 3. 对每对 landmark `(f₁, t₁)` 和 `(f₂, t₂)` 构建哈希对: | ||
| 139 | ``` | ||
| 140 | hash = (f₁, f₂, Δt) → (t₁, song_id) | ||
| 141 | ``` | ||
| 142 | 4. 查询时计算 Query 的 landmarks 和 hashes | ||
| 143 | 5. 在哈希表中找到匹配的歌曲候选 | ||
| 144 | 6. 对候选做时间偏移直方图投票,选出最高票歌曲 | ||
| 145 | |||
| 146 | **优点**:极快、曲库可极大、无需训练 | ||
| 147 | **缺点**:对哼唱、速度变化、调性变化不适应 | ||
| 148 | |||
| 149 | #### 3.2.2 深度嵌入法 (Deep Embedding) —— 本方案核心 | ||
| 150 | |||
| 151 | 将音频片段映射到一个固定维度的嵌入向量(如 256 维),在嵌入空间中相似歌曲的 Query 和 Reference 距离接近。 | ||
| 152 | |||
| 153 | **对比学习目标 (Contrastive Learning)**: | ||
| 154 | |||
| 155 | ``` | ||
| 156 | Loss = -log( exp(sim(q, p)/τ) / Σ_{n=1}^{N} exp(sim(q, n)/τ) ) | ||
| 157 | ``` | ||
| 158 | |||
| 159 | 其中 `sim(q, p)` 是 Query 与正样本 Reference 的余弦相似度,`τ` 是温度系数。 | ||
| 160 | |||
| 161 | **核心优势**: | ||
| 162 | |||
| 163 | - 通过对比学习,嵌入对音色、噪声、速度变化、调性变化具有不变性 | ||
| 164 | - 哼唱 Query 可与原曲 Reference 在嵌入空间中对齐 | ||
| 165 | - 支持增量曲库(新歌只需过一次模型生成嵌入) | ||
| 166 | |||
| 167 | ### 3.3 检索策略 | ||
| 168 | |||
| 169 | #### 3.3.1 精确检索 (Brute Force) | ||
| 170 | |||
| 171 | 当库规模 < 10K 时,直接计算 Query 嵌入与所有 Reference 嵌入的余弦相似度。 | ||
| 172 | |||
| 173 | ``` | ||
| 174 | score_i = cosine(query_emb, ref_emb_i) | ||
| 175 | result = argmax(score_i) | ||
| 176 | ``` | ||
| 177 | |||
| 178 | #### 3.3.2 近似最近邻检索 (ANN) | ||
| 179 | |||
| 180 | 当库规模 > 10K 时,使用近似最近邻索引: | ||
| 181 | |||
| 182 | | 算法 | 特点 | 适用场景 | | ||
| 183 | |------|------|---------| | ||
| 184 | | **IVF** | 倒排文件索引,训练聚类中心 | 百万级 | | ||
| 185 | | **IVF + PQ** | 乘积量化压缩向量 | 千万级 | | ||
| 186 | | **HNSW** | 分层导航小世界图 | 亿级,高精度 | | ||
| 187 | | **DiskANN** | 基于 SSD 的图索引 | 十亿级 | | ||
| 188 | |||
| 189 | 推荐使用 **Faiss** 库实现 ANN 检索。 | ||
| 190 | |||
| 191 | #### 3.3.3 级联检索策略 | ||
| 192 | |||
| 193 | ``` | ||
| 194 | Query → 粗筛 (ANN, top-K) → 精排 (余弦相似度) → 时间对齐验证 → Top-1 | ||
| 195 | ``` | ||
| 196 | |||
| 197 | - 粗筛:ANN 检索 Top-50/100 候选 | ||
| 198 | - 精排:计算精确余弦相似度,取 Top-10 | ||
| 199 | - 时间对齐验证:对 Top-10 候选做频谱图谱峰对齐验证,确认时序一致性 | ||
| 200 | |||
| 201 | --- | ||
| 202 | |||
| 203 | ## 4. 系统架构设计 | ||
| 204 | |||
| 205 | ### 4.1 整体架构 | ||
| 206 | |||
| 207 | ``` | ||
| 208 | ┌─────────────────────────────────────────────────────────────┐ | ||
| 209 | │ API Gateway │ | ||
| 210 | └─────────────────────┬───────────────────────────────────────┘ | ||
| 211 | │ | ||
| 212 | ┌─────────────┼─────────────┐ | ||
| 213 | ▼ ▼ ▼ | ||
| 214 | ┌───────────────┐ ┌───────┐ ┌───────────────┐ | ||
| 215 | │ Audio Ingest │ │ Search│ │ Admin Service │ | ||
| 216 | │ (Ingestion) │ │ (QPS) │ │ (管理) │ | ||
| 217 | └───────┬───────┘ └───┬───┘ └───────┬───────┘ | ||
| 218 | │ │ │ | ||
| 219 | ▼ ▼ ▼ | ||
| 220 | ┌─────────────────────────────────────────────────────────────┐ | ||
| 221 | │ Core Engine Layer │ | ||
| 222 | │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │ | ||
| 223 | │ │ Pre- │ │ Feature │ │ Embedder│ │ Matcher │ │ | ||
| 224 | │ │ processor│ │ Extractor│ │ (Model) │ │ (Searcher) │ │ | ||
| 225 | │ └──────────┘ └──────────┘ └──────────┘ └───────────────┘ │ | ||
| 226 | └─────────────────────────────────────────────────────────────┘ | ||
| 227 | │ │ │ | ||
| 228 | ▼ ▼ ▼ | ||
| 229 | ┌─────────────────────────────────────────────────────────────┐ | ||
| 230 | │ Storage Layer │ | ||
| 231 | │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │ | ||
| 232 | │ │ Raw Audio│ │ Finger- │ │ Embedding│ │ Song Metadata │ │ | ||
| 233 | │ │ (S3/OSS) │ │ print DB │ │ Index │ │ (PostgreSQL) │ │ | ||
| 234 | │ └──────────┘ └──────────┘ └──────────┘ └───────────────┘ │ | ||
| 235 | └─────────────────────────────────────────────────────────────┘ | ||
| 236 | ``` | ||
| 237 | |||
| 238 | ### 4.2 模块详细设计 | ||
| 239 | |||
| 240 | #### 4.2.1 Audio Preprocessor | ||
| 241 | |||
| 242 | ``` | ||
| 243 | 输入: raw_audio_bytes / file_path / stream | ||
| 244 | 功能: | ||
| 245 | 1. 格式解码 (MP3, WAV, FLAC, AAC, OGG, M4A) | ||
| 246 | 2. 重采样到统一采样率 (16kHz 或 22.05kHz) | ||
| 247 | 3. 通道合并 (多声道 → 单声道) | ||
| 248 | 4. 归一化 (RMS 归一化到目标响度) | ||
| 249 | 5. 分帧/滑窗 (非重叠或非重叠滑窗,每帧 3-15s) | ||
| 250 | 输出: numpy.ndarray, shape=(samples,) | ||
| 251 | ``` | ||
| 252 | |||
| 253 | #### 4.2.2 Feature Extractor | ||
| 254 | |||
| 255 | ``` | ||
| 256 | 支持多种特征提取策略,可通过配置切换: | ||
| 257 | |||
| 258 | 模式 A: Spectrogram + Log-Mel | ||
| 259 | - STFT: window=2048, hop=512, window_fn=hann | ||
| 260 | - Mel filters: 64/128 bins, fmin=0, fmax=8000 | ||
| 261 | - Log(spectrogram + 1e-6) | ||
| 262 | |||
| 263 | 模式 B: Chroma CQT | ||
| 264 | - Constant Q Transform, 12 bins/octave | ||
| 265 | - 适用于哼唱场景 | ||
| 266 | |||
| 267 | 模式 C: Landmark + Hash (Shazam 兼容) | ||
| 268 | - Peak extraction (2D local maxima) | ||
| 269 | - Target zone pairing for hash construction | ||
| 270 | |||
| 271 | 模式 D: Raw Waveform (可选) | ||
| 272 | - 直接输入原始波形给 1D CNN | ||
| 273 | ``` | ||
| 274 | |||
| 275 | #### 4.2.3 Embedder (深度模型) | ||
| 276 | |||
| 277 | 参见第 [6 节](#6-模型设计)。 | ||
| 278 | |||
| 279 | #### 4.2.4 Matcher / Searcher | ||
| 280 | |||
| 281 | ``` | ||
| 282 | 输入: query_embedding (dim=256) | ||
| 283 | 流程: | ||
| 284 | 1. ANN 检索: Faiss IVF+HNSW, top_k=100 | ||
| 285 | 2. 精排: 计算精确余弦相似度, top_k=10 | ||
| 286 | 3. 时间对齐验证 (可选): | ||
| 287 | - 对 Top-10 候选提取谱峰 | ||
| 288 | - 计算 Query 与候选的时间偏移直方图 | ||
| 289 | - 确认存在一致性偏移峰值 | ||
| 290 | 4. 置信度校准: 计算相似度分布 z-score | ||
| 291 | 5. 输出: sorted_results[ {song_id, score, match_type} ] | ||
| 292 | ``` | ||
| 293 | |||
| 294 | ### 4.3 API 设计 | ||
| 295 | |||
| 296 | ```protobuf | ||
| 297 | // Recognize — 识别音频 | ||
| 298 | service ACRService { | ||
| 299 | // 输入音频返回 Top-N 匹配歌曲 | ||
| 300 | rpc Recognize(RecognizeRequest) returns (RecognizeResponse); | ||
| 301 | |||
| 302 | // 批量入库 | ||
| 303 | rpc IngestSong(IngestSongRequest) returns (IngestSongResponse); | ||
| 304 | |||
| 305 | // 删除歌曲 | ||
| 306 | rpc DeleteSong(DeleteSongRequest) returns (DeleteSongResponse); | ||
| 307 | |||
| 308 | // 健康检查 | ||
| 309 | rpc HealthCheck(Empty) returns (HealthCheckResponse); | ||
| 310 | } | ||
| 311 | |||
| 312 | message RecognizeRequest { | ||
| 313 | bytes audio_data = 1; // 音频数据 | ||
| 314 | string audio_format = 2; // wav, mp3, ogg | ||
| 315 | float duration_sec = 3; // 实际有效时长 (若未知留空) | ||
| 316 | RecognizeMode mode = 4; // AUTO, BGM, HUMMING, RECORDING | ||
| 317 | int32 top_n = 5; // 返回 Top-N (默认 5) | ||
| 318 | } | ||
| 319 | |||
| 320 | enum RecognizeMode { | ||
| 321 | AUTO = 0; // 自动检测模式 | ||
| 322 | BGM = 1; // 纯 BGM 片段 | ||
| 323 | HUMMING = 2; // 哼唱 | ||
| 324 | RECORDING = 3; // 现场录音 | ||
| 325 | } | ||
| 326 | |||
| 327 | message RecognizeResponse { | ||
| 328 | repeated Candidate candidates = 1; | ||
| 329 | float processing_time_ms = 2; | ||
| 330 | } | ||
| 331 | |||
| 332 | message Candidate { | ||
| 333 | string song_id = 1; | ||
| 334 | string title = 2; | ||
| 335 | string artist = 3; | ||
| 336 | float confidence = 4; | ||
| 337 | float matched_begin_sec = 5; // 匹配起始时间 | ||
| 338 | float matched_end_sec = 6; // 匹配结束时间 | ||
| 339 | string match_type = 7; // bgm / humming / recording | ||
| 340 | } | ||
| 341 | ``` | ||
| 342 | |||
| 343 | ### 4.4 存储设计 | ||
| 344 | |||
| 345 | | 数据 | 存储引擎 | 说明 | | ||
| 346 | |------|---------|------| | ||
| 347 | | 原始音频 | S3/MinIO/OSS | 对象存储,按 song_id 组织 | | ||
| 348 | | 歌曲元数据 | PostgreSQL | 标题、歌手、专辑、时长、标签 | | ||
| 349 | | 嵌入向量 | Faiss Index (IVF+HNSW) | 256 维浮点向量 | | ||
| 350 | | 指纹哈希 | Redis / LevelDB | Shazam 兼容指纹键值对 | | ||
| 351 | | 频谱缓存 | Redis / S3 | 预处理后的频谱图缓存 | | ||
| 352 | | 操作日志 | ClickHouse / ELK | 查询日志、性能监控 | | ||
| 353 | |||
| 354 | ### 4.5 部署架构 | ||
| 355 | |||
| 356 | ``` | ||
| 357 | ┌──────────┐ | ||
| 358 | │ LB/Nginx│ | ||
| 359 | └────┬─────┘ | ||
| 360 | │ | ||
| 361 | ┌──────────┼──────────┐ | ||
| 362 | ▼ ▼ ▼ | ||
| 363 | ┌──────────┐ ┌──────────┐ ┌──────────┐ | ||
| 364 | │ API │ │ API │ │ API │ | ||
| 365 | │ Server 1 │ │ Server 2 │ │ Server N │ | ||
| 366 | └────┬─────┘ └────┬─────┘ └────┬─────┘ | ||
| 367 | │ │ │ | ||
| 368 | ▼ ▼ ▼ | ||
| 369 | ┌─────────────────────────────────────┐ | ||
| 370 | │ Faiss Index (Sharded) │ | ||
| 371 | │ GPU/CPU Hybrid │ | ||
| 372 | ├─────────────────────────────────────┤ | ||
| 373 | │ PostgreSQL (RDS) │ | ||
| 374 | ├─────────────────────────────────────┤ | ||
| 375 | │ S3-compatible Object Store │ | ||
| 376 | └─────────────────────────────────────┘ | ||
| 377 | ``` | ||
| 378 | |||
| 379 | --- | ||
| 380 | |||
| 381 | ## 5. 数据准备与增强 | ||
| 382 | |||
| 383 | ### 5.1 数据来源 | ||
| 384 | |||
| 385 | #### 5.1.1 歌曲原始数据 | ||
| 386 | |||
| 387 | | 来源 | 类型 | 规模目标 | 许可注意 | | ||
| 388 | |------|------|---------|---------| | ||
| 389 | | FMA (Free Music Archive) | 开源音乐 | 100K+ 曲 | CC 授权 | | ||
| 390 | | MUSDB18 | 多轨分离数据集 | 150 曲 | 研究用途 | | ||
| 391 | | GTZAN | 流派分类 | 1000 曲 | 研究用途 | | ||
| 392 | | 自行爬取/合作 | 商业音乐 | 1M+ 曲 | 需版权授权 | | ||
| 393 | | 自建录制 | 哼唱/翻唱 | 10K+ 段 | 内部数据 | | ||
| 394 | |||
| 395 | #### 5.1.2 训练数据构造 | ||
| 396 | |||
| 397 | 每个歌曲在库中作为 **Reference**,需为每个 Reference 构造多样化的 **Query** 用于训练。 | ||
| 398 | |||
| 399 | **基础构造逻辑**: | ||
| 400 | ``` | ||
| 401 | song.mp3 → 随机裁剪片段 (3-15s) → 数据增强 → Query | ||
| 402 | song.mp3 → 全曲 → Reference | ||
| 403 | ``` | ||
| 404 | |||
| 405 | #### 5.1.3 哼唱数据 | ||
| 406 | |||
| 407 | 哼唱数据可通过以下方式获取: | ||
| 408 | |||
| 409 | 1. **MIR-QBSH Corpus**:专业哼唱数据集 | ||
| 410 | 2. **自建哼唱数据集**:组织用户录制哼唱旋律 | ||
| 411 | 3. **MIDI 转音频模拟**:将 MIDI 文件通过合成器转为模拟哼唱 | ||
| 412 | 4. **M-Humming**:自行标注的哼唱数据集 | ||
| 413 | |||
| 414 | 哼唱数据格式要求: | ||
| 415 | ``` | ||
| 416 | { | ||
| 417 | "song_id": "song_001", | ||
| 418 | "humming_id": "hum_001", | ||
| 419 | "audio_path": "/data/humming/song_001_hum_001.wav", | ||
| 420 | "original_song_path": "/data/songs/song_001.mp3", | ||
| 421 | "humming_duration_sec": 8.5, | ||
| 422 | "relative_pitch_shift": -2, // 相对原曲的半音偏移 | ||
| 423 | "tempo_ratio": 1.1 // 相对原曲的速度倍率 | ||
| 424 | } | ||
| 425 | ``` | ||
| 426 | |||
| 427 | ### 5.2 数据增强策略 | ||
| 428 | |||
| 429 | 增强的目的是**使模型学到对真实世界干扰的不变性**。 | ||
| 430 | |||
| 431 | #### 5.2.1 基础增强 | ||
| 432 | |||
| 433 | | 增强操作 | 参数范围 | 目标 | | ||
| 434 | |---------|---------|------| | ||
| 435 | | Additive White Gaussian Noise (AWGN) | SNR: 5-30dB | 环境噪声 | | ||
| 436 | | Pink Noise / Brown Noise | SNR: 10-25dB | 自然噪声 | | ||
| 437 | | Band-stop Filtering | 随机 0.5-2kHz 陷波 | 频率缺失 | | ||
| 438 | | Low-pass / High-pass | 截止频率 1-8kHz | 频带限制 | | ||
| 439 | | Time Stretch | 0.85-1.15x | 速度变化 | | ||
| 440 | | Pitch Shift | -6 ~ +6 semitones | 调性变化(哼唱) | | ||
| 441 | | Equalizer Randomization | 随机增益 ±6dB | 音色变化 | | ||
| 442 | | Resampling | 8-44.1kHz | 采样率退化 | | ||
| 443 | | MP3 Compression | 32-128kbps | 压缩失真 | | ||
| 444 | | Reverb | 房间混响模拟 | 远场录音 | | ||
| 445 | | Volume Jitter | -12 ~ 0 dB | 响度变化 | | ||
| 446 | | Time Masking (SpecAug) | 遮罩 10-50 帧 | 局部缺失 | | ||
| 447 | | Frequency Masking (SpecAug) | 遮罩 8-16 bins | 局部频率缺失 | | ||
| 448 | |||
| 449 | #### 5.2.2 哼唱专用增强 | ||
| 450 | |||
| 451 | | 增强操作 | 说明 | | ||
| 452 | |---------|------| | ||
| 453 | | F0 抖动 | 基频随机扰动 ±5% | | ||
| 454 | | 节奏抖动 | 节拍随机扰动 ±10% | | ||
| 455 | | 添加呼吸声 | 插入随机位置的呼吸音 | | ||
| 456 | | 音色变异 | 使用不同的合成器/人声 | | ||
| 457 | | 单音偏差 | 部分音符替换为邻音(模拟跑调) | | ||
| 458 | |||
| 459 | #### 5.2.3 数据增强管线 | ||
| 460 | |||
| 461 | ``` | ||
| 462 | 原始音频 (16kHz mono) | ||
| 463 | │ | ||
| 464 | ├─→ [随机裁剪] 3-15s 随机片段 | ||
| 465 | ├─→ [重采样] 8kHz / 16kHz / 22.05kHz / 44.1kHz 随机选择 | ||
| 466 | ├─→ [响度归一化] RMS = target_loudness | ||
| 467 | ├─→ [噪声叠加] AWGN / Pink / 背景音 按概率叠加 | ||
| 468 | ├─→ [滤波器] 低通/高通/带阻/均衡器 随机选择 | ||
| 469 | ├─→ [时域变化] Time Stretch ±15% | ||
| 470 | ├─→ [频域变化] Pitch Shift ±6 semitones | ||
| 471 | ├─→ [压缩模拟] MP3 编码再解码 (64-128kpbs) | ||
| 472 | ├─→ [混响] 小型/中型/大型房间混响 | ||
| 473 | ├─→ [SpecAug] Time & Frequency Masking | ||
| 474 | └─→ [特征提取] Mel Spectrogram / Chroma / Raw | ||
| 475 | └─→ [输出] 增强后的特征张量 | ||
| 476 | ``` | ||
| 477 | |||
| 478 | 实现:`torchaudio` / `audiomentations` / `librosa` 组合管线。 | ||
| 479 | |||
| 480 | ### 5.3 数据格式与存储 | ||
| 481 | |||
| 482 | **训练数据格式**: | ||
| 483 | |||
| 484 | ``` | ||
| 485 | /data/ | ||
| 486 | ├── songs/ # 原始歌曲 | ||
| 487 | │ ├── song_001.mp3 | ||
| 488 | │ └── ... | ||
| 489 | ├── references/ # 参考指纹/嵌入 | ||
| 490 | │ ├── ref_001.npy # 歌曲全曲或多段嵌入 | ||
| 491 | │ └── ... | ||
| 492 | ├── queries/ # 查询片段 (训练数据) | ||
| 493 | │ ├── train/ | ||
| 494 | │ │ ├── song_001_seg_001.wav | ||
| 495 | │ │ └── ... | ||
| 496 | │ └── val/ | ||
| 497 | │ └── ... | ||
| 498 | ├── metadata.csv # 歌曲元数据 | ||
| 499 | └── train_pairs.csv # (query_path, song_id, type) | ||
| 500 | ``` | ||
| 501 | |||
| 502 | **metadata.csv 格式**: | ||
| 503 | ```csv | ||
| 504 | song_id,title,artist,album,duration_sec,genre,language | ||
| 505 | song_001,Song Title,Artist Name,Album Name,240.5,Pop,en | ||
| 506 | ``` | ||
| 507 | |||
| 508 | **train_pairs.csv 格式**: | ||
| 509 | ```csv | ||
| 510 | query_path,song_id,query_type,augmentation_params | ||
| 511 | queries/train/song_001_seg_001.wav,song_001,bgm,"{snr:15, pitch_shift:0}" | ||
| 512 | queries/train/song_001_hum_001.wav,song_001,humming,"{pitch_shift:-2, tempo:1.1}" | ||
| 513 | ``` | ||
| 514 | |||
| 515 | ### 5.4 数据流水线性能要求 | ||
| 516 | |||
| 517 | | 指标 | 目标 | | ||
| 518 | |------|------| | ||
| 519 | | 增强吞吐 | ≥ 200 样本/秒/GPU | | ||
| 520 | | 预处理缓存 | 频谱图存入 LMDB/RecordIO | | ||
| 521 | | 训练样本总量 | ≥ 5M Query-Reference 对 | | ||
| 522 | | 参考曲库 | ≥ 100K 歌曲(测试阶段) | | ||
| 523 | |||
| 524 | --- | ||
| 525 | |||
| 526 | ## 6. 模型设计 | ||
| 527 | |||
| 528 | ### 6.1 模型架构选型 | ||
| 529 | |||
| 530 | 本方案采用 **双塔结构 (Two-Tower / Siamese Network)**,两塔共享权重。 | ||
| 531 | |||
| 532 | ``` | ||
| 533 | ┌─────────────────────────────────────┐ | ||
| 534 | │ Similarity Score │ | ||
| 535 | │ cosine(q_emb, r_emb) │ | ||
| 536 | └──────────────────┬──────────────────┘ | ||
| 537 | │ | ||
| 538 | ┌────────────────────┴────────────────────┐ | ||
| 539 | ▼ ▼ | ||
| 540 | ┌───────────────┐ ┌───────────────┐ | ||
| 541 | │ Query │ │ Reference │ | ||
| 542 | │ Encoder │ │ Encoder │ | ||
| 543 | │ (shared) │ │ (shared) │ | ||
| 544 | └───────┬───────┘ └───────┬───────┘ | ||
| 545 | │ │ | ||
| 546 | ┌───────┴───────┐ ┌───────┴───────┐ | ||
| 547 | │ Input 1 │ │ Input 2 │ | ||
| 548 | │ (Mel Spec) │ │ (Mel Spec) │ | ||
| 549 | └───────────────┘ └───────────────┘ | ||
| 550 | ``` | ||
| 551 | |||
| 552 | ### 6.2 候选骨干网络 | ||
| 553 | |||
| 554 | #### 方案 A: CNN-Transformer (推荐) | ||
| 555 | |||
| 556 | ``` | ||
| 557 | Input: Mel-Spectrogram (1, 128, T) — 单通道, 128 Mel bins, 变长时间 | ||
| 558 | │ | ||
| 559 | ├─ Conv2D(1→32, 3×3, stride=1) + BN + ReLU | ||
| 560 | ├─ Conv2D(32→64, 3×3, stride=2) + BN + ReLU | ||
| 561 | ├─ Conv2D(64→128, 3×3, stride=2) + BN + ReLU | ||
| 562 | ├─ Conv2D(128→256, 3×3, stride=2) + BN + ReLU | ||
| 563 | │ | ||
| 564 | ├─ Reshape: (batch, T', 256) | ||
| 565 | ├─ Transformer Encoder × 4 (d_model=256, nhead=8, dim_feedforward=1024) | ||
| 566 | ├─ [CLS] Token Pooling / Global Average Pooling | ||
| 567 | ├─ Projection: 256 → 256 (Linear + LayerNorm) | ||
| 568 | └─ L2 Normalize → Embedding (256-dim) | ||
| 569 | ``` | ||
| 570 | |||
| 571 | **总参数量**: ~8-12M | **MACs**: ~2-5G per 5s audio | ||
| 572 | |||
| 573 | #### 方案 B: EfficientNet-ish (轻量级) | ||
| 574 | |||
| 575 | ``` | ||
| 576 | Input: Mel-Spectrogram (3, 128, T) — 拼接近邻帧伪 RGB | ||
| 577 | │ | ||
| 578 | ├─ MBConv blocks (EfficientNet-B0 like) | ||
| 579 | │ - Stem: Conv 3×3, 32ch | ||
| 580 | │ - Stage 1-7: MBConv with SE | ||
| 581 | │ - Head: Conv 1×1, 1280ch | ||
| 582 | ├─ Global Average Pooling | ||
| 583 | ├─ Dropout 0.2 | ||
| 584 | ├─ Projection: 1280 → 256 | ||
| 585 | └─ L2 Normalize → Embedding (256-dim) | ||
| 586 | ``` | ||
| 587 | |||
| 588 | **总参数量**: ~5-8M | **MACs**: ~1-3G per 5s audio | ||
| 589 | |||
| 590 | #### 方案 C: 纯 Attention (AST-like) | ||
| 591 | |||
| 592 | ``` | ||
| 593 | Input: Mel-Spectrogram (1, 128, T) | ||
| 594 | │ | ||
| 595 | ├─ Patch Embedding (16×16 patches) + Position Embedding | ||
| 596 | ├─ Transformer Encoder × 12 (d_model=768, nhead=12) | ||
| 597 | ├─ [CLS] Token | ||
| 598 | ├─ Projection: 768 → 256 | ||
| 599 | └─ L2 Normalize → Embedding (256-dim) | ||
| 600 | ``` | ||
| 601 | |||
| 602 | **总参数量**: ~80-90M | **MACs**: ~5-15G per 5s audio | ||
| 603 | **优势**: 准确率最高 | **劣势**: 推理速度较慢 | ||
| 604 | |||
| 605 | #### 推荐: 方案 A (CNN-Transformer) 作为主选,方案 B 作为备选轻量级。 | ||
| 606 | |||
| 607 | ### 6.3 训练损失函数 | ||
| 608 | |||
| 609 | #### 6.3.1 主损失: SupConLoss (Supervised Contrastive Loss) | ||
| 610 | |||
| 611 | ``` | ||
| 612 | 对于 batch 中每个 anchor a, | ||
| 613 | 正样本集 P(a) = 所有与 a 同歌曲的样本 | ||
| 614 | 负样本集 N(a) = 与 a 不同歌曲的样本 | ||
| 615 | |||
| 616 | L_supcon = Σ_a [ -1/|P(a)| · Σ_{p∈P(a)} log( exp(sim(z_a, z_p)/τ) / Σ_{n∈N(a)∪P(a)} exp(sim(z_a, z_n)/τ) ) ] | ||
| 617 | ``` | ||
| 618 | |||
| 619 | #### 6.3.2 辅助损失: ArcFace / CosFace (可选) | ||
| 620 | |||
| 621 | 当曲库有固定类别标签时,可附加分类损失: | ||
| 622 | |||
| 623 | ``` | ||
| 624 | L_arcface = -log( exp(s·cos(θ_y + m)) / (exp(s·cos(θ_y + m)) + Σ_j≠y exp(s·cos θ_j)) ) | ||
| 625 | ``` | ||
| 626 | |||
| 627 | #### 6.3.3 总损失 | ||
| 628 | |||
| 629 | ``` | ||
| 630 | L_total = λ₁ · L_supcon + λ₂ · L_arcface + λ₃ · L_triplet | ||
| 631 | ``` | ||
| 632 | |||
| 633 | 推荐 `λ₁=1.0, λ₂=0.3, λ₃=0.1`。 | ||
| 634 | |||
| 635 | ### 6.4 哼唱识别专用模块 | ||
| 636 | |||
| 637 | 对于哼唱输入,在主干网络外增加一个**旋律编码分支**: | ||
| 638 | |||
| 639 | ``` | ||
| 640 | 哼唱音频 | ||
| 641 | │ | ||
| 642 | ├─ F0 估计 (CREPE / PYIN) → F0 轮廓 (hourglass-shaped) | ||
| 643 | ├─ Chroma CQT → 12-bin 色谱图 | ||
| 644 | │ | ||
| 645 | ├─ 可选融合策略: | ||
| 646 | │ A) 早融合 (Early Fusion): Mel + Chroma 通道拼接 → 同一网络 | ||
| 647 | │ B) 晚融合 (Late Fusion): Mel 分支 + Chroma 分支分别编码 → 拼接嵌入 | ||
| 648 | │ C) 分叉网络 (Forked): 共享底层特征层,高层分支出 Mel 和 Chroma 特征 | ||
| 649 | │ | ||
| 650 | └─ → 256-dim Embedding | ||
| 651 | ``` | ||
| 652 | |||
| 653 | 推荐使用 **晚融合** 方案,在训练时将 Mel 特征和 Chroma 特征分别经过共享底层后拼接,再投影到 256 维。 | ||
| 654 | |||
| 655 | ### 6.5 多尺度匹配策略 | ||
| 656 | |||
| 657 | 由于 Query 长度可变(3-15s),使用多尺度滑窗: | ||
| 658 | |||
| 659 | ``` | ||
| 660 | Reference (全曲 3min): | ||
| 661 | [───── Window 1 (5s) ─────] | ||
| 662 | [───── Window 2 (5s) ─────] | ||
| 663 | [───── Window 3 (5s) ─────] | ||
| 664 | ... (stride = 2.5s) | ||
| 665 | |||
| 666 | 每个窗口 → Reference Embedding Matrix: (num_windows, 256) | ||
| 667 | |||
| 668 | Query (5s) → Query Embedding: (1, 256) | ||
| 669 | |||
| 670 | 匹配: max_sim = max(sim(query_emb, ref_window_emb_i) for i in windows) | ||
| 671 | ``` | ||
| 672 | |||
| 673 | --- | ||
| 674 | |||
| 675 | ## 7. 训练细节 | ||
| 676 | |||
| 677 | ### 7.1 实验环境 | ||
| 678 | |||
| 679 | | 配置 | 规格 | | ||
| 680 | |------|------| | ||
| 681 | | GPU | NVIDIA A100 (80GB) × 4 | | ||
| 682 | | CPU | AMD EPYC 64C / Intel Xeon 48C | | ||
| 683 | | RAM | 512 GB | | ||
| 684 | | 存储 | NVMe SSD 4TB | | ||
| 685 | | 框架 | PyTorch 2.x + Lightning / FSDP | | ||
| 686 | | 加速 | Flash Attention, torch.compile | | ||
| 687 | | 监控 | W&B / MLflow | | ||
| 688 | |||
| 689 | ### 7.2 超参数 | ||
| 690 | |||
| 691 | | 参数 | 值 | 备注 | | ||
| 692 | |------|-----|------| | ||
| 693 | | Audio SR | 16000 Hz | 统一采样率 | | ||
| 694 | | Frame Size | 1024 (~64ms) | STFT 窗长 | | ||
| 695 | | Hop Size | 512 (~32ms) | STFT 步长 | | ||
| 696 | | Mel Bins | 128 | 梅尔滤波器数量 | | ||
| 697 | | Max Duration | 10s | 训练时音频截断长度 | | ||
| 698 | | Embedding Dim | 256 | 嵌入向量维度 | | ||
| 699 | | Batch Size | 512-1024 | 分布式训练 | | ||
| 700 | | Optimizer | AdamW | β=(0.9, 0.999) | | ||
| 701 | | Learning Rate | 3e-4 | Cosine Annealing | | ||
| 702 | | Weight Decay | 0.01 | L2 正则化 | | ||
| 703 | | Warmup Steps | 5000 | Linear Warmup | | ||
| 704 | | Epochs | 100-200 | Early Stopping | | ||
| 705 | | Temperature τ | 0.07 | 对比学习温度 | | ||
| 706 | | Label Smoothing | 0.1 | 防止过拟合 | | ||
| 707 | | Gradient Clipping | 1.0 | Max norm | | ||
| 708 | | Mixed Precision | bfloat16 | 加速训练 | | ||
| 709 | | Scheduler | Cosine Decay | Warm restarts | | ||
| 710 | |||
| 711 | ### 7.3 训练流程 | ||
| 712 | |||
| 713 | ``` | ||
| 714 | Step 1: 数据准备 | ||
| 715 | 1. 收集原始歌曲 → 16kHz mono → 存储为 WAV | ||
| 716 | 2. 随机裁剪 + 数据增强 → 生成 Query/Reference 对 | ||
| 717 | 3. 提取 Mel 频谱 → 存储为 .npy (可选在线提取) | ||
| 718 | 4. 分割 train/val/test (80/10/10) | ||
| 719 | |||
| 720 | Step 2: 预训练 (可选) | ||
| 721 | 1. 在大规模无标签数据上使用 SimCLR / BYOL 做自监督预训练 | ||
| 722 | 2. 或使用公开预训练权重 (AudioMAE, CLAIR, CLAP) | ||
| 723 | |||
| 724 | Step 3: 有监督对比学习训练 | ||
| 725 | 1. 加载预训练权重或从头初始化 | ||
| 726 | 2. 每个 batch: 从 B 个歌曲各取 K 个片段 → B×K 样本 | ||
| 727 | 3. 计算 SupConLoss + 辅助损失 | ||
| 728 | 4. 每 N 步验证集评估 Recall@1, Recall@5 | ||
| 729 | 5. 最佳模型保存 checkpoint | ||
| 730 | |||
| 731 | Step 4: 哼唱微调 (可选阶段) | ||
| 732 | 1. 使用哼唱数据 + 数据增强对模型做有监督微调 | ||
| 733 | 2. 固定部分底层参数,微调顶层和高层 Transformer | ||
| 734 | 3. Learning rate: 1e-5 (较小) | ||
| 735 | |||
| 736 | Step 5: 索引构建 | ||
| 737 | 1. 对所有歌曲提取 Reference Embeddings | ||
| 738 | 2. 使用 Faiss 构建 IVF+HNSW 索引 | ||
| 739 | 3. 评估索引准确率与检索速度 | ||
| 740 | ``` | ||
| 741 | |||
| 742 | ### 7.4 评估指标 | ||
| 743 | |||
| 744 | | 指标 | 说明 | 目标值 | | ||
| 745 | |------|------|--------| | ||
| 746 | | **Recall@1** | Top-1 准确率 | ≥ 90% (BGM), ≥ 80% (哼唱) | | ||
| 747 | | **Recall@5** | Top-5 召回率 | ≥ 95% (BGM), ≥ 90% (哼唱) | | ||
| 748 | | **MRR** | Mean Reciprocal Rank | ≥ 0.9 | | ||
| 749 | | **mAP** | Mean Average Precision | ≥ 0.88 | | ||
| 750 | | **QPS** | Queries Per Second (单 GPU) | ≥ 500 | | ||
| 751 | | **P50 Latency** | 中位数响应时间 | ≤ 100ms | | ||
| 752 | | **P99 Latency** | 99% 响应时间 | ≤ 500ms | | ||
| 753 | | **Index Build** | 10万曲库索引构建时间 | ≤ 30min | | ||
| 754 | | **Index Size** | 索引占用内存 | ≤ 2GB (100K 曲) | | ||
| 755 | |||
| 756 | ### 7.5 消融实验设计 | ||
| 757 | |||
| 758 | | 实验 | 变量 | 预期验证目标 | | ||
| 759 | |------|------|------------| | ||
| 760 | | 特征对比 | Mel vs Chroma vs CQT vs Raw | 最优输入特征 | | ||
| 761 | | 骨干对比 | CNN vs CNN-Tfm vs AST vs EffNet | 最优架构 | | ||
| 762 | | 嵌入维度 | 64 vs 128 vs 256 vs 512 | 性能-容量平衡 | | ||
| 763 | | 对比损失 | SupCon vs Triplet vs NT-Xent vs ArcFace | 最优损失函数 | | ||
| 764 | | 温度系数 | τ=0.05, 0.07, 0.1, 0.2 | 最优温度 | | ||
| 765 | | 数据增强 | 无增强 vs 基础 vs 全部 | 增强贡献度 | | ||
| 766 | | 哼唱策略 | 早融合 vs 晚融合 vs 分叉 | 最优融合方式 | | ||
| 767 | | 曲库抗噪 | 添加噪声曲库干扰 | 抗干扰能力 | | ||
| 768 | |||
| 769 | ### 7.6 分布式训练策略 | ||
| 770 | |||
| 771 | ```bash | ||
| 772 | # 使用 PyTorch DDP / FSDP | ||
| 773 | torchrun --nproc_per_node=8 train.py \ | ||
| 774 | --batch_size 64 \ | ||
| 775 | --model cnn_transformer \ | ||
| 776 | --embed_dim 256 \ | ||
| 777 | --max_duration 10 \ | ||
| 778 | --lr 3e-4 \ | ||
| 779 | --epochs 200 \ | ||
| 780 | --warmup 5000 \ | ||
| 781 | --fp16 \ | ||
| 782 | --dataset_path /data/acr \ | ||
| 783 | --save_interval 10 | ||
| 784 | ``` | ||
| 785 | |||
| 786 | --- | ||
| 787 | |||
| 788 | ## 8. 推理与匹配策略 | ||
| 789 | |||
| 790 | ### 8.1 推理流程 | ||
| 791 | |||
| 792 | ``` | ||
| 793 | 用户输入 Query (任意时长) | ||
| 794 | │ | ||
| 795 | ├─ 1. 音频预处理 (重采样+通道合并+归一化) | ||
| 796 | ├─ 2. 滑窗切片 (5s 窗口, 2.5s 步长) | ||
| 797 | │ 如果 Query < 3s: 补充静音到 3s → 拒绝/低置信度 | ||
| 798 | │ 如果 3s ≤ Query ≤ 15s: 单窗口或最多 2 窗口 | ||
| 799 | │ 如果 Query > 15s: 多窗口 5s 滑窗 | ||
| 800 | │ | ||
| 801 | ├─ 3. 特征提取 (Mel Spectrogram) | ||
| 802 | │ | ||
| 803 | ├─ 4. 嵌入推理 (模型 forward) → query_embs: (num_windows, 256) | ||
| 804 | │ | ||
| 805 | ├─ 5. 候选检索 | ||
| 806 | │ a) 对每个窗口嵌入做 ANN 检索 → Top-50 × num_windows | ||
| 807 | │ b) 合并候选并去重 → Top-100 | ||
| 808 | │ c) 精排: 精确相似度计算 → Top-10 | ||
| 809 | │ | ||
| 810 | ├─ 6. (Optional) 时间对齐验证 | ||
| 811 | │ - 对 Top-10 候选提取频谱图峰值 | ||
| 812 | │ - 计算与 Query 的时间偏移直方图 | ||
| 813 | │ - 一致性验证 → 更新置信度 | ||
| 814 | │ | ||
| 815 | ├─ 7. 置信度校准 | ||
| 816 | │ - 计算 query_embs 与各候选嵌入的最大相似度 | ||
| 817 | │ - Z-score 标准化: score_z = (score - μ_candidates) / σ_candidates | ||
| 818 | │ - 应用阈值 (score_z > 2.0 或直接阈值 > 0.7) | ||
| 819 | │ | ||
| 820 | └─ 8. 输出结果 | ||
| 821 | ``` | ||
| 822 | |||
| 823 | ### 8.2 流式推理 (Streaming) | ||
| 824 | |||
| 825 | 对于长音频流 (如直播、电台监听),支持流式识别: | ||
| 826 | |||
| 827 | ``` | ||
| 828 | 音频流输入 (16kHz, 实时) | ||
| 829 | │ | ||
| 830 | ├─ 环形缓冲区 (Ring Buffer, 15s 容量) | ||
| 831 | ├─ 每积累 2.5s 新音频 → 触发一次识别 | ||
| 832 | ├─ 取: 缓冲区末尾 5s 作为当前 Query | ||
| 833 | ├─ 嵌入 → ANN 检索 (使用缓存减少重复计算) | ||
| 834 | ├─ 结果缓存与平滑: 连续 N 次命中同一歌曲 → 确认输出 | ||
| 835 | └─ 重复 | ||
| 836 | ``` | ||
| 837 | |||
| 838 | ### 8.3 拒绝策略 (Rejection) | ||
| 839 | |||
| 840 | 当 Query 不在库中时,应可靠地拒绝(低误报率): | ||
| 841 | |||
| 842 | | 策略 | 实现 | | ||
| 843 | |------|------| | ||
| 844 | | 绝对阈值 | max_score < 0.5 → 拒绝 | | ||
| 845 | | 相对阈值 | max_score - second_score < 0.15 → 拒绝 | | ||
| 846 | | 分布阈值 | max_score < μ_candidates + 2·σ_candidates → 拒绝 | | ||
| 847 | | 混合策略 | 三者加权组合 | | ||
| 848 | | 验证分支 | 增加"非歌分类"头,判断输入是否为有效音乐 | | ||
| 849 | |||
| 850 | ### 8.4 缓存策略 | ||
| 851 | |||
| 852 | ``` | ||
| 853 | Query → 特征 Cache (LRU): | ||
| 854 | - Key: audio_hash (MD5 of first 2s) | ||
| 855 | - Value: (query_embedding, timestamp) | ||
| 856 | - TTL: 30 分钟 | ||
| 857 | - Max size: 10K entries | ||
| 858 | |||
| 859 | 热门歌曲 Cache: | ||
| 860 | - 频繁命中的歌曲嵌入常驻内存 | ||
| 861 | - 使用 LFU eviction | ||
| 862 | ``` | ||
| 863 | |||
| 864 | --- | ||
| 865 | |||
| 866 | ## 9. 使用方法 | ||
| 867 | |||
| 868 | ### 9.1 安装 | ||
| 869 | |||
| 870 | ```bash | ||
| 871 | # 克隆仓库 | ||
| 872 | git clone <repo-url> && cd acr-engine | ||
| 873 | |||
| 874 | # 创建环境 | ||
| 875 | conda create -n acr python=3.11 && conda activate acr | ||
| 876 | |||
| 877 | # 安装依赖 | ||
| 878 | pip install -r requirements.txt | ||
| 879 | |||
| 880 | # 可选: GPU 版 Faiss | ||
| 881 | pip install faiss-gpu | ||
| 882 | |||
| 883 | # 安装 torchaudio (含 CUDA) | ||
| 884 | pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu121 | ||
| 885 | ``` | ||
| 886 | |||
| 887 | ### 9.2 数据导入 | ||
| 888 | |||
| 889 | ```bash | ||
| 890 | # 批量导入歌曲到曲库 | ||
| 891 | python scripts/ingest.py \ | ||
| 892 | --input /data/music_library/ \ | ||
| 893 | --format mp3 \ | ||
| 894 | --recursive \ | ||
| 895 | --metadata metadata.csv | ||
| 896 | |||
| 897 | # 导入单曲 | ||
| 898 | python scripts/ingest.py --input song.mp3 --song-id "song_001" | ||
| 899 | ``` | ||
| 900 | |||
| 901 | ### 9.3 训练 | ||
| 902 | |||
| 903 | ```bash | ||
| 904 | # 完整训练流程 | ||
| 905 | python train.py \ | ||
| 906 | --config configs/default.yaml \ | ||
| 907 | --data /data/acr/ \ | ||
| 908 | --output /models/acr/ \ | ||
| 909 | --epochs 200 \ | ||
| 910 | --gpus 4 | ||
| 911 | |||
| 912 | # 继续训练 (从 checkpoint) | ||
| 913 | python train.py --resume /models/acr/checkpoint_epoch_100.ckpt | ||
| 914 | |||
| 915 | # 哼唱微调 | ||
| 916 | python train.py \ | ||
| 917 | --config configs/humming_finetune.yaml \ | ||
| 918 | --resume /models/acr/pretrained.ckpt \ | ||
| 919 | --data /data/humming/ | ||
| 920 | ``` | ||
| 921 | |||
| 922 | ### 9.4 索引构建 | ||
| 923 | |||
| 924 | ```bash | ||
| 925 | # 构建 Faiss 索引 | ||
| 926 | python scripts/build_index.py \ | ||
| 927 | --model /models/acr/best.ckpt \ | ||
| 928 | --songs /data/songs/ \ | ||
| 929 | --output /index/acr_index.faiss \ | ||
| 930 | --index-type "IVF4096,PQ16" \ | ||
| 931 | --gpu | ||
| 932 | ``` | ||
| 933 | |||
| 934 | ### 9.5 API 服务启动 | ||
| 935 | |||
| 936 | ```bash | ||
| 937 | # 启动 REST API (HTTP) | ||
| 938 | python serve.py \ | ||
| 939 | --model /models/acr/best.ckpt \ | ||
| 940 | --index /index/acr_index.faiss \ | ||
| 941 | --port 8088 \ | ||
| 942 | --workers 4 | ||
| 943 | |||
| 944 | # 启动 gRPC 服务 (推荐生产使用) | ||
| 945 | python serve.py --mode grpc --port 50051 | ||
| 946 | |||
| 947 | # 使用 Docker Compose | ||
| 948 | docker-compose up -d | ||
| 949 | ``` | ||
| 950 | |||
| 951 | ### 9.6 客户端调用 | ||
| 952 | |||
| 953 | **Python 客户端**: | ||
| 954 | ```python | ||
| 955 | import requests | ||
| 956 | |||
| 957 | url = "http://localhost:8088/v1/recognize" | ||
| 958 | files = {"audio": open("query.wav", "rb")} | ||
| 959 | params = {"top_n": 5, "mode": "auto"} | ||
| 960 | |||
| 961 | resp = requests.post(url, files=files, params=params) | ||
| 962 | print(resp.json()) | ||
| 963 | # { | ||
| 964 | # "candidates": [ | ||
| 965 | # {"song_id": "...", "title": "...", "artist": "...", | ||
| 966 | # "confidence": 0.92, "match_type": "bgm"} | ||
| 967 | # ], | ||
| 968 | # "processing_time_ms": 45.2 | ||
| 969 | # } | ||
| 970 | ``` | ||
| 971 | |||
| 972 | **命令行**: | ||
| 973 | ```bash | ||
| 974 | # 识别本地音频文件 | ||
| 975 | python cli.py recognize --audio query.mp3 --top-n 5 | ||
| 976 | |||
| 977 | # 录音识别 (麦克风) | ||
| 978 | python cli.py recognize --mic --duration 5 | ||
| 979 | |||
| 980 | # 流式识别 (文件) | ||
| 981 | python cli.py stream --input live_audio.wav --interval 2.5 | ||
| 982 | ``` | ||
| 983 | |||
| 984 | ### 9.7 SDK 集成 | ||
| 985 | |||
| 986 | ``` | ||
| 987 | Python: pip install acr-sdk | ||
| 988 | Go: go get github.com/xxx/acr-go | ||
| 989 | Rust: cargo add acr-rs | ||
| 990 | Java: Maven: com.xxx:acr-client:1.0 | ||
| 991 | ``` | ||
| 992 | |||
| 993 | **Python SDK 使用示例**: | ||
| 994 | ```python | ||
| 995 | from acr_sdk import ACRClient | ||
| 996 | |||
| 997 | client = ACRClient(endpoint="localhost:50051", mode="grpc") | ||
| 998 | |||
| 999 | # 识别 | ||
| 1000 | result = client.recognize("query.wav", mode="humming") | ||
| 1001 | print(f"Song: {result.title}, Confidence: {result.confidence:.2f}") | ||
| 1002 | |||
| 1003 | # 批量入库 | ||
| 1004 | client.ingest("/data/new_songs/") | ||
| 1005 | |||
| 1006 | # 删除 | ||
| 1007 | client.delete_song("song_001") | ||
| 1008 | ``` | ||
| 1009 | |||
| 1010 | --- | ||
| 1011 | |||
| 1012 | ## 10. SOTA 调研与对比 | ||
| 1013 | |||
| 1014 | ### 10.1 学术界 SOTA | ||
| 1015 | |||
| 1016 | | 方法 | 年份 | 核心思想 | 哼唱支持 | Recall@1 (BGM) | Recall@1 (Humming) | | ||
| 1017 | |------|------|---------|---------|---------------|-------------------| | ||
| 1018 | | **Shazam** (Wang) | 2003 | 谱峰哈希指纹 | ❌ | ~85%* | N/A | | ||
| 1019 | | **SoundHound** | 2006 | 旋律轮廓+指纹 | ✅ | ~88%* | ~75%* | | ||
| 1020 | | **Dejavu** | 2015 | Shazam 开源实现 | ❌ | ~82% | N/A | | ||
| 1021 | | **MatchNet** | 2018 | Siamese CNN + Triplet | ❌ | ~90% | N/A | | ||
| 1022 | | **CLAP** (LAION) | 2023 | 对比语言-音频预训练 | ❌ | ~87% | N/A | | ||
| 1023 | | **AudioMAE** | 2023 | 掩码自编码器预训练 | ❌ | ~85% | N/A | | ||
| 1024 | | **Contrastive Audio** (Oord) | 2018 | CPC + 对比学习 | ❌ | ~86% | N/A | | ||
| 1025 | | **HummingBird** | 2024 | Chroma + 对比学习 | ✅ | ~91% | ~82% | | ||
| 1026 | | **Singer** (ByteDance) | 2024 | 多任务对比学习 | ✅ | ~93% | ~85% | | ||
| 1027 | | **Ours** | 2026 | CNN-Tfm + SupCon + 哼唱融合 | ✅ | ≥92% | ≥83% | | ||
| 1028 | |||
| 1029 | *\* 为公开披露的估计值,非学术基准* | ||
| 1030 | |||
| 1031 | ### 10.2 工业界产品对比 | ||
| 1032 | |||
| 1033 | | 产品 | 识别速度 | BGM 准确率 | 哼唱准确率 | 曲库规模 | 延迟 | | ||
| 1034 | |------|---------|-----------|-----------|---------|------| | ||
| 1035 | | **Shazam (Apple)** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ❌ | 亿级 | ~2s | | ||
| 1036 | | **SoundHound** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 千万级 | ~3s | | ||
| 1037 | | **网易云音乐** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 千万级 | ~2s | | ||
| 1038 | | **QQ音乐** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | 千万级 | ~2s | | ||
| 1039 | | **Google Sound Search** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | 亿级 | ~3s | | ||
| 1040 | | **Ours** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 百万级(初期) | ≤0.5s | | ||
| 1041 | |||
| 1042 | ### 10.3 本方案的边际优势 (vs 现有方案) | ||
| 1043 | |||
| 1044 | 1. **哼唱融合训练**:通过专用的哼唱增强和对比学习策略,哼唱识别准确率显著优于纯指纹方案 | ||
| 1045 | 2. **混合架构**:CNN-Transformer 比纯 CNN 有更好的序列建模能力,比纯 Transformer 更高效 | ||
| 1046 | 3. **级联检索**:ANN 粗筛 + 精确重排 + 时间对齐验证,兼顾速度与精度 | ||
| 1047 | 4. **数据增强系统**:全面的增强策略涵盖 BGM、哼唱、录音三大场景 | ||
| 1048 | 5. **可扩展性**:增量索引支持动态歌库,无需重训练 | ||
| 1049 | |||
| 1050 | --- | ||
| 1051 | |||
| 1052 | ## 11. Roadmap | ||
| 1053 | |||
| 1054 | ### 11.1 阶段规划 | ||
| 1055 | |||
| 1056 | ``` | ||
| 1057 | Phase 0: 基础建设 (Week 1-2) | ||
| 1058 | ├── 环境搭建与依赖配置 | ||
| 1059 | ├── 数据探索与预处理 pipeline | ||
| 1060 | ├── 基础特征提取模块 (Mel, Chroma, CQT) | ||
| 1061 | ├── 数据增强模块 (audiomentations pipeline) | ||
| 1062 | └── 基线模型: Shazam 式指纹法 (Dejavu fork) | ||
| 1063 | |||
| 1064 | Phase 1: V1 MVP (Week 3-6) | ||
| 1065 | ├── CNN-Transformer 模型实现 | ||
| 1066 | ├── SupConLoss 训练管线 | ||
| 1067 | ├── 基础数据收集 (FMA + MUSDB18 + GTZAN) | ||
| 1068 | ├── 训练 100K Query-Reference 对的模型 | ||
| 1069 | ├── Faiss 索引构建 Pipeline | ||
| 1070 | ├── REST API + gRPC 服务 | ||
| 1071 | └── 本地 CLI 工具 | ||
| 1072 | |||
| 1073 | Phase 2: 哼唱支持 (Week 7-10) | ||
| 1074 | ├── 哼唱数据收集 (内部录制 + MIR-QBSH) | ||
| 1075 | ├── 哼唱增强 Pipeline | ||
| 1076 | ├── Chroma 分支 + 旋律轮廓编码 | ||
| 1077 | ├── 哼唱-原曲对比学习微调 | ||
| 1078 | ├── 哼唱专用评估集构建 | ||
| 1079 | └── 哼唱模式 API 支持 | ||
| 1080 | |||
| 1081 | Phase 3: 生产优化 (Week 11-14) | ||
| 1082 | ├── 模型量化 (INT8 / FP16) | ||
| 1083 | ├── ONNX Runtime / TensorRT 部署 | ||
| 1084 | ├── 级联检索策略优化 | ||
| 1085 | ├── 缓存系统实现 (LRU + LFU) | ||
| 1086 | ├── 流式识别支持 | ||
| 1087 | ├── 负载测试与性能调优 | ||
| 1088 | ├── Docker + K8s 部署配置 | ||
| 1089 | └── CI/CD Pipeline | ||
| 1090 | |||
| 1091 | Phase 4: 进阶能力 (Week 15-20) | ||
| 1092 | ├── 分布式曲库 (Index Sharding) | ||
| 1093 | ├── 多语言歌曲支持 | ||
| 1094 | ├── 歌曲翻唱/Remix 识别 | ||
| 1095 | ├── 歌曲定位 (识别到歌曲中具体位置) | ||
| 1096 | ├── 歌词时间轴对齐 | ||
| 1097 | ├── Web dashboard (曲库管理 + 监控) | ||
| 1098 | ├── 增量学习 (在线模型更新) | ||
| 1099 | └── 边缘端部署 (移动端/嵌入式) | ||
| 1100 | |||
| 1101 | Phase 5: 持续迭代 (Week 21+) | ||
| 1102 | ├── 用户反馈环路 | ||
| 1103 | ├── A/B 测试框架 | ||
| 1104 | ├── 模型持续训练 (CT) | ||
| 1105 | ├── 数据处理自动化 | ||
| 1106 | ├── 新 SOTA 方法集成 | ||
| 1107 | ├── 商业合作接入 | ||
| 1108 | └── 合规与版权管理 | ||
| 1109 | ``` | ||
| 1110 | |||
| 1111 | ### 11.2 里程碑 | ||
| 1112 | |||
| 1113 | | 里程碑 | 时间 | 交付物 | 验收标准 | | ||
| 1114 | |--------|------|--------|---------| | ||
| 1115 | | M0: 基础准备 | Week 2 | 开发环境、数据管线 | 增强管线吞吐 ≥ 200/秒 | | ||
| 1116 | | M1: V1 MVP | Week 6 | 可运行的识别引擎 | Recall@1 ≥ 85% (BGM) | | ||
| 1117 | | M2: 哼唱上线 | Week 10 | 哼唱识别能力 | Recall@1 ≥ 75% (Humming) | | ||
| 1118 | | M3: 生产就绪 | Week 14 | 高性能服务 | P50 ≤ 100ms, QPS ≥ 500 | | ||
| 1119 | | M4: 进阶能力 | Week 20 | 企业级平台 | 多场景覆盖, 曲库 100 万+ | | ||
| 1120 | |||
| 1121 | --- | ||
| 1122 | |||
| 1123 | ## 12. Checklist | ||
| 1124 | |||
| 1125 | ### 12.1 数据准备 | ||
| 1126 | |||
| 1127 | - [ ] 确定数据来源并获取授权 | ||
| 1128 | - [ ] 下载并组织原始歌曲库 (≥ 100K songs) | ||
| 1129 | - [ ] 统一转为 16kHz mono WAV 格式 | ||
| 1130 | - [ ] 实现数据增强管线 (全部增强策略) | ||
| 1131 | - [ ] 生成训练 Query-Reference 对 (≥ 5M pairs) | ||
| 1132 | - [ ] 构建哼唱数据集 (≥ 10K 段) | ||
| 1133 | - [ ] 分割 train/val/test (80/10/10) | ||
| 1134 | - [ ] 验证数据分布多样性 (流派、语言、年代) | ||
| 1135 | - [ ] 实现数据加载器 (支持在线增强) | ||
| 1136 | - [ ] 数据版本控制 (DVC / HuggingFace Datasets) | ||
| 1137 | |||
| 1138 | ### 12.2 模型开发 | ||
| 1139 | |||
| 1140 | - [ ] 实现基础 CNN-Transformer 骨干 | ||
| 1141 | - [ ] 实现训练循环 (SupConLoss + 辅助损失) | ||
| 1142 | - [ ] 实现哼唱分支 (Chroma + F0 融合) | ||
| 1143 | - [ ] 实现多尺度滑窗匹配 | ||
| 1144 | - [ ] 实现基准模型 (Shazam + Dejavu) | ||
| 1145 | - [ ] 实现对比实验框架 | ||
| 1146 | - [ ] 超参数搜索 (学习率、温度、嵌入维度等) | ||
| 1147 | - [ ] 训练收敛验证 | ||
| 1148 | |||
| 1149 | ### 12.3 索引与检索 | ||
| 1150 | |||
| 1151 | - [ ] 实现 Faiss 索引构建管线 | ||
| 1152 | - [ ] 实现 ANN + 精确重排的级联检索 | ||
| 1153 | - [ ] 实现时间对齐验证 | ||
| 1154 | - [ ] 实现置信度校准与拒绝策略 | ||
| 1155 | - [ ] 索引增量更新 (增删歌曲) | ||
| 1156 | - [ ] 索引持久化与加载优化 | ||
| 1157 | |||
| 1158 | ### 12.4 服务部署 | ||
| 1159 | |||
| 1160 | - [ ] 实现 REST API (FastAPI / Flask) | ||
| 1161 | - [ ] 实现 gRPC API | ||
| 1162 | - [ ] 模型导出 (ONNX / TorchScript) | ||
| 1163 | - [ ] 模型量化 (INT8 / FP16) | ||
| 1164 | - [ ] 实现流式识别 | ||
| 1165 | - [ ] 实现缓存系统 | ||
| 1166 | - [ ] 负载测试 & 性能调优 | ||
| 1167 | - [ ] Docker 镜像构建 | ||
| 1168 | - [ ] Docker Compose / K8s 配置文件 | ||
| 1169 | - [ ] 监控与告警 (Prometheus + Grafana) | ||
| 1170 | - [ ] 日志系统 (结构化日志) | ||
| 1171 | - [ ] CI/CD Pipeline | ||
| 1172 | |||
| 1173 | ### 12.5 质量保障 | ||
| 1174 | |||
| 1175 | - [ ] 单元测试 (核心模块覆盖率 ≥ 80%) | ||
| 1176 | - [ ] 集成测试 (端到端识别流程) | ||
| 1177 | - [ ] 性能基准测试 (延迟、吞吐、内存) | ||
| 1178 | - [ ] 鲁棒性测试 (噪声、压缩、哼唱变化) | ||
| 1179 | - [ ] 回归测试 (每次模型更新) | ||
| 1180 | - [ ] 评估集标注与维护 | ||
| 1181 | - [ ] 安全审计 (注入、权限、数据泄露) | ||
| 1182 | |||
| 1183 | ### 12.6 文档与交付 | ||
| 1184 | |||
| 1185 | - [x] 设计文档 (本文件) | ||
| 1186 | - [ ] API 文档 (Swagger / OpenAPI) | ||
| 1187 | - [ ] 部署文档 (Docker, K8s, 环境要求) | ||
| 1188 | - [ ] 用户手册 (SDK 使用指南) | ||
| 1189 | - [ ] 训练文档 (数据、超参数、实验记录) | ||
| 1190 | - [ ] 运维手册 (监控、日志、故障排查) | ||
| 1191 | - [ ] 演示 / demos | ||
| 1192 | |||
| 1193 | --- | ||
| 1194 | |||
| 1195 | ## 13. Changelog | ||
| 1196 | |||
| 1197 | ### [v1.0] — 2026-06-02 | ||
| 1198 | |||
| 1199 | #### Added | ||
| 1200 | - 初始设计文档创建 | ||
| 1201 | - 完整架构设计 (双塔对比学习 + Faiss 检索) | ||
| 1202 | - 数据增强策略 (12+ 种操作) | ||
| 1203 | - 哼唱识别模块设计 | ||
| 1204 | - SOTA 调研对比表 | ||
| 1205 | - Roadmap (Phase 0-5) | ||
| 1206 | - Checklist (6 大模块) | ||
| 1207 | |||
| 1208 | ### [Planned] — v1.1 | ||
| 1209 | |||
| 1210 | #### Planned | ||
| 1211 | - 实验基准数据 | ||
| 1212 | - 训练收敛曲线与指标 | ||
| 1213 | - 模型参数量与推理延迟详细报告 | ||
| 1214 | - 消融实验结果 | ||
| 1215 | - 用户反馈收集结果 | ||
| 1216 | |||
| 1217 | ### [Planned] — v2.0 | ||
| 1218 | |||
| 1219 | #### Planned | ||
| 1220 | - 分布式曲库方案 | ||
| 1221 | - 边缘端部署方案 | ||
| 1222 | - 在线学习模块 | ||
| 1223 | - 歌词时间轴识别 | ||
| 1224 | |||
| 1225 | --- | ||
| 1226 | |||
| 1227 | ## 14. Handoff 交付清单 | ||
| 1228 | |||
| 1229 | ### 14.1 交付物概要 | ||
| 1230 | |||
| 1231 | | 类别 | 交付物 | 责任人 | 验收人 | | ||
| 1232 | |------|--------|-------|--------| | ||
| 1233 | | 设计 | ACR 设计文档 (本文) | 架构师 | 技术负责人 | | ||
| 1234 | | 数据 | 训练数据集 & 评估集 | 数据工程师 | 算法工程师 | | ||
| 1235 | | 代码 | 模型训练代码 | 算法工程师 | 架构师 | | ||
| 1236 | | 代码 | API 服务 & CLI 工具 | 后端工程师 | 架构师 | | ||
| 1237 | | 部署 | Docker / K8s 配置 | DevOps | 运维 | | ||
| 1238 | | 文档 | API 文档 & 用户手册 | 技术写作 | 产品经理 | | ||
| 1239 | | 测试 | 测试报告 & 性能基准 | QA | 技术负责人 | | ||
| 1240 | |||
| 1241 | ### 14.2 验收标准 | ||
| 1242 | |||
| 1243 | ``` | ||
| 1244 | [ ] 端到端识别流程通过: 输入音频 → 输出正确歌曲 | ||
| 1245 | [ ] Recall@1 ≥ 90% (BGM 场景, 干净音频) | ||
| 1246 | [ ] Recall@1 ≥ 80% (哼唱场景) | ||
| 1247 | [ ] P50 延迟 ≤ 100ms (单机器, 百万曲库) | ||
| 1248 | [ ] P99 延迟 ≤ 500ms | ||
| 1249 | [ ] 并发 QPS ≥ 100 (单机器, 4 CPU cores) | ||
| 1250 | [ ] 曲库增量更新 ≤ 1s/曲 | ||
| 1251 | [ ] 所有单元测试通过 (覆盖率 ≥ 80%) | ||
| 1252 | [ ] 安全审计无高危漏洞 | ||
| 1253 | [ ] 文档完整性审查通过 | ||
| 1254 | ``` | ||
| 1255 | |||
| 1256 | ### 14.3 风险与缓解 | ||
| 1257 | |||
| 1258 | | 风险 | 概率 | 影响 | 缓解措施 | | ||
| 1259 | |------|------|-----|---------| | ||
| 1260 | | 版权音乐数据获取困难 | 高 | 高 | 优先使用开源数据集; 探索合成数据 | | ||
| 1261 | | 哼唱数据不足 | 中 | 高 | 合成哼唱 + Mid-to-Audio 生成 | | ||
| 1262 | | 噪声下准确率不达标 | 中 | 中 | 更激进的数据增强; 模型集成 | | ||
| 1263 | | 大曲库检索延迟 | 低 | 中 | 多级索引; GPU 加速检索 | | ||
| 1264 | | 模型过拟合 | 低 | 中 | 强正则化; 大规模数据; Dropout | | ||
| 1265 | | 哼唱与 BGM 模式冲突 | 中 | 中 | 双模式 / 级联识别 | | ||
| 1266 | |||
| 1267 | ### 14.4 移交步骤 | ||
| 1268 | |||
| 1269 | 1. **代码移交**:所有代码推送到主仓库,PR 审核通过,CI 绿色 | ||
| 1270 | 2. **模型移交**:最佳模型 checkpoint + 导出 ONNX/TorchScript | ||
| 1271 | 3. **数据移交**:训练数据、评估数据、数据管线代码 | ||
| 1272 | 4. **索引移交**:Faiss 索引文件 + 元数据 | ||
| 1273 | 5. **部署移交**:Docker 镜像推送到 Registry,K8s 配置文件就绪 | ||
| 1274 | 6. **文档移交**:所有文档整理到 `/docs/` 目录 | ||
| 1275 | 7. **演示移交**:运行 demo 脚本,展示端到端识别流程 | ||
| 1276 | 8. **培训移交**:对运维/开发人员进行 2 小时技术培训 | ||
| 1277 | |||
| 1278 | --- | ||
| 1279 | |||
| 1280 | ## 15. 参考与引用 | ||
| 1281 | |||
| 1282 | ### 15.1 学术论文 | ||
| 1283 | |||
| 1284 | | 主题 | 论文 | 年份 | | ||
| 1285 | |------|------|------| | ||
| 1286 | | 音频指纹 (Shazam) | Wang, A. "An Industrial-Strength Audio Search Algorithm" | 2003 | | ||
| 1287 | | 对比学习 (SimCLR) | Chen et al. "A Simple Framework for Contrastive Learning" | 2020 | | ||
| 1288 | | 监督对比学习 | Khosla et al. "Supervised Contrastive Learning" | 2020 | | ||
| 1289 | | 频谱图增强 (SpecAug) | Park et al. "SpecAugment: A Simple Augmentation Method" | 2019 | | ||
| 1290 | | 语音谱图 Transformer | Gong et al. "AST: Audio Spectrogram Transformer" | 2021 | | ||
| 1291 | | CLAP | Wu et al. "Large-scale Contrastive Language-Audio Pretraining" | 2023 | | ||
| 1292 | | AudioMAE | Huang et al. "Masked Autoencoders that Listen" | 2023 | | ||
| 1293 | | CPC for Audio | Oord et al. "Representation Learning with Contrastive Predictive Coding" | 2018 | | ||
| 1294 | | 哼唱识别综述 | Sharma et al. "Query-by-Humming: A Survey" | 2023 | | ||
| 1295 | | CREPE | Kim et al. "CREPE: A Convolutional Representation for Pitch Estimation" | 2018 | | ||
| 1296 | |||
| 1297 | ### 15.2 开源项目 | ||
| 1298 | |||
| 1299 | | 项目 | 说明 | 链接 | | ||
| 1300 | |------|------|------| | ||
| 1301 | | **Dejavu** | Shazam 指纹法 Python 实现 | https://github.com/worldveil/dejavu | | ||
| 1302 | | **Faiss** | 向量相似度搜索库 (Meta) | https://github.com/facebookresearch/faiss | | ||
| 1303 | | **CLAP** | 对比语言-音频预训练 (LAION) | https://github.com/LAION-AI/CLAP | | ||
| 1304 | | **torchaudio** | PyTorch 音频工具包 | https://github.com/pytorch/audio | | ||
| 1305 | | **audiomentations** | 音频数据增强库 | https://github.com/iver56/audiomentations | | ||
| 1306 | | **librosa** | 音频分析库 | https://github.com/librosa/librosa | | ||
| 1307 | | **marsyas** | 音频处理框架 | https://github.com/marsyas/marsyas | | ||
| 1308 | | **Essentia** | 音频分析库 (UPF) | https://github.com/MTG/essentia | | ||
| 1309 | |||
| 1310 | ### 15.3 数据集 | ||
| 1311 | |||
| 1312 | | 数据集 | 规模 | 用途 | 许可 | | ||
| 1313 | |--------|------|------|------| | ||
| 1314 | | FMA (Free Music Archive) | 106,574 曲 | 基础歌曲库 | CC | | ||
| 1315 | | MUSDB18 | 150 曲 (多轨) | 音源分离 | 研究 | | ||
| 1316 | | GTZAN | 1,000 曲 | 流派分类 (基线) | 研究 | | ||
| 1317 | | MIR-QBSH | ~4,800 哼唱 | 哼唱识别 | 研究 | | ||
| 1318 | | Medley-solos-DB | 21,574 片段 | 音色分析 | CC | | ||
| 1319 | | AudioSet (Google) | 2M+ 片段 | 预训练/多任务 | YouTube | | ||
| 1320 | |||
| 1321 | --- | ||
| 1322 | |||
| 1323 | ## 附录 A: 快速开始 Demo | ||
| 1324 | |||
| 1325 | ```python | ||
| 1326 | #!/usr/bin/env python | ||
| 1327 | """ACR Engine Quick Demo""" | ||
| 1328 | |||
| 1329 | from acr_engine import ACRPipeline | ||
| 1330 | |||
| 1331 | # 初始化 | ||
| 1332 | pipeline = ACRPipeline( | ||
| 1333 | model_path="models/acr/best.ckpt", | ||
| 1334 | index_path="index/acr_index.faiss", | ||
| 1335 | mode="auto" | ||
| 1336 | ) | ||
| 1337 | |||
| 1338 | # 批量导入 | ||
| 1339 | pipeline.ingest_directory("data/samples/") | ||
| 1340 | |||
| 1341 | # 识别 | ||
| 1342 | for query_path in ["query_bgm.wav", "query_hum.wav", "query_noisy.wav"]: | ||
| 1343 | result = pipeline.recognize(query_path) | ||
| 1344 | print(f"{query_path}: {result.title} ({result.confidence:.2%})") | ||
| 1345 | ``` | ||
| 1346 | |||
| 1347 | ## 附录 B: 配置模板 (configs/default.yaml) | ||
| 1348 | |||
| 1349 | ```yaml | ||
| 1350 | model: | ||
| 1351 | name: cnn_transformer | ||
| 1352 | embed_dim: 256 | ||
| 1353 | backbone: | ||
| 1354 | cnn_channels: [32, 64, 128, 256] | ||
| 1355 | transformer_layers: 4 | ||
| 1356 | nhead: 8 | ||
| 1357 | dim_feedforward: 1024 | ||
| 1358 | humming_branch: | ||
| 1359 | enabled: true | ||
| 1360 | fusion: late | ||
| 1361 | chroma_bins: 12 | ||
| 1362 | f0_embed_dim: 64 | ||
| 1363 | |||
| 1364 | data: | ||
| 1365 | sample_rate: 16000 | ||
| 1366 | n_mels: 128 | ||
| 1367 | n_fft: 1024 | ||
| 1368 | hop_length: 512 | ||
| 1369 | max_duration: 10.0 | ||
| 1370 | min_duration: 3.0 | ||
| 1371 | window_size: 5.0 | ||
| 1372 | window_stride: 2.5 | ||
| 1373 | |||
| 1374 | augmentation: | ||
| 1375 | noise: | ||
| 1376 | enable: true | ||
| 1377 | snr_range: [5, 30] | ||
| 1378 | pitch_shift: | ||
| 1379 | enable: true | ||
| 1380 | semitones_range: [-6, 6] | ||
| 1381 | time_stretch: | ||
| 1382 | enable: true | ||
| 1383 | rate_range: [0.85, 1.15] | ||
| 1384 | mp3_compression: | ||
| 1385 | enable: true | ||
| 1386 | bitrate_range: [32, 128] | ||
| 1387 | spec_augment: | ||
| 1388 | enable: true | ||
| 1389 | time_mask_max: 50 | ||
| 1390 | freq_mask_max: 16 | ||
| 1391 | |||
| 1392 | training: | ||
| 1393 | batch_size: 512 | ||
| 1394 | epochs: 200 | ||
| 1395 | lr: 0.0003 | ||
| 1396 | weight_decay: 0.01 | ||
| 1397 | warmup_steps: 5000 | ||
| 1398 | temperature: 0.07 | ||
| 1399 | loss: | ||
| 1400 | supcon_weight: 1.0 | ||
| 1401 | arcface_weight: 0.3 | ||
| 1402 | triplet_weight: 0.1 | ||
| 1403 | optimizer: adamw | ||
| 1404 | scheduler: cosine | ||
| 1405 | mixed_precision: bf16 | ||
| 1406 | gradient_clip: 1.0 | ||
| 1407 | |||
| 1408 | index: | ||
| 1409 | type: "IVF4096,PQ16" | ||
| 1410 | metric: cosine | ||
| 1411 | train_on_gpu: true | ||
| 1412 | nprobe: 64 | ||
| 1413 | |||
| 1414 | serving: | ||
| 1415 | host: "0.0.0.0" | ||
| 1416 | port: 8088 | ||
| 1417 | workers: 4 | ||
| 1418 | max_query_duration: 30.0 | ||
| 1419 | cache_size: 10000 | ||
| 1420 | reject_threshold: 0.5 | ||
| 1421 | top_n: 5 | ||
| 1422 | |||
| 1423 | logging: | ||
| 1424 | level: INFO | ||
| 1425 | format: json | ||
| 1426 | output: stdout | ||
| 1427 | ``` |
docs/changelist-2026-06-02.md
deleted
100644 → 0
| 1 | # Changelist / 2026-06-02 | ||
| 2 | |||
| 3 | ## 本次补充交付(2026-06-02 16:12 UTC) | ||
| 4 | |||
| 5 | ### 目标 | ||
| 6 | 把当前工作切换成“可交接、可暂停、可恢复”的状态。 | ||
| 7 | |||
| 8 | ### 本次纳入交付的内容 | ||
| 9 | |||
| 10 | | 类别 | 内容 | | ||
| 11 | |---|---| | ||
| 12 | | 状态 | 当前 dual-axis 仍以 `hum_focus` 为最佳候选 | | ||
| 13 | | 文档 | `CHANGELOG`、`session-handoff`、`delivery-handoff` 已补齐最新快照 | | ||
| 14 | | 约束 | 继续保留相对路径文档跳转,不碰大数据与训练产物 | | ||
| 15 | | 续跑 | 新 session 可直接从 handoff 接上继续做训练/评测/优化 | | ||
| 16 | |||
| 17 | ### 这次交付的意义 | ||
| 18 | |||
| 19 | 1. 先把当前成果冻结,避免上下文丢失。 | ||
| 20 | 2. 给新 session 留一个最短恢复路径。 | ||
| 21 | 3. 后续可以无缝继续补数据集、改切片、提准确率。 | ||
| 22 | |||
| 23 | --- | ||
| 24 | |||
| 25 | ## 本次补充交付(2026-06-02 15:09 UTC) | ||
| 26 | |||
| 27 | ### 目标 | ||
| 28 | 把当前状态从“仍在稳定推进”升级为“已确认异常退出、需要排查”的交接包。 | ||
| 29 | |||
| 30 | ### 本次纳入交付的内容 | ||
| 31 | |||
| 32 | | 类别 | 内容 | | ||
| 33 | |---|---| | ||
| 34 | | 证据 | `PID=431703` 与 `PID=424691` 均已退出 | | ||
| 35 | | 状态 | observable 目录仍停在 `chromaprint_progress.json + chromaprint.pkl` | | ||
| 36 | | 风险 | 没有 `reference_*`,没有 `evaluate.py`,没有明确 traceback | | ||
| 37 | | 文档 | `CHANGELOG`、`changelist`、`delivery handoff`、`session handoff`、`AGENT memory` | | ||
| 38 | |||
| 39 | ### 文件级变更 | ||
| 40 | |||
| 41 | | 文件 | 说明 | | ||
| 42 | |---|---| | ||
| 43 | | [./CHANGELOG.md](./CHANGELOG.md) | 补记 build-index 异常退出 checkpoint | | ||
| 44 | | [./delivery-handoff-2026-06-02.md](./delivery-handoff-2026-06-02.md) | 顶部改写为异常排查接管包 | | ||
| 45 | | [./session-handoff.md](./session-handoff.md) | 顶部快照切到“进程已退出、无下游产物” | | ||
| 46 | | [../AGENT.md](../AGENT.md) | 更新长期记忆,避免新 session 误判为仍在运行 | | ||
| 47 | |||
| 48 | ### 当前最重要的 fresh evidence | ||
| 49 | |||
| 50 | - 观测时间:`2026-06-02 15:09:19 UTC` | ||
| 51 | - `ps -p 431703`:无存活进程 | ||
| 52 | - `ps -p 424691`:无存活进程 | ||
| 53 | - `pgrep -af 'run_demo.py build-index|evaluate.py ...'`:未发现接续进程 | ||
| 54 | - observable 目录仅有: | ||
| 55 | - `chromaprint.pkl` | ||
| 56 | - `chromaprint_progress.json` | ||
| 57 | - 末次 progress: | ||
| 58 | - `status=building` | ||
| 59 | - `refs_done=4420/8000` | ||
| 60 | - 未出现: | ||
| 61 | - `reference_*` | ||
| 62 | - `evaluate.py` | ||
| 63 | |||
| 64 | ### 重要决策 | ||
| 65 | |||
| 66 | 1. 当前已不应继续把它描述成“仅仅线性慢”。 | ||
| 67 | 2. 下一轮工作应转向 **build-index 异常退出排查**。 | ||
| 68 | 3. 新提交已经有意义,因为状态从“运行中”变成了“已退出且无下游产物”。 | ||
| 69 | |||
| 70 | ## 本次追加交付(2026-06-02 15:18 UTC) | ||
| 71 | |||
| 72 | ### 新增代码修复 | ||
| 73 | |||
| 74 | | 文件 | 变更 | | ||
| 75 | |---|---| | ||
| 76 | | [../acr-engine/run_demo.py](../acr-engine/run_demo.py) | `build-index` / demo 关键日志统一 `flush=True` | | ||
| 77 | | [../acr-engine/src/engines/chromaprint_matcher.py](../acr-engine/src/engines/chromaprint_matcher.py) | chromaprint 阶段 progress 日志 `flush=True` | | ||
| 78 | | [../acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py) | embedding/reference 阶段关键日志 `flush=True` | | ||
| 79 | |||
| 80 | ### 新增验证证据 | ||
| 81 | |||
| 82 | - 极小样本复现:`/tmp/chroma_repro_tiny12` | ||
| 83 | - 结果:`RC=1` | ||
| 84 | - 现在日志已实时落盘,不再是 `0 bytes`: | ||
| 85 | - `[build-index] starting chromaprint index ...` | ||
| 86 | - `[build-reference-index] start: refs=12 ...` | ||
| 87 | - `ValueError: No reference embeddings were produced ...` | ||
| 88 | |||
| 89 | ### 结论 | ||
| 90 | |||
| 91 | - 当前已修复“失败时日志完全不可见”的可观测性问题。 | ||
| 92 | - 下一轮 root cause 排查可以直接依赖实时日志,而不再需要盲等。 | ||
| 93 | |||
| 94 | ## 本次追加交付(2026-06-02 15:22 UTC) | ||
| 95 | |||
| 96 | ### 新增代码修复 | ||
| 97 | |||
| 98 | | 文件 | 变更 | | ||
| 99 | |---|---| | ||
| 100 | | [../acr-engine/src/engines/chromaprint_matcher.py](../acr-engine/src/engines/chromaprint_matcher.py) | 坏音频/缺失音频跳过;progress 增加 `skipped_refs` | | ||
| 101 | | [../acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py) | 坏音频/缺失音频跳过;progress 增加 `skipped_refs` | | ||
| 102 | |||
| 103 | ### 新增验证证据 | ||
| 104 | |||
| 105 | - 最小容错复现:`/tmp/chroma_skip_repro` | ||
| 106 | - 输入:`1 good mp3 + 1 bad mp3` | ||
| 107 | - 结果:`RC=0` | ||
| 108 | - 验证点: | ||
| 109 | - 日志可见 `skip decode failure` | ||
| 110 | - `chromaprint_progress.json` 为 `status=complete` | ||
| 111 | - `reference_progress.json` 为 `status=complete` | ||
| 112 | - 两个 progress 文件都记录 `skipped_refs=1` | ||
| 113 | - 最终成功产出 `reference_embs.npy` / `reference_ids.npy` | ||
| 114 | |||
| 115 | ### 结论 | ||
| 116 | |||
| 117 | - 当前已验证:单个坏 MP3 不再拖垮整轮 `build-index`。 | ||
| 118 | - 下一轮应回到真实路径复现,确认主问题是否就是由坏 MP3 触发。 | ||
| 119 | |||
| 120 | ## 本次追加交付(2026-06-02 15:29 UTC) | ||
| 121 | |||
| 122 | ### 新增运行证据 | ||
| 123 | |||
| 124 | | 类别 | 内容 | | ||
| 125 | |---|---| | ||
| 126 | | rerun | fixed real-path 200-ref rerun 仍在前台运行:`session 19709` | | ||
| 127 | | chromaprint | `200/200` 完成,`skipped_refs=0` | | ||
| 128 | | reference | 已进入 embedding/reference 阶段,并完成 `25/200` checkpoint | | ||
| 129 | | 产物 | 已落盘 `reference_progress.json`、`reference_embs.partial.npy`、`reference_ids.partial.npy` | | ||
| 130 | |||
| 131 | ### 当前最重要的 fresh evidence | ||
| 132 | |||
| 133 | - 观测时间:`2026-06-02 15:29:17 UTC` | ||
| 134 | - 输出目录:`/tmp/fma_realpath_small_rerun_index2` | ||
| 135 | - `chromaprint_progress.json`: | ||
| 136 | - `status=complete` | ||
| 137 | - `refs_done=200/200` | ||
| 138 | - `hashes=57577` | ||
| 139 | - `postings=187446` | ||
| 140 | - `skipped_refs=0` | ||
| 141 | - `reference_progress.json`: | ||
| 142 | - `status=building` | ||
| 143 | - `refs_done=25/200` | ||
| 144 | - `windows_done=256` | ||
| 145 | - `skipped_refs=0` | ||
| 146 | - 已出现: | ||
| 147 | - `reference_embs.partial.npy` | ||
| 148 | - `reference_ids.partial.npy` | ||
| 149 | |||
| 150 | ### 结论 | ||
| 151 | |||
| 152 | - 这次 fixed rerun 已经证明:修复后的真实路径样本不再卡死在 chromaprint 阶段。 | ||
| 153 | - 当前最有价值的下一步,变为继续盯 `reference_*` 完成或捕获新的明确失败证据。 | ||
| 154 | |||
| 155 | ## 本次追加交付(2026-06-02 15:35 UTC) | ||
| 156 | |||
| 157 | ### 新增运行证据 | ||
| 158 | |||
| 159 | | 类别 | 内容 | | ||
| 160 | |---|---| | ||
| 161 | | chromaprint | `200/200` 完成,`skipped_refs=0` | | ||
| 162 | | reference | `200/200` 完成,`windows_done=2068` | | ||
| 163 | | 产物 | `reference_embs.npy`、`reference_ids.npy` 已完整落盘 | | ||
| 164 | | shape | `embedding_shape=[2068, 192]` | | ||
| 165 | |||
| 166 | ### 当前最重要的 fresh evidence | ||
| 167 | |||
| 168 | - 观测时间:`2026-06-02 15:35:19 UTC` | ||
| 169 | - 输出目录:`/tmp/fma_realpath_small_rerun_index2` | ||
| 170 | - `reference_progress.json`: | ||
| 171 | - `status=complete` | ||
| 172 | - `refs_done=200/200` | ||
| 173 | - `windows_done=2068` | ||
| 174 | - `embedding_shape=[2068, 192]` | ||
| 175 | - `skipped_refs=0` | ||
| 176 | - 最终产物: | ||
| 177 | - `reference_embs.npy`(`1588352 bytes`) | ||
| 178 | - `reference_ids.npy`(`74576 bytes`) | ||
| 179 | - stdout 明确出现: | ||
| 180 | - `Built reference index: 2068 windows, embeddings shape (2068, 192)` | ||
| 181 | - `[done] embedding index built: 2068 refs` | ||
| 182 | |||
| 183 | ### 结论 | ||
| 184 | |||
| 185 | - 当前已确认:修复后的真实路径 rerun 不仅能进入 reference 阶段,而且能完整产出最终 embedding index。 | ||
| 186 | - 下一轮最高价值工作应切到:评测链是否自动衔接,以及必要时补显式 evaluate smoke。 | ||
| 187 | |||
| 188 | ## 本次追加交付(2026-06-02 15:40 UTC) | ||
| 189 | |||
| 190 | ### 新增运行证据 | ||
| 191 | |||
| 192 | | 类别 | 内容 | | ||
| 193 | |---|---| | ||
| 194 | | evaluate | 显式 `evaluate.py` smoke 已完成 | | ||
| 195 | | query 规模 | `num_queries=35`(overlap 中全部非 reference query) | | ||
| 196 | | 指标 | `top1=0.8571`, `topk=1.0` | | ||
| 197 | | by_type | `clean: n=35, top1=0.8571, topk=1.0` | | ||
| 198 | |||
| 199 | ### 当前最重要的 fresh evidence | ||
| 200 | |||
| 201 | - 观测时间:`2026-06-02 15:40:30 UTC` | ||
| 202 | - 结果文件:`/tmp/fma_realpath_small_rerun_eval/eval_top50.json` | ||
| 203 | - 评测结果: | ||
| 204 | - `split=test` | ||
| 205 | - `num_queries=35` | ||
| 206 | - `top1=0.8571` | ||
| 207 | - `topk=1.0` | ||
| 208 | - query 数说明: | ||
| 209 | - overlap test items = `235` | ||
| 210 | - 非 `reference` query = `35` | ||
| 211 | - 所以 `--max-queries 50` 实际评到 `35` 条 | ||
| 212 | |||
| 213 | ### 结论 | ||
| 214 | |||
| 215 | - 当前已不只是建索引成功,而是已经拿到首份真实路径 `build-index -> evaluate` 闭环证据。 | ||
| 216 | - 下一轮应把重点切到:更大评测规模与 hard case / confusion 评测。 | ||
| 217 | |||
| 218 | ## 本次追加交付(2026-06-02 15:43 UTC) | ||
| 219 | |||
| 220 | ### 新增运行证据 | ||
| 221 | |||
| 222 | | 类别 | 内容 | | ||
| 223 | |---|---| | ||
| 224 | | hard-case smoke | `synthetic_v2 + models_v6 + index_v6` 显式评测完成 | | ||
| 225 | | 总体 | `num_queries=16`, `top1=0.6875`, `topk=1.0` | | ||
| 226 | | hard case | `humming_like top1=0.25`, `confused top1=0.0` | | ||
| 227 | | 结论 | 当前短板已明确落在 hard-case top1,而不是 clean/topk | | ||
| 228 | |||
| 229 | ### 当前最重要的 fresh evidence | ||
| 230 | |||
| 231 | - 观测时间:`2026-06-02 15:43:17 UTC` | ||
| 232 | - 结果文件:`/tmp/synthetic_v2_eval_v6_top16.json` | ||
| 233 | - 评测结果: | ||
| 234 | - `top1=0.6875` | ||
| 235 | - `topk=1.0` | ||
| 236 | - `humming_like: n=4, top1=0.25, topk=1.0` | ||
| 237 | - `confused: n=1, top1=0.0, topk=1.0` | ||
| 238 | - manifest 审计结果: | ||
| 239 | - real-path FMA external smoke 只有 `clean` query | ||
| 240 | - synthetic_v2 才包含 `augmented` / `humming_like` / `confused` | ||
| 241 | |||
| 242 | ### 结论 | ||
| 243 | |||
| 244 | - 当前已经不仅知道“系统能跑通”,还知道“最该优化哪里”:hard-case 的 top1。 | ||
| 245 | - 下一轮更有价值的是围绕 `humming_like` / `confused` 做输入层、切片、混淆增强与 hard negative 优化。 | ||
| 246 | |||
| 247 | ## 本次追加交付(2026-06-02 15:45 UTC) | ||
| 248 | |||
| 249 | ### 新增运行证据 | ||
| 250 | |||
| 251 | | 类别 | 内容 | | ||
| 252 | |---|---| | ||
| 253 | | baseline sweep | `v3~v6` 已完成统一 hard-case sweep | | ||
| 254 | | 总体最佳 | `v6`: `top1=0.65`, `topk=0.95` | | ||
| 255 | | humming_like 最佳 | `v5`: `top1=0.5` | | ||
| 256 | | confused 最佳 | `v3` / `v6`: `top1=0.25` | | ||
| 257 | |||
| 258 | ### 当前最重要的 fresh evidence | ||
| 259 | |||
| 260 | - 观测时间:`2026-06-02 15:45:18 UTC` | ||
| 261 | - 汇总文件:`/tmp/synth_v2_baseline_sweep/summary.json` | ||
| 262 | - 统一评测集:`data/synthetic_v2` | ||
| 263 | - 结果摘录: | ||
| 264 | - `v3`: overall `0.6/0.75`, hard-case `hum=0.0`, `conf=0.25` | ||
| 265 | - `v4`: overall `0.4/0.8`, hard-case `hum=0.0`, `conf=0.0` | ||
| 266 | - `v5`: overall `0.6/0.9`, hard-case `hum=0.5`, `conf=0.0` | ||
| 267 | - `v6`: overall `0.65/0.95`, hard-case `hum=0.25`, `conf=0.25` | ||
| 268 | |||
| 269 | ### 结论 | ||
| 270 | |||
| 271 | - 当前最合理的下一轮实验基线是 `v6`,因为总体最稳。 | ||
| 272 | - 但 `v5` 在 `humming_like` 上明显更强,值得做 targeted diff / 吸收。 | ||
| 273 | |||
| 274 | ## 本次追加交付(2026-06-02 15:46 UTC) | ||
| 275 | |||
| 276 | ### 新增差异审计证据 | ||
| 277 | |||
| 278 | | 类别 | 内容 | | ||
| 279 | |---|---| | ||
| 280 | | v5 来源 | `type-aware hard-case weighting` | | ||
| 281 | | v6 来源 | `sample-level confused-priority weighting` | | ||
| 282 | | 解释 | `v5` 更利于 `humming_like`,`v6` 更利于 `confused` | | ||
| 283 | | 决策 | 下一轮应做双轴 hard-case weighting / 分治,而不是单轴加权 | | ||
| 284 | |||
| 285 | ### 当前最重要的 fresh evidence | ||
| 286 | |||
| 287 | - `docs/CHANGELOG.md:2954+`:`v6` = sample-level confused-priority weighting | ||
| 288 | - `docs/CHANGELOG.md:6805+`:`v5` = type-aware hard-case weighting | ||
| 289 | - `docs/sota-research-2026.md:113-114`: | ||
| 290 | - `v5`: `overall=0.60`, `humming_like=0.50`, `confused=0.00` | ||
| 291 | - `v6`: `overall=0.65`, `humming_like=0.25`, `confused=0.25` | ||
| 292 | |||
| 293 | ### 结论 | ||
| 294 | |||
| 295 | - 现在已经不仅知道 `v5/v6` 哪个更强,还知道“为什么”。 | ||
| 296 | - 下一轮应把 `humming_like` 与 `confused` 分开建模或分开加权。 | ||
| 297 | |||
| 298 | ## 本次追加交付(2026-06-02 15:47 UTC) | ||
| 299 | |||
| 300 | ### 新增代码能力 | ||
| 301 | |||
| 302 | | 文件 | 变更 | | ||
| 303 | |---|---| | ||
| 304 | | [../acr-engine/src/data/dataset.py](../acr-engine/src/data/dataset.py) | hard-case 采样权重与 pair 权重改为配置驱动 | | ||
| 305 | | [../acr-engine/train.py](../acr-engine/train.py) | 训练链路透传 dual-axis 权重配置 | | ||
| 306 | | [../acr-engine/configs/default.yaml](../acr-engine/configs/default.yaml) | 增加 `sample_type_weights` / `pair_type_weights` 默认配置 | | ||
| 307 | |||
| 308 | ### 当前最重要的 fresh evidence | ||
| 309 | |||
| 310 | - `python -m py_compile train.py src/data/dataset.py`:通过 | ||
| 311 | - `train.py --data data/synthetic_v2 --device cpu --epochs 1 --batch-size 4 --dry-run`:通过 | ||
| 312 | - 自定义权重实例化检查: | ||
| 313 | - `dataset_len=96` | ||
| 314 | - `unique_songs=16` | ||
| 315 | - `sample_multiplicity_minmax=6/6` | ||
| 316 | - `hard_weight=[5.0, 1.0]` | ||
| 317 | |||
| 318 | ### 结论 | ||
| 319 | |||
| 320 | - dual-axis hard-case weighting 已从“设计建议”升级为“代码中可直接调参实验”的状态。 | ||
| 321 | - 下一轮可直接围绕 `sample_type_weights` 与 `pair_type_weights` 做最小实验。 | ||
| 322 | |||
| 323 | ## 本次追加交付(2026-06-02 15:56 UTC) | ||
| 324 | |||
| 325 | ### 新增运行证据 | ||
| 326 | |||
| 327 | | 类别 | 内容 | | ||
| 328 | |---|---| | ||
| 329 | | dual-axis smoke | `train -> build-index -> evaluate` 完整跑通 | | ||
| 330 | | 训练输出 | `/tmp/dualaxis_smoke/models/best_model.pt` | | ||
| 331 | | 索引输出 | `/tmp/dualaxis_smoke/index/` | | ||
| 332 | | 评测输出 | `/tmp/dualaxis_smoke/eval.json` | | ||
| 333 | | 结果 | `top1=0.5`, `topk=0.9` | | ||
| 334 | | hard-case | `humming_like=0.0`, `confused=0.25` | | ||
| 335 | |||
| 336 | ### 当前最重要的 fresh evidence | ||
| 337 | |||
| 338 | - `num_queries=20` | ||
| 339 | - `clean: n=8, top1=0.875, topk=1.0` | ||
| 340 | - `augmented: n=4, top1=0.5, topk=0.75` | ||
| 341 | - `humming_like: n=4, top1=0.0, topk=0.75` | ||
| 342 | - `confused: n=4, top1=0.25, topk=1.0` | ||
| 343 | |||
| 344 | ### 结论 | ||
| 345 | |||
| 346 | - 目前这组 dual-axis 配置证明了“可配置实验链路”是通的。 | ||
| 347 | - 但它没有带来 `humming_like` 改善,说明后续搜索需要更细:该拆分 `sample_type_weights` 与 `pair_type_weights` 的取值粒度。 | ||
| 348 | |||
| 349 | ## 本次追加交付(2026-06-02 16:03 UTC) | ||
| 350 | |||
| 351 | ### 新增运行证据 | ||
| 352 | |||
| 353 | | 候选 | top1 | topk | humming_like top1 | confused top1 | 结论 | | ||
| 354 | |---|---:|---:|---:|---:|---| | ||
| 355 | | hum_focus | 0.7 | 0.85 | 0.5 | 0.25 | 当前最优 | | ||
| 356 | | hum_balanced | 0.65 | 0.95 | 0.25 | 0.25 | 只回到 v6 水平 | | ||
| 357 | |||
| 358 | ### 当前最重要的 fresh evidence | ||
| 359 | |||
| 360 | - 观测时间:`2026-06-02 16:03:13 UTC` | ||
| 361 | - `hum_focus` 结果文件:`/tmp/dualaxis_sweep/hum_focus/eval.json` | ||
| 362 | - `hum_balanced` 结果文件:`/tmp/dualaxis_sweep/hum_balanced/eval.json` | ||
| 363 | - 对比结论:`hum_focus` 在 `humming_like` 上优于 `hum_balanced`,且总体更优。 | ||
| 364 | |||
| 365 | ### 结论 | ||
| 366 | |||
| 367 | - 当前 dual-axis 线的最佳候选已收敛为 `hum_focus`。 | ||
| 368 | - 下一轮应围绕 `hum_focus` 做微调搜索,而不是回退到 `v6` 或扩大盲搜范围。 |
docs/delivery-handoff-2026-06-02.md
deleted
100644 → 0
| 1 | ## 本次交付包追加更新(2026-06-02 16:03 UTC) | ||
| 2 | |||
| 3 | ### 交付结论 | ||
| 4 | |||
| 5 | 当前最新里程碑已经从“dual-axis 首轮可跑通”推进到 **dual-axis 候选已收敛到 hum_focus**: | ||
| 6 | - 远程基线当前为:`9c3f182`(更新前) | ||
| 7 | - `hum_focus` 当前优于 `hum_balanced` 与 `v6` 基线 | ||
| 8 | - 因此下一轮应围绕 `hum_focus` 做微调,而不是回退或盲搜 | ||
| 9 | |||
| 10 | ### 当前最新事实 | ||
| 11 | |||
| 12 | #### dual-axis 对比结果 | ||
| 13 | - `hum_focus`: | ||
| 14 | - `top1=0.7` | ||
| 15 | - `topk=0.85` | ||
| 16 | - `humming_like=0.5` | ||
| 17 | - `confused=0.25` | ||
| 18 | - `hum_balanced`: | ||
| 19 | - `top1=0.65` | ||
| 20 | - `topk=0.95` | ||
| 21 | - `humming_like=0.25` | ||
| 22 | - `confused=0.25` | ||
| 23 | |||
| 24 | ### 当前判断 | ||
| 25 | |||
| 26 | - `hum_focus` 是目前最值得继续迭代的 dual-axis 起点。 | ||
| 27 | - 下一阶段建议是以 `hum_focus` 为锚点做小步搜索,优先保住 `humming_like` 优势。 | ||
| 28 | |||
| 29 | ## 本次交付包追加更新(2026-06-02 16:11 UTC) | ||
| 30 | |||
| 31 | ### 交付结论 | ||
| 32 | |||
| 33 | 最新的 `hum_guard` 复核结果已经确认: | ||
| 34 | - 它没有超过 `hum_focus` | ||
| 35 | - `topk` 持平,但 `top1` 更低 | ||
| 36 | - 所以下一轮仍应围绕 `hum_focus` 微调 | ||
| 37 | |||
| 38 | ### fresh evidence | ||
| 39 | |||
| 40 | - `num_queries=20` | ||
| 41 | - `top1=0.6` | ||
| 42 | - `topk=0.85` | ||
| 43 | - `humming_like top1=0.5` | ||
| 44 | - `confused top1=0.0` | ||
| 45 | |||
| 46 | --- | ||
| 47 | |||
| 48 | ## 本次交付包追加更新(2026-06-02 16:12 UTC) | ||
| 49 | |||
| 50 | ### 交付结论 | ||
| 51 | |||
| 52 | 当前已经完成“先交付、后续续跑”的冻结动作: | ||
| 53 | - 交接文档已补齐最新快照 | ||
| 54 | - 新 session 可直接从这些文件继续 | ||
| 55 | - 当前最重要的优化方向仍是 `hum_focus` | ||
| 56 | |||
| 57 | ### 当前可直接继承的内容 | ||
| 58 | |||
| 59 | - 训练数据规范 | ||
| 60 | - pgvector 导出规范 | ||
| 61 | - FMA / 开源数据接入说明 | ||
| 62 | - SOTA 研究和切片策略说明 | ||
| 63 | |||
| 64 | ### 重启后建议顺序 | ||
| 65 | |||
| 66 | 1. 读 `docs/session-handoff.md` | ||
| 67 | 2. 读 `docs/CHANGELOG.md` | ||
| 68 | 3. 继续做 `hum_focus` 小步搜索 | ||
| 69 | 4. 再做训练 / 评测 / 提交闭环 | ||
| 70 | |||
| 71 | --- | ||
| 72 | |||
| 73 | ## 本次交付包追加更新(2026-06-02 15:56 UTC) | ||
| 74 | |||
| 75 | ### 交付结论 | ||
| 76 | |||
| 77 | 当前最新里程碑已经从“dual-axis 参数化完成”推进到 **dual-axis smoke 首次端到端评测完成**: | ||
| 78 | - 远程基线当前为:`6279850`(更新前) | ||
| 79 | - 训练、建索引、评测全部跑通 | ||
| 80 | - 但这组权重没有改善 `humming_like`,说明接下来要做更细粒度搜索 | ||
| 81 | |||
| 82 | ### 当前最新事实 | ||
| 83 | |||
| 84 | #### dual-axis smoke 结果 | ||
| 85 | - 观测时间:`2026-06-02 15:56:02 UTC` | ||
| 86 | - 结果文件:`/tmp/dualaxis_smoke/eval.json` | ||
| 87 | - 评测结果: | ||
| 88 | - `num_queries=20` | ||
| 89 | - `top1=0.5` | ||
| 90 | - `topk=0.9` | ||
| 91 | - `clean=0.875` | ||
| 92 | - `augmented=0.5` | ||
| 93 | - `humming_like=0.0` | ||
| 94 | - `confused=0.25` | ||
| 95 | |||
| 96 | ### 当前判断 | ||
| 97 | |||
| 98 | - dual-axis 入口是可用的,但当前试验组合不是更优解。 | ||
| 99 | - 下一阶段应进入更细粒度的权重搜索,而不是直接扩大规模。 | ||
| 100 | |||
| 101 | --- | ||
| 102 | |||
| 103 | ## 本次交付包追加更新(2026-06-02 15:47 UTC) | ||
| 104 | |||
| 105 | ### 交付结论 | ||
| 106 | |||
| 107 | 当前最新里程碑已经从“知道该做 dual-axis”推进到 **dual-axis hard-case weighting 已在代码中参数化**: | ||
| 108 | - 远程基线当前为:`7812b58`(更新前) | ||
| 109 | - `sample_type_weights` 与 `pair_type_weights` 已可配置 | ||
| 110 | - 训练 dry-run 已通过 | ||
| 111 | - 因此下一轮可直接做最小调参实验,而不是再先改代码结构 | ||
| 112 | |||
| 113 | ### 当前最新事实 | ||
| 114 | |||
| 115 | #### 代码实现位置 | ||
| 116 | - `src/data/dataset.py`: | ||
| 117 | - `sample_type_weights` 控制 song-level 采样重复度 | ||
| 118 | - `pair_type_weights` 控制 pair-level `hard_weight` | ||
| 119 | - `train.py`:从 `training` 配置透传 | ||
| 120 | - `configs/default.yaml`:提供默认 dual-axis 配置 | ||
| 121 | |||
| 122 | #### fresh verification | ||
| 123 | - `python -m py_compile train.py src/data/dataset.py`:通过 | ||
| 124 | - `train.py --data data/synthetic_v2 --device cpu --epochs 1 --batch-size 4 --dry-run`:通过 | ||
| 125 | - 自定义权重实例化检查: | ||
| 126 | - `dataset_len=96` | ||
| 127 | - `sample_multiplicity_minmax=6/6` | ||
| 128 | - `hard_weight=[5.0, 1.0]` | ||
| 129 | |||
| 130 | ### 当前判断 | ||
| 131 | |||
| 132 | - 现在已经具备一个最小、低风险、可反复实验的 dual-axis 入口。 | ||
| 133 | - 下一阶段最值得做的是直接搜索 `humming_like` / `confused` 的权重组合,而不是继续做只读分析。 | ||
| 134 | |||
| 135 | --- | ||
| 136 | |||
| 137 | ## 本次交付包追加更新(2026-06-02 15:46 UTC) | ||
| 138 | |||
| 139 | ### 交付结论 | ||
| 140 | |||
| 141 | 当前最新里程碑已经从“确定 v6/v5 谁更适合作为基线”推进到 **解释清楚它们为什么会这样表现**: | ||
| 142 | - 远程基线当前为:`93dfa15`(更新前) | ||
| 143 | - `v5` 的关键机制是 `type-aware hard-case weighting` | ||
| 144 | - `v6` 的关键机制是 `sample-level confused-priority weighting` | ||
| 145 | - 因此下一轮最合理的不是继续盲 sweep,而是做 `humming_like` 与 `confused` 的双轴分治策略 | ||
| 146 | |||
| 147 | ### 当前最新事实 | ||
| 148 | |||
| 149 | #### v5 / v6 差异来源 | ||
| 150 | - `v5`: | ||
| 151 | - 历史记录位置:`docs/CHANGELOG.md:6805+` | ||
| 152 | - 定义:`type-aware hard-case weighting` | ||
| 153 | - 结果:`humming_like top1=0.50`, `confused top1=0.00` | ||
| 154 | - `v6`: | ||
| 155 | - 历史记录位置:`docs/CHANGELOG.md:2954+` | ||
| 156 | - 定义:`sample-level confused-priority weighting` | ||
| 157 | - 结果:`humming_like top1=0.25`, `confused top1=0.25` | ||
| 158 | - 汇总解释:`docs/sota-research-2026.md:113-114` | ||
| 159 | |||
| 160 | ### 当前判断 | ||
| 161 | |||
| 162 | - `v5` 与 `v6` 的差异已经可解释,不再是黑箱经验差异。 | ||
| 163 | - 下一阶段最值得做的是: | ||
| 164 | 1. 设计双轴 hard-case weighting; | ||
| 165 | 2. 让 `humming_like` 与 `confused` 分开控制; | ||
| 166 | 3. 再用现有双轨验证链回归测试。 | ||
| 167 | |||
| 168 | --- | ||
| 169 | |||
| 170 | ## 本次交付包追加更新(2026-06-02 15:45 UTC) | ||
| 171 | |||
| 172 | ### 交付结论 | ||
| 173 | |||
| 174 | 当前最新里程碑已经从“知道 hard-case 有缺口”推进到 **知道哪套历史基线最值得作为下一轮优化起点**: | ||
| 175 | - 远程基线当前为:`d4961b1`(更新前) | ||
| 176 | - `v6` 是当前总体最优基线:`top1=0.65`, `topk=0.95` | ||
| 177 | - `v5` 在 `humming_like` 上更强:`top1=0.5` | ||
| 178 | - 因此下一轮不该盲改,而应以 `v6` 为主基线,对比吸收 `v5` 的 hard-case 优势 | ||
| 179 | |||
| 180 | ### 当前最新事实 | ||
| 181 | |||
| 182 | #### hard-case baseline sweep | ||
| 183 | - 观测时间:`2026-06-02 15:45:18 UTC` | ||
| 184 | - 汇总:`/tmp/synth_v2_baseline_sweep/summary.json` | ||
| 185 | - 结果: | ||
| 186 | - `v3`: overall `top1=0.6`, `topk=0.75`; `humming_like=0.0`, `confused=0.25` | ||
| 187 | - `v4`: overall `top1=0.4`, `topk=0.8`; `humming_like=0.0`, `confused=0.0` | ||
| 188 | - `v5`: overall `top1=0.6`, `topk=0.9`; `humming_like=0.5`, `confused=0.0` | ||
| 189 | - `v6`: overall `top1=0.65`, `topk=0.95`; `humming_like=0.25`, `confused=0.25` | ||
| 190 | |||
| 191 | ### 当前判断 | ||
| 192 | |||
| 193 | - `v6` 适合作为下一轮总体优化主基线。 | ||
| 194 | - `v5` 适合作为 `humming_like` 对照基线。 | ||
| 195 | - 下一阶段最值得做的是: | ||
| 196 | 1. 审计 `v5` 与 `v6` 的配置/数据/切片差异; | ||
| 197 | 2. 把 `v5` 的 `humming_like` 优势迁移到 `v6`; | ||
| 198 | 3. 再用真实路径 clean + synthetic hard-case 双轨复测。 | ||
| 199 | |||
| 200 | --- | ||
| 201 | |||
| 202 | ## 本次交付包追加更新(2026-06-02 15:43 UTC) | ||
| 203 | |||
| 204 | ### 交付结论 | ||
| 205 | |||
| 206 | 当前最新里程碑已经从“real-path clean 闭环跑通”推进到 **hard-case 短板已被明确量化**: | ||
| 207 | - 远程基线当前为:`81704ac`(更新前) | ||
| 208 | - real-path FMA smoke 已证明 `clean` 闭环可跑通 | ||
| 209 | - synthetic hard-case smoke 已证明当前主要短板在 `humming_like` / `confused` 的 top1 | ||
| 210 | - 因此下一阶段不应重复 clean smoke,而应聚焦 hard-case 鲁棒性优化 | ||
| 211 | |||
| 212 | ### 当前最新事实 | ||
| 213 | |||
| 214 | #### hard-case smoke 结果 | ||
| 215 | - 观测时间:`2026-06-02 15:43:17 UTC` | ||
| 216 | - 组合:`data/synthetic_v2` + `data/models_v6/best_model.pt` + `data/index_v6/reference` | ||
| 217 | - 结果文件:`/tmp/synthetic_v2_eval_v6_top16.json` | ||
| 218 | - 评测结果: | ||
| 219 | - `num_queries=16` | ||
| 220 | - `top1=0.6875` | ||
| 221 | - `topk=1.0` | ||
| 222 | - `clean: n=7, top1=1.0, topk=1.0` | ||
| 223 | - `augmented: n=4, top1=0.75, topk=1.0` | ||
| 224 | - `humming_like: n=4, top1=0.25, topk=1.0` | ||
| 225 | - `confused: n=1, top1=0.0, topk=1.0` | ||
| 226 | |||
| 227 | #### 关键解释 | ||
| 228 | - real-path FMA external smoke manifest 目前只有 `clean` query: | ||
| 229 | - external test = `1613 clean` | ||
| 230 | - rerun overlap test = `35 clean` | ||
| 231 | - 当前仓库里能提供 `humming_like` / `confused` 的现成评测集是 `data/synthetic_v2`。 | ||
| 232 | |||
| 233 | ### 当前判断 | ||
| 234 | |||
| 235 | - 真实路径闭环已经足够证明工程链可运行。 | ||
| 236 | - 下一阶段的收益最高点已经收敛到: | ||
| 237 | 1. `humming_like` top1 提升; | ||
| 238 | 2. `confused` top1 提升; | ||
| 239 | 3. 将 hard-case 生成/标注引入真实开放数据评测链。 | ||
| 240 | |||
| 241 | --- | ||
| 242 | |||
| 243 | ## 本次交付包追加更新(2026-06-02 15:40 UTC) | ||
| 244 | |||
| 245 | ### 交付结论 | ||
| 246 | |||
| 247 | 当前最新里程碑已经从“reference index 完成”推进到 **fixed real-path 200-ref rerun 已拿到首份显式 evaluate 指标**: | ||
| 248 | - 远程基线当前为:`9371e94`(更新前) | ||
| 249 | - real-path `200-ref` index 已完整完成 | ||
| 250 | - 显式 `evaluate.py` smoke 已完成 | ||
| 251 | - 当前首份结果:`top1=0.8571`, `topk=1.0`, `num_queries=35` | ||
| 252 | - 因此主线已从“索引能否跑通”进入“评测质量与 hard case 扩展”阶段 | ||
| 253 | |||
| 254 | ### 当前最新事实 | ||
| 255 | |||
| 256 | #### evaluate smoke 路径 | ||
| 257 | - 观测时间:`2026-06-02 15:40:30 UTC` | ||
| 258 | - 结果文件:`/tmp/fma_realpath_small_rerun_eval/eval_top50.json` | ||
| 259 | - 评测结果: | ||
| 260 | - `split=test` | ||
| 261 | - `num_queries=35` | ||
| 262 | - `top1=0.8571` | ||
| 263 | - `topk=1.0` | ||
| 264 | - `by_type.clean`: `n=35`, `top1=0.8571`, `topk=1.0` | ||
| 265 | - query 数来源说明: | ||
| 266 | - 200-ref catalog 与现有 external smoke test overlap = `235` items | ||
| 267 | - 其中非 `reference` query = `35` | ||
| 268 | - 所以 `--max-queries 50` 实际只评到 `35` 条 | ||
| 269 | |||
| 270 | ### 当前判断 | ||
| 271 | |||
| 272 | - 当前已经拥有一条完整可复用的真实路径 smoke 证据链: | ||
| 273 | `chromaprint complete -> reference complete -> evaluate complete` | ||
| 274 | - 下一阶段更值得做的是: | ||
| 275 | 1. 扩大评测 query 数与 reference 规模; | ||
| 276 | 2. 引入 `confused` / `humming_like` / hard negative 评测。 | ||
| 277 | |||
| 278 | --- | ||
| 279 | |||
| 280 | ## 本次交付包追加更新(2026-06-02 15:35 UTC) | ||
| 281 | |||
| 282 | ### 交付结论 | ||
| 283 | |||
| 284 | 当前最新里程碑已经从“进入 reference 阶段”推进到 **fixed real-path 200-ref rerun 已完整产出最终 embedding/reference index**: | ||
| 285 | - 远程基线当前为:`41c4d7c`(更新前) | ||
| 286 | - chromaprint 已完整完成:`200/200` | ||
| 287 | - reference 已完整完成:`200/200` | ||
| 288 | - 最终产物 `reference_embs.npy` / `reference_ids.npy` 已落盘 | ||
| 289 | - 因此主问题已从“能否穿过建索引核心阶段”转向“后续 evaluate / identify 链如何衔接验证” | ||
| 290 | |||
| 291 | ### 当前最新事实 | ||
| 292 | |||
| 293 | #### fixed real-path rerun 路径 | ||
| 294 | - 观测时间:`2026-06-02 15:35:19 UTC` | ||
| 295 | - 输出目录:`/tmp/fma_realpath_small_rerun_index2` | ||
| 296 | - `chromaprint_progress.json`: | ||
| 297 | - `status=complete` | ||
| 298 | - `refs_done=200 / 200` | ||
| 299 | - `hashes=57577` | ||
| 300 | - `postings=187446` | ||
| 301 | - `skipped_refs=0` | ||
| 302 | - `reference_progress.json`: | ||
| 303 | - `status=complete` | ||
| 304 | - `refs_done=200 / 200` | ||
| 305 | - `windows_done=2068` | ||
| 306 | - `elapsed_sec=410.046` | ||
| 307 | - `embedding_shape=[2068, 192]` | ||
| 308 | - `skipped_refs=0` | ||
| 309 | - 当前已出现最终产物: | ||
| 310 | - `reference_embs.npy` | ||
| 311 | - `reference_ids.npy` | ||
| 312 | |||
| 313 | ### 当前判断 | ||
| 314 | |||
| 315 | - 这条 fixed rerun 已经给出强证据:`flush=True` 与坏音频 skip tolerance 修复后,真实路径样本可以完整跑完两段核心建索引流程。 | ||
| 316 | - 下一阶段应集中验证: | ||
| 317 | 1. 是否自动衔接到 evaluate / identify; | ||
| 318 | 2. 若没有,补一轮显式 evaluate smoke。 | ||
| 319 | |||
| 320 | --- | ||
| 321 | |||
| 322 | ## 本次交付包追加更新(2026-06-02 15:29 UTC) | ||
| 323 | |||
| 324 | ### 交付结论 | ||
| 325 | |||
| 326 | 当前最新里程碑不是新的失败,而是 **fixed real-path 200-ref rerun 已明确跨入 reference/embedding 阶段**: | ||
| 327 | - 远程基线当前为:`707449b` | ||
| 328 | - chromaprint 已完整完成:`200/200` | ||
| 329 | - reference 阶段已写出首个 checkpoint:`25/200` | ||
| 330 | - 已出现 `reference_progress.json` 与 partial numpy 产物 | ||
| 331 | - 因此下一 session 不应再把这条 rerun 当作“停在 chromaprint 无下游文件”的旧状态 | ||
| 332 | |||
| 333 | ### 当前最新事实 | ||
| 334 | |||
| 335 | #### fixed real-path rerun 路径 | ||
| 336 | - 前台 session:`19709` | ||
| 337 | - 观测时间:`2026-06-02 15:29:17 UTC` | ||
| 338 | - 输出目录:`/tmp/fma_realpath_small_rerun_index2` | ||
| 339 | - `chromaprint_progress.json`: | ||
| 340 | - `status=complete` | ||
| 341 | - `refs_done=200 / 200` | ||
| 342 | - `hashes=57577` | ||
| 343 | - `postings=187446` | ||
| 344 | - `skipped_refs=0` | ||
| 345 | - `reference_progress.json`: | ||
| 346 | - `status=building` | ||
| 347 | - `refs_done=25 / 200` | ||
| 348 | - `windows_done=256` | ||
| 349 | - `elapsed_sec=52.567` | ||
| 350 | - `eta_sec=367.967` | ||
| 351 | - `skipped_refs=0` | ||
| 352 | - 当前已出现: | ||
| 353 | - `reference_embs.partial.npy` | ||
| 354 | - `reference_ids.partial.npy` | ||
| 355 | |||
| 356 | ### 当前判断 | ||
| 357 | |||
| 358 | - `flush=True` 与坏音频 skip tolerance 修复之后,真实路径 rerun 已穿过 `chromaprint -> reference` 阶段边界。 | ||
| 359 | - 当前最高优先级不再是重复证明 chromaprint 完成,而是继续盯 reference 阶段是否: | ||
| 360 | 1. 完整落盘 `reference_embs.npy` / `reference_ids.npy`;或 | ||
| 361 | 2. 暴露新的明确 traceback / failure evidence。 | ||
| 362 | |||
| 363 | ### 建议的新 session 接管顺序 | ||
| 364 | |||
| 365 | 1. 先看 [./session-handoff.md](./session-handoff.md) 顶部新快照 | ||
| 366 | 2. 读取前台 `session 19709` 最新输出 | ||
| 367 | 3. 检查 `/tmp/fma_realpath_small_rerun_index2/` 是否已从 partial 转为 final 产物 | ||
| 368 | |||
| 369 | --- | ||
| 370 | |||
| 371 | # Delivery Handoff / 2026-06-02 | ||
| 372 | |||
| 373 | ## 本次交付包(2026-06-02 15:09 UTC) | ||
| 374 | |||
| 375 | ### 交付结论 | ||
| 376 | |||
| 377 | 这次新增的关键交付,不再是单纯的进度观察,而是一个**新的异常状态检查点**: | ||
| 378 | - 远程基线已推进到:`cdf33bb` | ||
| 379 | - observable chromaprint smoke 与 legacy 全量 FMA `build-index` 进程都已退出 | ||
| 380 | - 但两者都**没有**进入 `reference_*` / `evaluate.py` | ||
| 381 | - 因此下一 session 的首要任务,已从“盯进度”切换为“排查 `build-index` 异常退出” | ||
| 382 | |||
| 383 | ### 当前最新事实 | ||
| 384 | |||
| 385 | #### observable 路径 | ||
| 386 | - 原进程:`PID=431703` | ||
| 387 | - 最后观测时间:`2026-06-02 15:09:19 UTC` | ||
| 388 | - 当前 `ps -p 431703`:无存活进程 | ||
| 389 | - 当前目录仅有: | ||
| 390 | - `chromaprint.pkl` | ||
| 391 | - `chromaprint_progress.json` | ||
| 392 | - 最后 progress 状态: | ||
| 393 | - `status=building` | ||
| 394 | - `refs_done=4420 / 8000` | ||
| 395 | - `elapsed_sec=3964.861` | ||
| 396 | - `hashes=357373` | ||
| 397 | - `postings=3774363` | ||
| 398 | - 当前**仍未出现**: | ||
| 399 | - `reference_progress.json` | ||
| 400 | - `reference_embs.partial.npy` | ||
| 401 | - `reference_ids.partial.npy` | ||
| 402 | - `reference_embs.npy` | ||
| 403 | - `reference_ids.npy` | ||
| 404 | - `evaluate.py` | ||
| 405 | |||
| 406 | #### legacy 全量 FMA 路径 | ||
| 407 | - 原进程:`PID=424691` | ||
| 408 | - 当前 `ps -p 424691`:无存活进程 | ||
| 409 | - 当前目录仍只有: | ||
| 410 | - `/tmp/fma_real_smoke_stopcheck/fma_index_smoke` | ||
| 411 | - 仍未看到 index artifact 或 `evaluate.py` | ||
| 412 | |||
| 413 | #### 当前判断 | ||
| 414 | - 这不再是“CPU-only 长时间构建但仍在推进”的状态。 | ||
| 415 | - 现在更像是:**`build-index` 在 chromaprint 阶段中途退出,但没有留下显式下游产物**。 | ||
| 416 | |||
| 417 | #### 已完成的低风险修复 | ||
| 418 | - 已把 `run_demo.py`、`chromaprint_matcher.py`、`ecapa_embedder.py` 的关键日志改为 `flush=True`。 | ||
| 419 | - 极小样本 `/tmp/chroma_repro_tiny12` 已验证:失败时日志与 traceback 可实时落盘,不再保持 `0 bytes`。 | ||
| 420 | - 这意味着下一 session 继续排查时,日志可作为一手证据,而不是黑箱。 | ||
| 421 | |||
| 422 | #### 已完成的坏音频容错修复 | ||
| 423 | - 已为 chromaprint/reference 两个建索引阶段增加单文件容错:坏 MP3 / 缺失音频会被记录并跳过。 | ||
| 424 | - 最小复现 `/tmp/chroma_skip_repro` 已验证: | ||
| 425 | - `RC=0` | ||
| 426 | - `skip decode failure` 日志可见 | ||
| 427 | - `reference_embs.npy` / `reference_ids.npy` 成功产出 | ||
| 428 | - progress 中记录 `skipped_refs=1` | ||
| 429 | - 这说明:单个坏 MP3 不再拖垮整轮 `build-index`。 | ||
| 430 | |||
| 431 | ## 新 session 接管顺序 | ||
| 432 | |||
| 433 | 1. 先看 [./session-handoff.md](./session-handoff.md) | ||
| 434 | 2. 再看 [./changelist-2026-06-02.md](./changelist-2026-06-02.md) | ||
| 435 | 3. 然后优先做 3 件事: | ||
| 436 | 1. 复盘 `run_demo.py build-index` 的退出路径与异常处理 | ||
| 437 | 2. 检查是否存在未捕获 OOM / shell termination / silent failure | ||
| 438 | 3. 在更小样本上复现“chromaprint 中途退出但无后续文件”的行为 | ||
| 439 | |||
| 440 | ## 当前卡点 | ||
| 441 | |||
| 442 | 1. 关键进程已经退出,但没有明确 traceback 留存。 | ||
| 443 | 2. observable 与 legacy 两条路径都停在“没有 `reference_*` / 没有 `evaluate.py`”的中间态。 | ||
| 444 | 3. 工作树仍有大量数据噪音,提交时必须只显式暂存文档/代码文件。 | ||
| 445 | |||
| 446 | ## 本次交付包含的关键文档 | ||
| 447 | |||
| 448 | - [./CHANGELOG.md](./CHANGELOG.md) | ||
| 449 | - [./changelist-2026-06-02.md](./changelist-2026-06-02.md) | ||
| 450 | - [./session-handoff.md](./session-handoff.md) | ||
| 451 | - [../AGENT.md](../AGENT.md) | ||
| 452 | |||
| 453 | ## 本次明确不提交 | ||
| 454 | |||
| 455 | - `acr-engine/data/raw/*` | ||
| 456 | - `acr-engine/data/external_smoke/*` | ||
| 457 | - `/tmp/*` | ||
| 458 | - checkpoint / index artifacts | ||
| 459 | - `__pycache__` |
docs/external-manifest-template.md
deleted
100644 → 0
| 1 | # External Manifest Template | ||
| 2 | |||
| 3 | 适用于 FMA / Jamendo / CCMusic / ModelScope 白名单数据集。 | ||
| 4 | |||
| 5 | ## catalog.csv 最小字段 | ||
| 6 | |||
| 7 | ```csv | ||
| 8 | song_id,audio_path,duration,source_dataset | ||
| 9 | track_0001,raw/track_0001.wav,12.5,fma | ||
| 10 | ``` | ||
| 11 | |||
| 12 | 转换命令: | ||
| 13 | |||
| 14 | ```bash | ||
| 15 | python src/data/manifest_tools.py csv-to-catalog catalog.csv manifests/catalog.json | ||
| 16 | ``` | ||
| 17 | |||
| 18 | ## 输出 catalog.json 结构 | ||
| 19 | |||
| 20 | ```json | ||
| 21 | { | ||
| 22 | "song_id": "track_0001", | ||
| 23 | "audio_path": "raw/track_0001.wav", | ||
| 24 | "duration": 12.5, | ||
| 25 | "type": "reference", | ||
| 26 | "source_dataset": "fma" | ||
| 27 | } | ||
| 28 | ``` |
docs/open-dataset-plan.md
deleted
100644 → 0
| 1 | # Open Dataset Integration Plan | ||
| 2 | |||
| 3 | ## Recommended order | ||
| 4 | |||
| 5 | 1. **FMA small** | ||
| 6 | - URL: https://github.com/mdeff/fma | ||
| 7 | - Why: easiest small realistic music subset for retrieval experiments | ||
| 8 | 2. **MTG-Jamendo** | ||
| 9 | - URL: https://github.com/MTG/mtg-jamendo-dataset | ||
| 10 | - Why: larger CC-licensed corpus with scriptable upstream tooling | ||
| 11 | 3. **QBSH / humming corpora** | ||
| 12 | - Why: add after retrieval baseline is stable | ||
| 13 | |||
| 14 | ## Repo strategy | ||
| 15 | |||
| 16 | - Keep external dataset ingestion optional | ||
| 17 | - Convert external tracks into: | ||
| 18 | - `catalog.json` for searchable references | ||
| 19 | - query segment manifests for evaluation | ||
| 20 | - Start with small local subsets before full-corpus scaling |
docs/roadmap.md
deleted
100644 → 0
| 1 | # ACR 项目 Roadmap | ||
| 2 | |||
| 3 | > 更新:2026-06-02 | ||
| 4 | |||
| 5 | ## Phase 0:原型跑通(当前阶段) | ||
| 6 | |||
| 7 | ### 目标 | ||
| 8 | 完成一个端到端可运行的本地 demo。 | ||
| 9 | |||
| 10 | ### 范围 | ||
| 11 | - [x] 合成数据生成 | ||
| 12 | - [x] 数据增强 | ||
| 13 | - [x] ECAPA embedding 模型 | ||
| 14 | - [x] 传统指纹匹配器 | ||
| 15 | - [x] HybridEngine | ||
| 16 | - [x] 最小训练入口 | ||
| 17 | - [x] 最小识别入口 | ||
| 18 | - [x] 文档补全 | ||
| 19 | |||
| 20 | ### 验收标准 | ||
| 21 | - 能生成数据 | ||
| 22 | - 能训练至少 1 epoch | ||
| 23 | - 能建立 reference 索引 | ||
| 24 | - 能对测试片段输出 Top-K 候选 | ||
| 25 | |||
| 26 | --- | ||
| 27 | |||
| 28 | ## Phase 1:研究验证 | ||
| 29 | |||
| 30 | ### 目标 | ||
| 31 | 验证不同场景下识别效果是否可接受。 | ||
| 32 | |||
| 33 | ### 任务 | ||
| 34 | - [ ] 增加 top-1 / top-5 / MRR 评估脚本 | ||
| 35 | - [ ] 对 clean / noisy / stretched / pitch-shifted 分开评测 | ||
| 36 | - [ ] 增加 query-by-humming 专项评测集 | ||
| 37 | - [ ] 加入更稳健的 negative sampling | ||
| 38 | - [ ] 补充 checkpoint / config versioning | ||
| 39 | |||
| 40 | --- | ||
| 41 | |||
| 42 | ## Phase 2:工程化 | ||
| 43 | |||
| 44 | ### 目标 | ||
| 45 | 把原型升级为可复现实验项目。 | ||
| 46 | |||
| 47 | ### 任务 | ||
| 48 | - [ ] 增加 `Makefile` 或 `justfile` | ||
| 49 | - [ ] 增加 `pytest` 基础测试 | ||
| 50 | - [ ] 增加日志与指标记录 | ||
| 51 | - [ ] 增加模型导出与加载规范 | ||
| 52 | - [ ] 增加 CLI 参数校验 | ||
| 53 | - [ ] 增加 Docker 运行方式 | ||
| 54 | |||
| 55 | --- | ||
| 56 | |||
| 57 | ## Phase 3:产品化 PoC | ||
| 58 | |||
| 59 | ### 目标 | ||
| 60 | 提供可被业务方调用的服务接口。 | ||
| 61 | |||
| 62 | ### 任务 | ||
| 63 | - [ ] FastAPI 服务化 | ||
| 64 | - [ ] 上传音频并返回候选歌曲 | ||
| 65 | - [ ] 曲库增量入库命令 | ||
| 66 | - [ ] 元数据管理接口 | ||
| 67 | - [ ] 结果缓存与批量检索 | ||
| 68 | |||
| 69 | --- | ||
| 70 | |||
| 71 | ## Phase 4:大规模检索 | ||
| 72 | |||
| 73 | ### 目标 | ||
| 74 | 支持百万级以上曲库。 | ||
| 75 | |||
| 76 | ### 任务 | ||
| 77 | - [ ] 接入 Faiss / HNSW | ||
| 78 | - [ ] embedding 分片与压缩 | ||
| 79 | - [ ] 双层召回 + 精排 | ||
| 80 | - [ ] 在线索引更新 | ||
| 81 | - [ ] 冷热分层存储 | ||
| 82 | |||
| 83 | --- | ||
| 84 | |||
| 85 | ## Phase 5:真实业务能力 | ||
| 86 | |||
| 87 | ### 目标 | ||
| 88 | 逼近真实听歌识曲产品。 | ||
| 89 | |||
| 90 | ### 任务 | ||
| 91 | - [ ] 真实版权音频数据接入 | ||
| 92 | - [ ] 哼唱专项模型/旋律塔 | ||
| 93 | - [ ] 多模态融合(旋律 + 声纹 + 指纹) | ||
| 94 | - [ ] 在线 A/B 评估 | ||
| 95 | - [ ] 监控与质量回流 |
| ... | @@ -5,267 +5,204 @@ | ... | @@ -5,267 +5,204 @@ |
| 5 | > 1. 当前项目已经走到哪里 | 5 | > 1. 当前项目已经走到哪里 |
| 6 | > 2. 应该先读哪些文档 | 6 | > 2. 应该先读哪些文档 |
| 7 | > 3. 应该从哪一步开始推进 | 7 | > 3. 应该从哪一步开始推进 |
| 8 | > 4. 哪些是当前稳定结论,哪些还只是待验证假设 | 8 | > 4. 哪些是稳定结论,哪些还是待验证缺口 |
| 9 | 9 | ||
| 10 | --- | 10 | --- |
| 11 | 11 | ||
| 12 | ## 首选启动流程(最短路径) | 12 | ## 0. 下次启动先做什么 |
| 13 | 13 | ||
| 14 | 下次启动如果目标是“先判断当前 host 能不能继续推进 Phase-1”,不要先手工翻很多文档,先直接跑: | 14 | 先执行: |
| 15 | 15 | ||
| 16 | ```bash | 16 | ```bash |
| 17 | cd /workspace/acr-engine | 17 | cd /workspace/acr-engine |
| 18 | /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 | 18 | /usr/local/miniconda3/bin/python scripts/run_planner_validation_commands_live.py \ |
| 19 | --dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \ | ||
| 20 | --output data/pgvector_eval/music20/planner_validation_commands_runner_report.json | ||
| 19 | ``` | 21 | ``` |
| 20 | 22 | ||
| 21 | 当前这条命令的 fresh evidence 已有: | 23 | 也可以用包装脚本:`acr-engine/scripts/start_phase1_shortest_path.sh 'postgres://d2:d2pass@127.0.0.1:5432/d2'` |
| 22 | 24 | ||
| 25 | 当前 fresh evidence: | ||
| 23 | - `executed_count = 4` | 26 | - `executed_count = 4` |
| 24 | - `all_passed = true` | 27 | - `all_passed = true` |
| 25 | 28 | ||
| 26 | 它会一次性执行: | 29 | 这条 runner 会一次性执行: |
| 27 | |||
| 28 | 1. `prereq_audit` | 30 | 1. `prereq_audit` |
| 29 | 2. `worker_contract_smoke` | 31 | 2. `worker_contract_smoke` |
| 30 | 3. `semantic_vector_negative_matrix` | 32 | 3. `semantic_vector_negative_matrix` |
| 31 | 4. `asset_level_upsert_validation` | 33 | 4. `asset_level_upsert_validation` |
| 32 | 34 | ||
| 33 | ### 跑完之后怎么判断 | 35 | 如果结果仍是: |
| 34 | |||
| 35 | 如果结果仍是当前状态: | ||
| 36 | - `downloads_root_exists = false` | 36 | - `downloads_root_exists = false` |
| 37 | - `ready_jobs = 0` | 37 | - `ready_jobs = 0` |
| 38 | - exact = `failed/unreadable_audio_assets` | 38 | - exact = `failed/unreadable_audio_assets` |
| 39 | - semantic = `4/4 failed` | 39 | - semantic = `4/4 failed` |
| 40 | 40 | ||
| 41 | 那么说明: | 41 | 则说明当前优先级仍然是: |
| 42 | 42 | 1. 补 `/workspace/downloads` 挂载 | |
| 43 | > 当前不该继续怀疑 PostgreSQL contract,而应该优先解决 **音频挂载** 与 **模型 runtime 依赖**。 | 43 | 2. 补 `torch / torchaudio / transformers / speechbrain` |
| 44 | |||
| 45 | 如果未来这条 runner 开始失败,才优先检查: | ||
| 46 | - planner 报告是否变了 | ||
| 47 | - validation scripts 是否回归 | ||
| 48 | - schema / worker contract 是否被破坏 | ||
| 49 | |||
| 50 | ## 一页结论 | ||
| 51 | |||
| 52 | 当前项目主线已经从“原型是否能跑通”切到: | ||
| 53 | |||
| 54 | > **为版权保护场景建设一个可演进的音乐 ACR / 检索系统**, | ||
| 55 | > 目标是让 `100w` 音频、约 `30w` 歌曲能够在未来通过 | ||
| 56 | > `canonical_song / work / recording / recording_asset / audio_window` | ||
| 57 | > 这条主数据链,以及 `model_registry / feature_set_registry` | ||
| 58 | > 这套模型注册机制,稳定支撑检索、归属、升级与回滚。 | ||
| 59 | |||
| 60 | 当前已经完成的关键交付: | ||
| 61 | - 文档体系已重构为“角色化阅读路径” | ||
| 62 | - SOTA 演进路径已明确:**Phase-1 先走 encoder-only** | ||
| 63 | - PostgreSQL 主数据与特征注册 DDL 已落地为推荐版 schema | ||
| 64 | - Phase-1 实施 checklist 和 model/feature/reference set 初始化手册已补齐 | ||
| 65 | - `acr_test` schema 上已经真实完成 Phase-1 `model_registry / feature_set_registry / reference_set_registry` bootstrap 验证 | ||
| 66 | 44 | ||
| 67 | 当前最重要的下一步不是继续写方案,而是: | 45 | 而不是回头怀疑 PostgreSQL contract。 |
| 68 | |||
| 69 | 1. **按 schema v2 落 PostgreSQL 主数据模型** | ||
| 70 | 2. **把 reference set / audio_window / feature_set 初始化做起来** | ||
| 71 | 3. **接入 MERT / MuQ 的 encoder-only 抽特征链** | ||
| 72 | 4. **跑通 fingerprint lane + semantic lane 的第一版聚合闭环** | ||
| 73 | 46 | ||
| 74 | --- | 47 | --- |
| 75 | 48 | ||
| 76 | ## 下次启动先读什么 | 49 | ## 1. 当前项目一句话状态 |
| 77 | 50 | ||
| 78 | ### 最短阅读顺序(推荐) | 51 | 项目已经从“原型能否跑通”转为: |
| 79 | 1. [docs/README.md](./README.md) | ||
| 80 | 2. [docs/acr-architecture.md](./acr-architecture.md) | ||
| 81 | 3. [docs/sota-evolution-guide.md](./sota-evolution-guide.md) | ||
| 82 | 4. [docs/postgresql-data-model.md](./postgresql-data-model.md) | ||
| 83 | 5. [docs/phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | ||
| 84 | 6. [docs/model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) | ||
| 85 | 7. [docs/phase1-worker-contract.md](./phase1-worker-contract.md) | ||
| 86 | 8. [docs/CHANGELOG.md](./CHANGELOG.md) | ||
| 87 | 52 | ||
| 88 | 如果只想快速恢复上下文,至少读前 5 个。 | 53 | > **面向版权保护 / 听歌识曲 / 版本归属的可演进音乐 ACR 系统。** |
| 89 | 54 | ||
| 90 | --- | 55 | 当前目标是让 `100w` 音频、约 `30w` 歌曲能通过稳定的数据主链和模型注册机制,支撑检索、归属、升级与回滚。 |
| 91 | 56 | ||
| 92 | ## 当前稳定结论(可以直接继承) | 57 | --- |
| 93 | 58 | ||
| 94 | ### 1. 技术方向 | 59 | ## 2. 当前稳定结论 |
| 95 | - **当前 ECAPA 路线保留为 baseline,不再作为长期主底座。** | ||
| 96 | - **Phase-1 主推 encoder-only foundation 路线。** | ||
| 97 | - exact lane:`Chromaprint` | ||
| 98 | - semantic lane 主 baseline:`MERT-v1-95M` | ||
| 99 | - semantic lane challenger:`MuQ` | ||
| 100 | - **Phase-2 才考虑 version / cover lane。** | ||
| 101 | - **Phase-3 再进入工业化检索/重排/治理。** | ||
| 102 | 60 | ||
| 103 | ### 2. 数据主链 | 61 | ### 技术路线 |
| 104 | 后续主数据一律围绕: | 62 | - exact lane:`Chromaprint` |
| 63 | - semantic baseline:`MERT-v1-95M` | ||
| 64 | - semantic challenger:`MuQ` | ||
| 65 | - `ECAPA`:historical baseline | ||
| 66 | - Phase-1:先走 **encoder-only**,先不用微调底座 | ||
| 105 | 67 | ||
| 68 | ### 数据主链 | ||
| 106 | ```text | 69 | ```text |
| 107 | canonical_song -> work -> recording -> recording_asset -> audio_window | 70 | canonical_song -> work -> recording -> recording_asset -> audio_window |
| 108 | ``` | 71 | ``` |
| 109 | 72 | ||
| 110 | 不要再退回到仅有 `song_id` 的扁平结构。 | 73 | ### 模型主链 |
| 111 | |||
| 112 | ### 3. 模型/特征主链 | ||
| 113 | 后续 encoder、feature、索引一律围绕: | ||
| 114 | |||
| 115 | ```text | 74 | ```text |
| 116 | model_registry -> feature_set_registry -> audio_embedding / audio_fingerprint -> retrieval_index_registry | 75 | model_registry -> feature_set_registry -> audio_embedding / audio_fingerprint -> retrieval_index_registry |
| 117 | ``` | 76 | ``` |
| 118 | 77 | ||
| 119 | 不要设计成固定列: | 78 | ### reference set 结论 |
| 120 | - `mert_embedding` | 79 | - 保留 `is_reference=true` |
| 121 | - `muq_embedding` | 80 | - 但生产切换必须依赖 `reference_set_registry / reference_set_member` |
| 122 | - `ecapa_embedding` | 81 | - 后续 A/B、热切换、回滚都围绕 reference set 版本化进行 |
| 123 | |||
| 124 | ### 4. reference 集合 | ||
| 125 | 当前结论是: | ||
| 126 | - 需要显式 `reference_set_registry` | ||
| 127 | - `is_reference=true` 仍然保留,但不再足够表达生产切换 | ||
| 128 | - 未来热 reference 集、A/B、回滚、encoder 升级都要依赖 reference set 版本化 | ||
| 129 | 82 | ||
| 130 | --- | 83 | --- |
| 131 | 84 | ||
| 132 | ## 本轮新增/修改的关键文件 | 85 | ## 3. 当前已经完成的关键交付 |
| 133 | 86 | ||
| 134 | ### 主文档 | 87 | ### 文档与设计 |
| 135 | - [docs/README.md](./README.md) | 88 | - 文档主入口已收敛到 `README -> start-here -> session-handoff` |
| 136 | - [docs/acr-architecture.md](./acr-architecture.md) | 89 | - SOTA 演进路径已明确 |
| 137 | - [docs/sota-evolution-guide.md](./sota-evolution-guide.md) | 90 | - PostgreSQL 主数据与特征模型已固定为 v2 推荐方案 |
| 138 | - [docs/postgresql-data-model.md](./postgresql-data-model.md) | 91 | - Phase-1 实施 checklist / registry bootstrap / worker contract 文档已齐备 |
| 139 | - [docs/phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | ||
| 140 | - [docs/model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) | ||
| 141 | 92 | ||
| 142 | ### SQL / schema | 93 | ### PostgreSQL / live contract |
| 143 | - `acr-engine/sql/acr_pg_schema_v2.sql` | 94 | - `acr-engine/sql/acr_pg_schema_v2.sql` 已落地 |
| 95 | - `model_registry / feature_set_registry / reference_set_registry` 已 live bootstrap 验证 | ||
| 96 | - `audio_embedding` 的 asset-level 幂等 upsert 已 live 验证 | ||
| 97 | - semantic vector-table 负例矩阵已 live 验证 | ||
| 98 | - planner validation commands 已可被 runner 一键执行 | ||
| 144 | 99 | ||
| 145 | ### 历史/补充说明(仍有参考价值) | 100 | ### worker / script |
| 146 | - [docs/sota-research-2026.md](./sota-research-2026.md) | 101 | - `run_chromaprint_job.py` 已具备真实写入路径 |
| 147 | - [docs/production-encoder-freeze-and-embedding-strategy.md](./production-encoder-freeze-and-embedding-strategy.md) | 102 | - `run_embedding_job.py` 已具备 preflight failure contract |
| 148 | - [docs/training-data-and-pgvector-guide.md](./training-data-and-pgvector-guide.md) | 103 | - `run_phase1_prereq_audit_live.py` 已能输出 host 前置条件审计 |
| 104 | - `run_planner_validation_commands_live.py` 已收敛最短验证链路 | ||
| 149 | 105 | ||
| 150 | --- | 106 | --- |
| 151 | 107 | ||
| 152 | ## 当前推荐的启动动作 | 108 | ## 4. 当前明确的 blocker |
| 153 | |||
| 154 | ## 路线 A:如果下次 session 继续“补文档/补设计” | ||
| 155 | 优先顺序: | ||
| 156 | 1. 补 **数据导入手册**:100w 音频如何映射到 `canonical_song/work/recording/recording_asset` | ||
| 157 | 2. 补 **检索聚合设计文档**:fingerprint lane + semantic lane 的分数融合与 song/work 聚合规则 | ||
| 158 | 3. 补 **索引与版本治理文档**:reference set / feature set / index set 的上线切换规则 | ||
| 159 | |||
| 160 | ## 路线 B:如果下次 session 开始“进入实现” | ||
| 161 | 直接按下面顺序推进: | ||
| 162 | 1. 建库执行 `acr-engine/sql/acr_pg_schema_v2.sql` | ||
| 163 | 2. 初始化 `canonical_song / work / recording / recording_asset` | ||
| 164 | 3. 初始化 `reference_set_registry` | ||
| 165 | 4. 生成 `audio_window` | ||
| 166 | 5. 初始化 `model_registry / feature_set_registry` | ||
| 167 | 6. 接入 MERT / MuQ encoder-only 抽特征 | ||
| 168 | 7. 构建 semantic index | ||
| 169 | 8. 跑通 query -> candidate -> canonical_song 闭环 | ||
| 170 | 109 | ||
| 171 | --- | 110 | ### 环境 blocker |
| 111 | - `/workspace/downloads` 缺失 | ||
| 112 | - 缺少 `torch` | ||
| 113 | - 缺少 `torchaudio` | ||
| 114 | - 缺少 `transformers` | ||
| 115 | - 缺少 `speechbrain` | ||
| 172 | 116 | ||
| 173 | ## 下次 session 第一条可直接复制执行的检查命令 | 117 | ### 能力 blocker |
| 118 | - 还未真实跑通 `MERT / MuQ` inference | ||
| 119 | - 还未完成线上融合策略 | ||
| 120 | - 还未接入更大规模真实 reference set | ||
| 174 | 121 | ||
| 175 | ```bash | 122 | 因此当前最该优先推进的是: |
| 176 | cd /workspace | 123 | > **把环境补齐,再把 semantic lane 从 guarded failure 推到真实抽特征。** |
| 177 | sed -n '1,220p' docs/README.md | 124 | |
| 178 | sed -n '1,260p' docs/phase1-implementation-checklist.md | 125 | --- |
| 179 | sed -n '1,260p' docs/model-feature-registry-bootstrap.md | ||
| 180 | sed -n '1,260p' docs/postgresql-data-model.md | ||
| 181 | ``` | ||
| 182 | 126 | ||
| 183 | 如果要直接看 schema: | 127 | ## 5. 下次启动先读什么 |
| 184 | 128 | ||
| 185 | ```bash | 129 | 按这个顺序即可: |
| 186 | cd /workspace | 130 | 1. [README.md](./README.md) |
| 187 | sed -n '1,320p' acr-engine/sql/acr_pg_schema_v2.sql | 131 | 2. [start-here.md](./start-here.md) |
| 188 | ``` | 132 | 3. [acr-architecture.md](./acr-architecture.md) |
| 133 | 4. [postgresql-data-model.md](./postgresql-data-model.md) | ||
| 134 | 5. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | ||
| 135 | 6. [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) | ||
| 136 | 7. [phase1-worker-contract.md](./phase1-worker-contract.md) | ||
| 137 | 8. [CHANGELOG.md](./CHANGELOG.md) | ||
| 189 | 138 | ||
| 190 | --- | 139 | --- |
| 191 | 140 | ||
| 192 | ## 当前实现与未来实现的边界 | 141 | ## 6. 下次启动优先动作 |
| 193 | |||
| 194 | ### 当前仓库已经有的东西 | ||
| 195 | - `Chromaprint` 原型链 | ||
| 196 | - `ECAPA` embedding baseline | ||
| 197 | - hybrid engine 原型 | ||
| 198 | - 早期 pgvector prototype schema | ||
| 199 | 142 | ||
| 200 | ### 当前还没做完的东西 | 143 | ### 路线 A:继续环境恢复 |
| 201 | - PostgreSQL v2 schema 的实际落库 | 144 | 1. 检查 `/workspace/downloads` 是否已挂载 |
| 202 | - Phase-1 的 reference set 初始化 | 145 | 2. 检查 `torch / torchaudio / transformers / speechbrain` 是否已可导入 |
| 203 | - MERT / MuQ encoder-only 特征抽取与入库 | 146 | 3. 重跑 planner validation runner |
| 204 | - semantic lane 的第一版 production-oriented 聚合 | 147 | 4. 确认 `ready_jobs` 是否从 `0` 开始提升 |
| 205 | 148 | ||
| 206 | 所以: | 149 | ### 路线 B:继续语义特征抽取实现 |
| 150 | 1. 查看 `acr-engine/workers/run_embedding_job.py` | ||
| 151 | 2. 保持现有失败语义 contract | ||
| 152 | 3. 接入真实 inference adapter | ||
| 153 | 4. 复用现有 `audio_embedding` upsert 逻辑 | ||
| 207 | 154 | ||
| 208 | > 当前项目的“方案层”已经足够启动实现, | 155 | ### 路线 C:继续数据规模化落库 |
| 209 | > 下次 session 不应再从头讨论“要不要 song/work/recording”, | 156 | 1. 查看 [postgresql-data-model.md](./postgresql-data-model.md) |
| 210 | > 而应该直接进入 **Schema -> Reference Set -> Feature Set -> Extraction -> Retrieval** 的执行链。 | 157 | 2. 查看 [postgres_db_schema_samples.md](./postgres_db_schema_samples.md) |
| 158 | 3. 规划 100w 音频导入批次 | ||
| 159 | 4. 固定 `reference_set` / `feature_set` / `index` 版本治理 | ||
| 211 | 160 | ||
| 212 | --- | 161 | --- |
| 213 | 162 | ||
| 214 | ## 当前验证状态 | 163 | ## 7. 当前不要再重复讨论的结论 |
| 215 | 164 | ||
| 216 | ### 已验证 | 165 | - 不要回退到只有 `song_id` 的扁平表 |
| 217 | - 新文档结构已补齐并接入 README | 166 | - 不要把 embedding 设计成固定列 |
| 218 | - Phase-1 方案、PostgreSQL 设计、实施 checklist、registry bootstrap 均已提交 | 167 | - 不要在 Phase-1 先讨论重新训练底座 |
| 219 | - architect 审核结论:**APPROVED** | 168 | - 不要把当前问题误判成 PostgreSQL schema 问题 |
| 220 | - 代码已推送远端 | ||
| 221 | - PostgreSQL `acr_test` live 路径已再次验证:`recording` / `audio_window` / `audio_embedding` 三类 lineage trigger 均有真实负例证据 | ||
| 222 | - 机械校验已补齐:`live_pgvector_music20_eval.py` 的 `py_compile` 通过,相关变更 `diff --check` 通过 | ||
| 223 | - PostgreSQL `acr_test` schema 上已真实写入 Phase-1 registry bootstrap:`chromaprint / mert / muq / ecapa` + 5 组 feature set + `phase1_hot_reference_v1` | ||
| 224 | - Phase-1 registry bootstrap 已有幂等性证据:同 schema 连续执行两次后,`model_registry=5 / feature_set_registry=6 / reference_set_registry=2` 保持不变 | ||
| 225 | - PostgreSQL `acr_test` schema 上已真实创建 5 条 `feature_extraction_job`,后续 MERT / MuQ 接入可直接从 pending jobs 启动 | ||
| 226 | - PostgreSQL `acr_test` schema 上已真实生成 Phase-1 extraction execution plan,当前顺序是 `chromaprint -> mert -> mert-long -> muq -> ecapa` | ||
| 227 | - extraction plan 报告里已包含 `command_suggestions / primary_command`,下次可直接从 plan 抄 worker 命令模板 | ||
| 228 | - Phase-1 worker 入口已真实落地:`run_chromaprint_job.py / run_embedding_job.py / mark_job_status.py` | ||
| 229 | - 下一阶段已经不是“补 planner”,而是把 dry-run worker 替换为真实 extractor,并把 `audio_fingerprint / audio_embedding` 写入做成幂等执行 | ||
| 230 | - semantic lane 也已完成 live failure contract:`run_embedding_job.py` 现在会同时暴露 `unreadable_audio_assets` 与 `model_runtime_unavailable`,而不是把失败伪装成 completed | ||
| 231 | - `audio_embedding` 已补上 window / asset 双路唯一键,后续真实 encoder 只需替换 inference adapter 即可复用同一 upsert 合同 | ||
| 232 | - `scripts/run_phase1_embedding_preflight_matrix_live.py` 已跑通,4 条 semantic jobs(mert/muq/ecapa)在 `acr_test` 上都被稳定标记为 `preflight_failed`;当前共性 blocker 已收敛为 `/workspace/downloads` 缺失 + 语义模型 runtime 缺失 | ||
| 233 | - `scripts/validate_audio_embedding_asset_upsert_live.py` 已在隔离 schema `acr_asset_upsert_test` 上验证 `uq_audio_embedding_feature_asset`:重复 insert 会被唯一键拒绝,upsert 会复用同一 `embedding_id`,说明 asset-level 幂等键也已有真实证据 | ||
| 234 | - `scripts/run_phase1_worker_contract_smoke_live.py` 已提供一条命令的全局 smoke:当前 exact lane = `failed/unreadable_audio_assets`,semantic lane = `4/4 failed`,共性 blocker 已固化为音频挂载缺失 + 语义模型 runtime 缺失 | ||
| 235 | - `scripts/run_embedding_vector_table_negative_matrix_live.py` 已在 live PostgreSQL 上补齐 semantic vector-table 负例矩阵:`vector_table_dim_mismatch`、`vector_table_not_allowlisted`、`vector_table_missing_in_schema` 三类错误都能被稳定写入 `vector_table_report.reason` | ||
| 236 | - `scripts/run_phase1_prereq_audit_live.py` 已给出当前 host 的先决条件审计:`downloads_root_exists=false`、`ready_jobs=0/5`,并把 `torch/torchaudio/transformers/speechbrain` 的缺失状态按 job 落成 JSON 报告 | ||
| 237 | - `phase1_extraction_plan_report.json` 现已附带 `validation_commands`,下次 session 可以直接从 planner 复制 `prereq_audit / worker_contract_smoke / semantic_vector_negative_matrix / asset_level_upsert_validation` 四类命令 | ||
| 238 | - `phase1_validation_commands_execution_report.json` 已证明 planner 里的 4 条 validation commands 都可以被直接脚本消费且 `returncode=0`:`prereq_audit`、`worker_contract_smoke`、`semantic_vector_negative_matrix`、`asset_level_upsert_validation` | ||
| 239 | - `scripts/run_planner_validation_commands_live.py` 已把这 4 条 validation commands 收敛成通用 runner;当前 `planner_validation_commands_runner_report.json` 显示 `executed_count=4` 且 `all_passed=true` | ||
| 240 | - `phase1_hot_reference_v1` 在 `acr_test` 里已经真实补齐 `20` 个 reference members,因此 worker dry-run 当前看到的 scope 已是 `20 recordings / 20 assets / 20 windows` | ||
| 241 | - worker contract 现在已有基础前置状态保护;重复执行同一 chromaprint dry-run job 会被 `expected_status=pending` 明确拒绝,证据见 `phase1_worker_double_claim_guard_report.json` | ||
| 242 | - exact lane 的 `run_chromaprint_job.py` 已具备非 dry-run 写入路径;当前在 `acr_test` 的 live 结果是因为 `/workspace/downloads/...` 缺失而明确 `failed`,不是继续假装 `completed` | ||
| 243 | |||
| 244 | ### 未验证 / 仍是缺口 | ||
| 245 | - **未实际跑 MERT / MuQ encoder-only 特征抽取** | ||
| 246 | - **semantic / cover 等后续 lane 仍主要停留在 dry-run;exact lane 已接上真实 `audio_fingerprint` 写入路径,但当前容器缺 reference 音频挂载,live 结果仍停在可审计失败** | ||
| 247 | - **还未落更大规模的生产 reference set 真实业务数据(当前仅验证了 `acr_test` 下的 20-song live members)** | ||
| 248 | - **未定义最终线上分数融合细则** | ||
| 249 | - **type_8 / type_16 还没有进入当前 live JSONL 的 PostgreSQL 实测链** | ||
| 250 | - **当前容器里缺少 `/workspace/downloads`,因此暂时无法直接从业务样本目录继续补 type_8 / type_16 live query** | ||
| 251 | |||
| 252 | 因此下次 session 应优先从这些未验证缺口里挑一条推进,而不是重复写总方案。 | ||
| 253 | 169 | ||
| 254 | --- | 170 | --- |
| 255 | 171 | ||
| 256 | ## 最近相关提交 | 172 | ## 8. 关键文件入口 |
| 173 | |||
| 174 | ### 文档 | ||
| 175 | - [README.md](./README.md) | ||
| 176 | - [start-here.md](./start-here.md) | ||
| 177 | - [postgresql-data-model.md](./postgresql-data-model.md) | ||
| 178 | - [phase1-worker-contract.md](./phase1-worker-contract.md) | ||
| 257 | 179 | ||
| 258 | 按当前 handoff 相关主线,最近重要提交是: | 180 | ### 代码与脚本 |
| 259 | - `a549d1d` — Clarify the ACR evolution path and freeze a production-grade data model | 181 | - `acr-engine/sql/acr_pg_schema_v2.sql` |
| 260 | - `e514a6c` — Keep the new ACR architecture guide clean for follow-up edits | 182 | - `acr-engine/workers/run_chromaprint_job.py` |
| 261 | - `4b23f54` — Make the Phase-1 ACR plan executable for each delivery role | 183 | - `acr-engine/workers/run_embedding_job.py` |
| 262 | - `0679481` — Attach runnable command templates to the extraction plan | 184 | - `acr-engine/scripts/run_planner_validation_commands_live.py` |
| 185 | - `acr-engine/scripts/run_phase1_prereq_audit_live.py` | ||
| 263 | 186 | ||
| 264 | 如果下次需要追踪文档补充点,可以从这三个提交开始看。 | 187 | --- |
| 188 | |||
| 189 | ## 9. 当前验证状态摘要 | ||
| 190 | |||
| 191 | ### 已验证 | ||
| 192 | - planner validation runner 可执行且 `all_passed = true` | ||
| 193 | - exact lane 当前会诚实落成 `failed/unreadable_audio_assets` | ||
| 194 | - semantic lane 当前会诚实落成 `preflight_failed` | ||
| 195 | - asset-level embedding upsert 幂等合同已验证 | ||
| 196 | - vector table 负例矩阵已验证 | ||
| 197 | - prerequisites audit 已验证 | ||
| 198 | |||
| 199 | ### 未验证 | ||
| 200 | - MERT / MuQ 真实 inference | ||
| 201 | - 更大规模生产 reference set 导入 | ||
| 202 | - 最终线上融合与重排策略 | ||
| 265 | 203 | ||
| 266 | --- | 204 | --- |
| 267 | 205 | ||
| 268 | ## 一句话交接 | 206 | ## 一句话 handoff |
| 269 | 207 | ||
| 270 | > **下次启动不要再从“要不要换模型、要不要重构数据结构”开始讨论。** | 208 | > 下次接手不要再从总方案开始,先跑 runner;若结果仍显示 downloads/runtime 缺失,就优先补环境,再推进 semantic lane 真实抽特征。 |
| 271 | > 这些方向已经定了。直接从 **PostgreSQL v2 schema 落库 + Phase-1 worker/extractor 执行链** 开始推进。 | ... | ... |
docs/start-here.md
0 → 100644
| 1 | # Start Here / 新同学接手入口 | ||
| 2 | |||
| 3 | > 目标:让新来的同学在 **10 分钟内**知道:先跑什么、先读什么、当前卡在哪、下一步该做什么。 | ||
| 4 | |||
| 5 | --- | ||
| 6 | |||
| 7 | ## 1. 先执行这条命令 | ||
| 8 | |||
| 9 | ```bash | ||
| 10 | cd /workspace/acr-engine | ||
| 11 | /usr/local/miniconda3/bin/python scripts/run_planner_validation_commands_live.py \ | ||
| 12 | --dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \ | ||
| 13 | --output data/pgvector_eval/music20/planner_validation_commands_runner_report.json | ||
| 14 | ``` | ||
| 15 | |||
| 16 | 也可以用包装脚本:`acr-engine/scripts/start_phase1_shortest_path.sh 'postgres://d2:d2pass@127.0.0.1:5432/d2'` | ||
| 17 | |||
| 18 | ### 当前 fresh evidence | ||
| 19 | - `executed_count = 4` | ||
| 20 | - `all_passed = true` | ||
| 21 | |||
| 22 | ### 这条命令会执行 | ||
| 23 | 1. `prereq_audit` | ||
| 24 | 2. `worker_contract_smoke` | ||
| 25 | 3. `semantic_vector_negative_matrix` | ||
| 26 | 4. `asset_level_upsert_validation` | ||
| 27 | |||
| 28 | ### 看到下面这些结果时应该如何判断 | ||
| 29 | 如果你看到: | ||
| 30 | - `downloads_root_exists = false` | ||
| 31 | - `ready_jobs = 0` | ||
| 32 | - exact lane = `failed/unreadable_audio_assets` | ||
| 33 | - semantic lane = `4/4 failed` | ||
| 34 | |||
| 35 | 说明当前优先级是: | ||
| 36 | 1. 挂载 `/workspace/downloads` | ||
| 37 | 2. 安装 `torch / torchaudio / transformers / speechbrain` | ||
| 38 | |||
| 39 | 也就是说: | ||
| 40 | > 当前首要问题是运行环境前置条件,不是 PostgreSQL schema,也不是 worker contract 设计错误。 | ||
| 41 | |||
| 42 | --- | ||
| 43 | |||
| 44 | ## 2. 接手时只读这 5 份文档 | ||
| 45 | |||
| 46 | 1. [README.md](./README.md) | ||
| 47 | 2. [session-handoff.md](./session-handoff.md) | ||
| 48 | 3. [acr-architecture.md](./acr-architecture.md) | ||
| 49 | 4. [postgresql-data-model.md](./postgresql-data-model.md) | ||
| 50 | 5. [phase1-implementation-checklist.md](./phase1-implementation-checklist.md) | ||
| 51 | |||
| 52 | 如果你负责算法或检索,再补: | ||
| 53 | - [sota-evolution-guide.md](./sota-evolution-guide.md) | ||
| 54 | - [model-feature-registry-bootstrap.md](./model-feature-registry-bootstrap.md) | ||
| 55 | - [phase1-worker-contract.md](./phase1-worker-contract.md) | ||
| 56 | |||
| 57 | --- | ||
| 58 | |||
| 59 | ## 3. 用一句话理解项目 | ||
| 60 | |||
| 61 | 我们在做的是一个面向 **版权保护 / 听歌识曲 / 版本归属** 的音乐 ACR 系统, | ||
| 62 | 目标是从 `100w` 音频、约 `30w` 歌曲中,快速定位正确的 `song_id / work / recording` 归属。 | ||
| 63 | |||
| 64 | --- | ||
| 65 | |||
| 66 | ## 4. 当前主线方案 | ||
| 67 | |||
| 68 | ### 检索主线 | ||
| 69 | - exact lane:`Chromaprint` | ||
| 70 | - semantic lane baseline:`MERT-v1-95M` | ||
| 71 | - semantic lane challenger:`MuQ` | ||
| 72 | - historical baseline:`ECAPA` | ||
| 73 | |||
| 74 | ### 数据主线 | ||
| 75 | ```text | ||
| 76 | canonical_song -> work -> recording -> recording_asset -> audio_window | ||
| 77 | ``` | ||
| 78 | |||
| 79 | ### 模型主线 | ||
| 80 | ```text | ||
| 81 | model_registry -> feature_set_registry -> audio_embedding / audio_fingerprint -> retrieval_index_registry | ||
| 82 | ``` | ||
| 83 | |||
| 84 | --- | ||
| 85 | |||
| 86 | ## 5. 当前哪些已经稳定 | ||
| 87 | |||
| 88 | - PostgreSQL v2 schema 已落地 | ||
| 89 | - registry bootstrap 已有 live 验证 | ||
| 90 | - worker contract 已有 live 验证 | ||
| 91 | - exact / semantic 的失败语义已可审计 | ||
| 92 | - planner 已能输出 validation commands | ||
| 93 | - planner validation runner 已可一键执行 | ||
| 94 | |||
| 95 | ## 6. 当前哪些还没完成 | ||
| 96 | |||
| 97 | - 还没有真正跑通 MERT / MuQ inference | ||
| 98 | - 当前 host 没有 `/workspace/downloads` | ||
| 99 | - 当前 host 缺 `torch / torchaudio / transformers / speechbrain` | ||
| 100 | - 还没完成最终线上融合策略 | ||
| 101 | - 还没接入更大规模真实 reference set | ||
| 102 | |||
| 103 | --- | ||
| 104 | |||
| 105 | ## 7. 如果你现在继续推进,按这个顺序 | ||
| 106 | |||
| 107 | ### 路线 A:先解环境 | ||
| 108 | 1. 挂载 `/workspace/downloads` | ||
| 109 | 2. 安装 semantic runtime 依赖 | ||
| 110 | 3. 重跑 planner validation runner | ||
| 111 | 4. 确认 `ready_jobs` 是否开始恢复 | ||
| 112 | |||
| 113 | ### 路线 B:先解实现 | ||
| 114 | 1. 阅读 [phase1-worker-contract.md](./phase1-worker-contract.md) | ||
| 115 | 2. 阅读 `acr-engine/workers/run_embedding_job.py` | ||
| 116 | 3. 用真实 inference adapter 替换 guarded failure path | ||
| 117 | 4. 保持当前 PostgreSQL contract 不变 | ||
| 118 | |||
| 119 | ### 路线 C:先解数据 | ||
| 120 | 1. 阅读 [postgresql-data-model.md](./postgresql-data-model.md) | ||
| 121 | 2. 阅读 [postgres_db_schema_samples.md](./postgres_db_schema_samples.md) | ||
| 122 | 3. 准备更大的 reference set | ||
| 123 | 4. 保持 `reference_set_registry / reference_set_member` 版本化 | ||
| 124 | |||
| 125 | --- | ||
| 126 | |||
| 127 | ## 8. 当前不建议优先做的事 | ||
| 128 | |||
| 129 | - 不要重新讨论要不要 `song/work/recording` 分层 | ||
| 130 | - 不要回退到只有 `song_id` 的扁平表 | ||
| 131 | - 不要先讨论重新训练底座 | ||
| 132 | - 不要把当前问题误判成 PostgreSQL contract 设计问题 | ||
| 133 | |||
| 134 | --- | ||
| 135 | |||
| 136 | ## 9. 仓库常用入口 | ||
| 137 | |||
| 138 | ### 文档 | ||
| 139 | - [README.md](./README.md) | ||
| 140 | - [session-handoff.md](./session-handoff.md) | ||
| 141 | - [postgresql-data-model.md](./postgresql-data-model.md) | ||
| 142 | - [phase1-worker-contract.md](./phase1-worker-contract.md) | ||
| 143 | |||
| 144 | ### 脚本 | ||
| 145 | - `acr-engine/scripts/run_planner_validation_commands_live.py` | ||
| 146 | - `acr-engine/scripts/run_phase1_prereq_audit_live.py` | ||
| 147 | - `acr-engine/scripts/run_phase1_worker_contract_smoke_live.py` | ||
| 148 | - `acr-engine/scripts/run_embedding_vector_table_negative_matrix_live.py` | ||
| 149 | - `acr-engine/scripts/validate_audio_embedding_asset_upsert_live.py` | ||
| 150 | |||
| 151 | --- | ||
| 152 | |||
| 153 | ## 一句话结论 | ||
| 154 | |||
| 155 | > 新同学接手时,先跑 runner,再读 5 份核心文档;当前首要问题是环境前置条件,不是 schema/contract 本身。 |
-
Please register or sign in to post a comment