PostgreSQL DB Schema Samples / 落库样例与 live 测试链路
更新:2026-06-04
目标:给后续开发一个可直接照着做的 PostgreSQL 落库样例,同时保留一次真实pgvectorlive 测试的证据。
一页结论
这次已经在用户提供的 PostgreSQL 上完成了下面几件事:
-
真实连接 PostgreSQL 成功
- DSN:
postgres://d2:***@127.0.0.1:5432/d2 - PostgreSQL:
17.5 - 已确认扩展
vector存在
- DSN:
-
真实应用 schema v2 成功
- 使用隔离 schema:
acr_test - DDL 来源:
acr-engine/sql/acr_pg_schema_v2.sql - 已成功创建主数据、registry、embedding、candidate、decision 等表
- 使用隔离 schema:
-
真实插入了一套完整的样例数据链
canonical_song -> work -> recording -> recording_asset -> audio_windowmodel_registry -> feature_set_registry -> audio_embedding -> retrieval_index_registryreference_set_registry -> reference_set_member
-
真实跑通了一轮 PostgreSQL + pgvector 检索评测
- 输入:
acr-engine/data/pgvector_eval/music20/*.jsonl - 输出:
acr-engine/data/pgvector_eval/music20/live_pgvector_report.json - live pgvector 指标和现有 FAISS stand-in 指标一致:
- overall
top1=0.9091 - overall
top3=0.9545 -
query_type=1:top1=1.0 -
query_type=7:top1=0.0,top3=0.5
- overall
- 输入:
-
lineage trigger 已被验证有效
- 脚本主动构造了三类错误 lineage:
recordingaudio_windowaudio_embedding
- PostgreSQL 都正确拒绝插入
- 脚本主动构造了三类错误 lineage:
本次使用的 live 测试资产
数据库
| 项目 | 值 |
|---|---|
| Host | 127.0.0.1 |
| Port | 5432 |
| DB | d2 |
| User | d2 |
| PostgreSQL | 17.5 |
| 扩展 |
vector, pg_trgm, ltree, hstore 等 |
| 本次测试 schema | acr_test |
代码与产物
| 类型 | 路径 |
|---|---|
| 推荐 DDL | acr-engine/sql/acr_pg_schema_v2.sql |
| live 测试脚本 | acr-engine/scripts/live_pgvector_music20_eval.py |
| registry bootstrap 脚本 | acr-engine/scripts/bootstrap_phase1_model_registry_live.py |
| live 报告 | acr-engine/data/pgvector_eval/music20/live_pgvector_report.json |
| FAISS 对照报告 | acr-engine/data/pgvector_eval/music20/songid_eval_report_fresh.json |
| registry bootstrap 报告 | acr-engine/data/pgvector_eval/music20/phase1_registry_bootstrap_report.json |
| registry bootstrap 幂等性报告 | acr-engine/data/pgvector_eval/music20/phase1_registry_bootstrap_idempotency_report.json |
| extraction job bootstrap 报告 | acr-engine/data/pgvector_eval/music20/phase1_extraction_jobs_report.json |
| extraction plan 报告 | acr-engine/data/pgvector_eval/music20/phase1_extraction_plan_report.json |
| reference member bootstrap 报告 | acr-engine/data/pgvector_eval/music20/phase1_reference_member_bootstrap_report.json |
| chromaprint worker dry-run 报告 | acr-engine/data/pgvector_eval/music20/phase1_worker_chromaprint_dry_run.json |
| embedding worker dry-run 报告 | acr-engine/data/pgvector_eval/music20/phase1_worker_embedding_dry_run.json |
| job status 手工回写报告 | acr-engine/data/pgvector_eval/music20/phase1_worker_mark_pending_report.json |
| double-claim guard 报告 | acr-engine/data/pgvector_eval/music20/phase1_worker_double_claim_guard_report.json |
| 历史对照报告 | acr-engine/data/pgvector_eval/music20/songid_eval_report.json |
这次实际落进去的数据链
flowchart LR
A[reference_embeddings.jsonl] --> B[canonical_song]
B --> C[work]
C --> D[recording]
D --> E[recording_asset]
E --> F[audio_window]
F --> G[audio_embedding]
G --> H[audio_embedding_vector_192]
I[model_registry] --> J[feature_set_registry]
J --> G
K[reference_set_registry] --> L[reference_set_member]
D --> L
M[query_embeddings.jsonl] --> N[SQL pgvector search]
H --> N
N --> O[retrieval_candidate]
O --> P[match_decision]
为什么这次 live 测试要把 24 维 embedding pad 到 192 维
当前 schema v2 里提供了:
audio_embedding_vector_192audio_embedding_vector_768
而这次本地 music20 样例 embedding 是 24 维 chroma 特征。
所以本次 live 测试采用的策略是:
-
逻辑维度:
24 -
物理落盘维度:
192 -
做法:后面补
0,写入vector(192)
这样做的原因:
- 不需要临时改 schema
- 仍然可以验证 schema v2 + pgvector + retrieval 链路
- 对这批样例的余弦相似度排序不会产生方向性错误(所有向量都以同样方式补零)
这只是验证链路用法。
生产里应按真实 encoder 维度选择:
-
MERT/MuQ之类高维 embedding:直接落合适物理表 - 如果后续维度更多,建议继续扩成
audio_embedding_vector_<dim>分桶策略
本次实际落盘样例
以下内容来自 acr_test schema 的真实查询结果。
1. canonical_song
{"canonical_song_id":1,"biz_song_code":"100","title":"Song 100","primary_artist":"Artist 100","rights_status":"protected"}
{"canonical_song_id":2,"biz_song_code":"101","title":"Song 101","primary_artist":"Artist 101","rights_status":"protected"}
2. work
{"work_id":1,"canonical_song_id":1,"work_code":"work-100","work_title":"Song 100","composer":"Composer 100"}
{"work_id":2,"canonical_song_id":2,"work_code":"work-101","work_title":"Song 101","composer":"Composer 101"}
3. recording
{"recording_id":1,"work_id":1,"canonical_song_id":1,"recording_code":"rec-100","version_type":"master_reference","is_reference":true,"reference_priority":100}
{"recording_id":2,"work_id":2,"canonical_song_id":2,"recording_code":"rec-101","version_type":"master_reference","is_reference":true,"reference_priority":101}
4. recording_asset
{"asset_id":1,"recording_id":1,"asset_role":"reference_audio","storage_uri":"/workspace/downloads/100/type_11/93dfdeb0-7da5-42a8-9c71-cf12af57dd191650256918.wav","storage_scheme":"file","duration_sec":8.0,"ingest_status":"ready"}
{"asset_id":2,"recording_id":2,"asset_role":"reference_audio","storage_uri":"/workspace/downloads/101/type_11/83c0c07f-4f96-4ff4-998c-58db910f3cfa1650256915.wav","storage_scheme":"file","duration_sec":8.0,"ingest_status":"ready"}
5. audio_window
{"window_id":1,"asset_id":1,"recording_id":1,"work_id":1,"canonical_song_id":1,"window_index":0,"start_sec":0.0,"end_sec":8.0,"segment_role":"reference","segment_type":"full_clip"}
{"window_id":2,"asset_id":2,"recording_id":2,"work_id":2,"canonical_song_id":2,"window_index":0,"start_sec":0.0,"end_sec":8.0,"segment_role":"reference","segment_type":"full_clip"}
6. model_registry / feature_set_registry
{"model_id":1,"model_name":"local_chroma24","model_family":"chroma_baseline","model_version":"v1","output_embedding_dim":24,"default_window_sec":8.0}
{"feature_set_id":1,"model_id":1,"feature_name":"chroma24_songid_eval","embedding_dim":24,"distance_metric":"cosine","feature_schema_version":"v1"}
7. audio_embedding
{"embedding_id":1,"feature_set_id":1,"asset_id":1,"window_id":1,"recording_id":1,"canonical_song_id":1,"embedding_storage_mode":"pgvector_inline_192_padded","is_indexed":true}
{"embedding_id":2,"feature_set_id":1,"asset_id":2,"window_id":2,"recording_id":2,"canonical_song_id":2,"embedding_storage_mode":"pgvector_inline_192_padded","is_indexed":true}
8. reference_set_registry / retrieval_index_registry
{"reference_set_id":1,"set_name":"music20_live_reference","encoder_scope":"local_chroma24","status":"active"}
{"retrieval_index_id":1,"feature_set_id":1,"index_name":"music20_live_pgvector_hnsw","index_backend":"pgvector","index_type":"hnsw_cosine","row_count":20,"index_status":"active"}
9. retrieval_candidate / match_decision
{"retrieval_candidate_id":1,"query_id":"music20-q0000-t1-song100","source_lane":"semantic","candidate_level":"canonical_song","candidate_id":1,"raw_score":0.99998549,"normalized_score":0.90998694,"rank_no":1}
{"retrieval_candidate_id":2,"query_id":"music20-q0000-t1-song100","source_lane":"semantic","candidate_level":"canonical_song","candidate_id":17,"raw_score":0.9527432,"normalized_score":0.86746888,"rank_no":2}
{"match_decision_id":1,"query_id":"music20-q0000-t1-song100","canonical_song_id":1,"decision_status":"matched","decision_score":0.90998694}
本次 live 测试的表规模
| 表 | 行数 |
|---|---|
canonical_song |
20 |
work |
20 |
recording |
20 |
recording_asset |
20 |
audio_window |
20 |
audio_embedding |
20 |
retrieval_candidate |
220 |
match_decision |
22 |
说明:
- 20 条 reference song
- 22 条 query
- 每条 query 写入 top10 candidate,因此
22 * 10 = 220
本次测试链路与逻辑
A. schema / 数据完整性测试
- 连接 PostgreSQL
- 创建隔离 schema:
acr_test - 执行
acr_pg_schema_v2.sql - 初始化:
model_registryfeature_set_registryreference_set_registryretrieval_index_registry
- 导入 20 条 reference 样例
- 验证表计数是否正确
- 主动插入三类错误 lineage:
-
recording.canonical_song_id与work.canonical_song_id不一致 -
audio_window.recording_id与recording_asset.recording_id不一致 -
audio_embedding的canonical_song_id与父audio_window不一致
-
- 预期 PostgreSQL trigger 拒绝这些坏写入
B. live 检索评测测试
- 从
reference_embeddings.jsonl读 20 条 reference embedding - 写入
audio_embedding+audio_embedding_vector_192 - 从
query_embeddings.jsonl读 22 条 query embedding - 每条 query 用 SQL 执行
pgvector cosine检索 - 在应用层做 song-level aggregation:
max_simtop3_avgvotecombined = 0.6 * max_sim + 0.3 * top3_avg + 0.1 * vote_factor
- 将 top10 候选落表到
retrieval_candidate - 将 top1 决策落表到
match_decision - 计算:
- overall
top1/top3/top10/mrr by_query_typeconfusion_focus
- overall
C. confusion test 口径
当前这次 live 样例里只实际包含:
type_1
Phase-1 worker dry-run 测试链路(新增)
这一步解决的是:
planner 虽然已经能输出可复制命令,但之前仓库里没有真正的 worker 可以消费这些命令。
现在已经补上最小真实 worker:
acr-engine/workers/mark_job_status.pyacr-engine/workers/run_chromaprint_job.pyacr-engine/workers/run_embedding_job.py
测试目标
验证下面这条链是真实可走通的:
flowchart TD
A[feature_extraction_job pending] --> B[planner 生成命令模板]
B --> C[worker 读取 extraction_job_id]
C --> D[worker 解析 feature/model/scope]
D --> E[worker 回写 running/completed]
E --> F[bootstrap 脚本可再次恢复 pending]
当前验证口径
这轮先不跑真实模型推理,而是先验证工业执行面:
-
run_chromaprint_job.py- 真实连接 PostgreSQL
- 读取
feature_extraction_job=1 - 解析
reference_set:phase1_hot_reference_v1 - 回写
running -> completed
-
run_embedding_job.py- 真实连接 PostgreSQL
- 读取
feature_extraction_job=2 - 解析
mert v1-95m - 回写
running -> completed
-
再次执行
bootstrap_phase1_extraction_jobs_live.py- 把 job 状态恢复为
pending - 保证后续 session 可以从同一批 jobs 继续推进
- 把 job 状态恢复为
-
plan_phase1_extraction_jobs_live.py- 当前生成的主命令模板已显式带:
cd /workspace/acr-engine &&PG_DSN="${PG_DSN:?set PG_DSN}"--complete-dry-run
- 因此
primary_command已经可以直接复现当前 dry-run 状态流转
- 当前生成的主命令模板已显式带:
为什么先做 dry-run
因为当前第一优先级是把下面这些东西固定住:
- job contract
- status transitions
- scope 解析
- planner -> worker 命令兼容性
等这个骨架稳定后,再把真实的:
- chromaprint 提取
- MERT / MuQ embedding 提取
接进去,整体风险更低。
当前 live 结果的关键更新
本轮已经新增:
acr-engine/scripts/bootstrap_phase1_reference_members_live.py
并已把 acr_test.phase1_hot_reference_v1 真实挂上 20 条 reference recordings,因此当前 worker dry-run 看到的 scope 已变成:
recording_count=20ready_asset_count=20active_window_count=20
这说明当前验证已经从“空 scope 状态机演示”推进到:
- planner -> worker 命令兼容
- worker -> PostgreSQL 状态流转可用
- reference_set -> recording/asset/window scope 解析可用
仍然要注意:
- 这依然是 dry-run
- 还不是真实特征抽取吞吐验证
当前并发/重试保护验证
本轮还额外做了一个故意的重复执行测试:
- 先让
feature_extraction_job=1从pending -> running -> completed - 不做 reset,直接再次执行同一个 chromaprint dry-run worker
- 预期第二次执行失败,因为 worker 认领 job 时要求:
expected_status = pending
实际结果见:
phase1_worker_double_claim_guard_report.json
关键证据:
double_claim_exit_code = 1stderr = failed to update feature_extraction_job=1 with expected_status=pending
这证明当前最小 worker contract 已经具备:
- 基础 claim guard
- 基础重复执行保护
exact lane 非 dry-run 写入尝试(新增)
这轮又继续向前推进了一步:
run_chromaprint_job.py已经不再只是 dry-run。
当前行为:
-
如果 reference asset 对应音频文件可读:
- 提取 repo-local chromaprint-style hash
- 写 artifact JSON
- 写
audio_fingerprint - job 标记为
completed
-
如果 reference asset 对应音频文件不可读:
- job 标记为
failed - 在
metadata_json里写入:failure_reasonmissing_asset_countmissing_asset_samples
- job 标记为
本轮 live 结果
报告:
acr-engine/data/pgvector_eval/music20/phase1_worker_chromaprint_write_attempt.jsonacr-engine/data/pgvector_eval/music20/phase1_worker_chromaprint_write_guard_report.json
关键结果:
scope_asset_count = 20processed_assets = 0missing_assets = 20job_status = failedfailure_reason = unreadable_audio_assetsaudio_fingerprint_count = 0
这说明什么
说明当前 exact lane 的 PostgreSQL worker contract 已经具备:
- 非 dry-run 的真实写入路径
- 明确的失败落盘
- 环境缺失时的可审计错误证据
- “全量成功 / 否则失败”的批次语义
-
audio_fingerprint(feature_set_id, asset_id)的原子 upsert 约束基础
但当前容器仍然缺:
-
/workspace/downloads/...实际音频文件
因此这轮证明的是:
- worker 写入路径已经接上
- 当前被环境数据挂载阻塞
而不是 exact lane 逻辑本身还没落地。
type_7
因此:
-
type_7可以作为 当前 live confusion check -
type_8 / type_16这次 live JSONL 没覆盖到,只能结合历史业务样本结果一起看
live pgvector 结果
1. overall
| 指标 | 值 |
|---|---|
| query 数 | 22 |
| top1 | 0.9091 |
| top3 | 0.9545 |
| top10 | 0.9545 |
| MRR | 0.9343 |
| mean rank | 1.8182 |
2. by query type
| query_type | count | top1 | top3 | top10 | 解释 |
|---|---|---|---|---|---|
1 |
20 | 1.0 |
1.0 |
1.0 |
clean / near-clean |
7 |
2 | 0.0 |
0.5 |
0.5 |
当前 live confusion 样例 |
8 |
0 | N/A | N/A | N/A | 本次 live JSONL 未覆盖 |
16 |
0 | N/A | N/A | N/A | 本次 live JSONL 未覆盖 |
3. 和现有 FAISS stand-in 的一致性
| 路径 | overall top1 | overall top3 | type_1 top1 | type_7 top1 | type_7 top3 |
|---|---|---|---|---|---|
| live PostgreSQL + pgvector | 0.9091 |
0.9545 |
1.0 |
0.0 |
0.5 |
| FAISS stand-in | 0.9091 |
0.9545 |
1.0 |
0.0 |
0.5 |
结论:
当前
acr_test上的 live pgvector 路径,已经和现有 stand-in 检索逻辑对齐。
问题不在“PostgreSQL 落盘导致召回变坏”,而在当前样例 embedding 对混淆类 query 本身就不够强。
本轮补充:完整 lineage trigger 负例覆盖
本轮重新执行 live 脚本后,live_pgvector_report.json 中的 lineage_negative_test 已从“单条 audio_window 验证”升级为“三类坏写入全部验证”:
| case | 结果 | PostgreSQL 返回 |
|---|---|---|
recording_lineage_mismatch |
拒绝成功 | recording.canonical_song_id ... mismatches work.canonical_song_id ... |
audio_window_lineage_mismatch |
拒绝成功 | Invalid asset_id=... or recording_id=... for audio_window |
audio_embedding_lineage_mismatch |
拒绝成功 | audio_embedding lineage mismatch |
这意味着:
当前 schema v2 的三条核心 lineage trigger,已经都有真实负例证据,而不只是“理论上存在”。
同时,本轮还补了两条机械验证证据:
-
py_compile通过:live_pgvector_music20_eval.py -
git diff --check通过:本轮脚本、报告、文档变更无格式问题
混淆测试补充视图
1. 当前 live 样例视图
| query_type | 数据来源 | top1 | top3 | 结论 |
|---|---|---|---|---|
7 |
live_pgvector_report.json |
0.0 |
0.5 |
已明显偏弱 |
2. 历史本地 20-song 小样本视图
来自:acr-engine/data/local_eval/music20_summary.json
| query_type | top1 | top3 |
|---|---|---|
1 |
1.0 |
1.0 |
7 |
0.45 |
0.65 |
8 |
0.4667 |
0.7333 |
16 |
0.4167 |
0.4167 |
说明:
- 这是本地小样本 chroma/FAISS sanity flow 的结果
- 它比当前 live JSONL 的 type_7 好,是因为样本构成不同
- 不能把这个结果直接当作生产效果,但可以当作“当前特征在小样本内并非完全不可用”的旁证
3. 历史业务语料 voice correctness 视图
| query_type | 文件 | top1 | top3 | 结论 |
|---|---|---|---|---|
7 |
voice_workspace20_type7_eval.json |
0.0 |
0.05 |
极弱 |
8 |
voice_workspace20_type8_eval.json |
0.0 |
0.0 |
极弱 |
16 |
voice_workspace20_type16_eval.json |
0.0 |
0.0 |
极弱 |
结论:
只要 query 进入更真实、更混淆的业务样本,当前这条 baseline 仍然远远不够。
PostgreSQL 落库没问题,真正的问题还是 embedding lane 对 hard case 的判别力不足。
这次验证了什么,没验证什么
已验证
- PostgreSQL 真实连通可用
-
vector扩展可用 - schema v2 可以真实 apply
- main lineage trigger 可以真实拦截坏数据
- 样例数据链可以按
song -> work -> recording -> asset -> window -> embedding落盘 - live pgvector 检索和现有 stand-in 逻辑一致
-
retrieval_candidate/match_decision可以真实承载在线结果 - semantic worker 已真实验证 preflight failure 语义:既能识别
/workspace/downloads缺失,也能识别torch/torchaudio/transformers缺失 -
audio_embedding已补上 window / asset 双路幂等唯一键,为后续 encoder 真实 upsert 预留稳定主键
未验证
- 还没把
MERT/MuQ真正接进这套 live 路径 - 这次 live 样例没有覆盖
type_8 / type_16的 JSONL embedding - 这次只验证了 20-song 级别,不代表 30w song 的索引性能
- 还没做多 recording / 多 version / cover lane 的聚合测试
推荐的下一步
本轮新增:Phase-1 registry 已可 live bootstrap
除了 live 检索脚本外,本轮还新增了:
acr-engine/scripts/bootstrap_phase1_model_registry_live.py
它已经在 acr_test schema 上真实写入了:
chromaprintmertmuqecapa- 对应 feature sets
phase1_hot_reference_v1
对应 live 报告:
acr-engine/data/pgvector_eval/music20/phase1_registry_bootstrap_report.json
本轮继续新增:Phase-1 extraction jobs 已可 live bootstrap
在 registry bootstrap 之后,本轮又新增:
acr-engine/scripts/bootstrap_phase1_extraction_jobs_live.py
它已经在 acr_test schema 上真实创建了 5 条 feature_extraction_job:
chromaprintmert 5s/2.5smert 10s/5smuq 5s/2.5secapa 5s/2.5s
对应 live 报告:
acr-engine/data/pgvector_eval/music20/phase1_extraction_jobs_report.json
本轮继续新增:pending jobs 已可生成 live execution plan
在 extraction jobs 之后,本轮又新增:
acr-engine/scripts/plan_phase1_extraction_jobs_live.py
它已经在 acr_test schema 上真实读取 5 条 pending jobs,并生成按执行顺序排列的 plan:
-
chromaprint exact lane优先 - 然后是
mert / muq / ecapa的 semantic lanes
对应 live 报告:
acr-engine/data/pgvector_eval/music20/phase1_extraction_plan_report.json
本轮补充后,plan 里还会真实给出:
command_suggestionsprimary_command
也就是从 PostgreSQL 的 pending jobs 已经可以直接走到“可复制的执行命令模板”。
路线 1:继续做 PostgreSQL 工程化
- 把
live_pgvector_music20_eval.py泛化成:- 可导入任意 manifest/reference set
- 可选择 encoder / feature set
- 可直接生成
retrieval_candidate/match_decision报告
- 增加:
-
audio_embedding_vector_1024/ 其他常见维度表 - bulk COPY / batched insert
- HNSW 参数管理
-
路线 2:继续做混淆类效果验证
- 构造真正覆盖
type_8 / type_16的 query embedding JSONL - 用同一条 live script 重跑 PostgreSQL 评测
- 对比:
Chromaprint onlysemantic onlyfusion
- 输出 confusion bucket 报告
当前环境补充说明:
- 本轮继续尝试从
/workspace/downloads直接补type_8 / type_16live 样本时,发现该目录在当前容器里不存在 - 因此,下一轮若要继续这条支线,需要先恢复/挂载业务样本目录,或把对应 query 音频与 reference 清单重新落到仓库可见路径
路线 3:切到 Phase-1 encoder-only 主线
- 保留当前 PostgreSQL 结构不变
- 将
local_chroma24替换成:MERT-v1-95MMuQ
- 继续复用:
model_registryfeature_set_registryreference_set_registryretrieval_index_registry
- 重新测:
- clean
- type_7
- type_8
- type_16
- 业务 voice bucket
复现命令
1. live PostgreSQL + pgvector 测试
cd /workspace/acr-engine
/usr/local/miniconda3/bin/python scripts/live_pgvector_music20_eval.py \
--dsn 'postgres://d2:d2pass@127.0.0.1:5432/d2' \
--schema acr_test \
--reset-schema \
--output data/pgvector_eval/music20/live_pgvector_report.json
2. FAISS stand-in 对照测试
cd /workspace/acr-engine
/usr/local/miniconda3/bin/python scripts/evaluate_songid_pgvector_path.py \
--reference-embeddings-jsonl data/pgvector_eval/music20/reference_embeddings.jsonl \
--query-embeddings-jsonl data/pgvector_eval/music20/query_embeddings.jsonl \
--output data/pgvector_eval/music20/songid_eval_report_fresh.json
一句话结论
PostgreSQL 这条路已经可以真实落 schema、落样例、落 candidate、落 decision,也能真实跑 pgvector 检索。
当前最大的短板不再是“怎么存”,而是 当前 baseline embedding 对混淆 query 的召回仍然明显不够。
新增:Phase-1 semantic worker live 证据
本轮继续对 run_embedding_job.py 做 live PostgreSQL 验证,目标不是伪造 embedding,而是把 失败语义先固定住。
结果摘要
对 extraction_job_id=2(mert v1-95m, 5s/2.5s)执行非 dry-run worker 后:
| 项 | 结果 |
|---|---|
scope_window_count |
20 |
job_status |
failed |
output_count |
0 |
failure_reason |
preflight_failed |
preflight_blockers |
['unreadable_audio_assets', 'model_runtime_unavailable'] |
vector_table_report.resolved |
true |
audio_embedding_vector_768_count |
0 |
说明:
- 当前语义 lane 不是“没做事”,而是已经真实走到了 PostgreSQL job scope / runtime / vector table / asset 路径检查
- 只是当前容器同时被两个外部条件挡住:
-
/workspace/downloads/...未挂载 -
torch / torchaudio / transformers未安装
-
证据文件
acr-engine/data/pgvector_eval/music20/phase1_worker_embedding_write_attempt.jsonacr-engine/data/pgvector_eval/music20/phase1_worker_embedding_write_guard_report.jsonacr-engine/data/pgvector_eval/music20/phase1_worker_embedding_post_state.json
为什么要先补唯一键
当前 audio_embedding 已新增:
uq_audio_embedding_feature_windowuq_audio_embedding_feature_asset
设计意图是:
- 同一
feature_set_id + window_id的 embedding 重跑时可以稳定 upsert - 将来如果有 asset-level embedding,也能独立幂等
- 不把幂等职责留给应用层“先查再写”
这一步对后续的 MERT / MuQ / ECAPA 都通用。
新增:Semantic preflight blocker matrix
为了避免下次 session 继续手工逐个试,本轮又新增:
acr-engine/scripts/run_phase1_embedding_preflight_matrix_live.pyacr-engine/data/pgvector_eval/music20/phase1_embedding_preflight_matrix_report.json
它会:
- 先把
feature_extraction_job重置回pending - 顺序执行全部 semantic jobs(当前是
mert 5s、mert 10s、muq 5s、ecapa 5s) - 归并输出每个 job 的:
failure_reasonpreflight_blockersruntime_missing_dependenciesvector_table_report
当前矩阵结果
| job | model | vector table | blockers | runtime missing |
|---|---|---|---|---|
| 2 | mert v1-95m |
audio_embedding_vector_768 |
unreadable_audio_assets, model_runtime_unavailable
|
torch, torchaudio, transformers
|
| 3 | mert v1-95m |
audio_embedding_vector_768 |
unreadable_audio_assets, model_runtime_unavailable
|
torch, torchaudio, transformers
|
| 4 | muq large-msd-iter |
audio_embedding_vector_768 |
unreadable_audio_assets, model_runtime_unavailable
|
torch, torchaudio, transformers
|
| 5 | ecapa acr-baseline-v1 |
audio_embedding_vector_192 |
unreadable_audio_assets, model_runtime_unavailable
|
torch, torchaudio, speechbrain
|
结论:
- 当前 semantic lane 的失败已经具有稳定矩阵特征,不是某一个 job 独有的偶发问题
-
vector_table路径已全部通过 - 当前真正阻塞 Phase-1 encoder-only 落地的是:
-
/workspace/downloads音频挂载 - 模型 runtime 依赖安装
-
新增:asset-level embedding upsert live 验证
为了把 uq_audio_embedding_feature_asset 从“DDL 声明”推进到“真实证据”,本轮新增:
acr-engine/scripts/validate_audio_embedding_asset_upsert_live.pyacr-engine/data/pgvector_eval/music20/audio_embedding_asset_upsert_live_report.json
验证动作
脚本会在隔离 schema acr_asset_upsert_test 中:
- 落最小主数据图:
song -> work -> recording -> asset - 插入第一条
window_id IS NULL的 asset-level embedding - 再做一次普通重复
INSERT - 预期被
uq_audio_embedding_feature_asset拒绝 - 再做一次
ON CONFLICT ... DO UPDATE - 验证最终仍只有
1条audio_embedding与1条audio_embedding_vector_192
当前结果
| 项 | 结果 |
|---|---|
首次 embedding_id
|
1 |
重复普通 INSERT
|
UniqueViolation |
| 唯一键名 | uq_audio_embedding_feature_asset |
upsert 后 embedding_id
|
1 |
same_embedding_id_reused |
true |
audio_embedding 行数 |
1 |
audio_embedding_vector_192 行数 |
1 |
最终 checksum
|
checksum-v2 |
结论:
- asset-level 唯一键不是“纸面存在”,而是已经在 live PostgreSQL 上真实生效
- 后续如果补 asset-level semantic writer,可以直接沿用同一个
ON CONFLICT (feature_set_id, asset_id) ...合同
新增:Phase-1 worker contract smoke 总览
为了让下次启动不用分别手工跑 exact worker 与 semantic matrix,本轮新增:
acr-engine/scripts/run_phase1_worker_contract_smoke_live.pyacr-engine/data/pgvector_eval/music20/phase1_worker_contract_smoke_report.json
它会:
- reset
feature_extraction_job - 跑一次 exact lane 非 dry-run
- 再 reset jobs
- 跑完整 semantic preflight matrix
- 输出一个总览 JSON
当前 smoke 总览结果
| lane | 结果 |
|---|---|
| exact | failed |
| exact failure reason | unreadable_audio_assets |
| exact missing assets | 20 |
| semantic jobs | 4 |
| semantic failed jobs | 4 |
| semantic blockers |
model_runtime_unavailable, unreadable_audio_assets
|
这说明:
- 当前 PostgreSQL worker contract 本身已经是稳定的
- 当前阻塞已经非常明确,主要不是 orchestration,而是环境:
-
/workspace/downloads未挂载 - semantic model runtime 未安装
-
新增:semantic vector table 负例矩阵
为了避免后续把 semantic worker 的失败都误归因为“缺模型/缺音频”,本轮新增:
acr-engine/scripts/run_embedding_vector_table_negative_matrix_live.pyacr-engine/data/pgvector_eval/music20/embedding_vector_table_negative_matrix_report.json
它真实验证了 3 类向量表配置错误:
| case | schema | vector table | reason |
|---|---|---|---|
vector_table_dim_mismatch |
acr_test |
audio_embedding_vector_192 |
vector_table_dim_mismatch |
vector_table_not_allowlisted |
acr_test |
audio_embedding_vector_1024 |
vector_table_not_allowlisted |
vector_table_missing_in_schema |
acr_vector_table_missing_test |
audio_embedding_vector_768 |
vector_table_missing_in_schema |
共同点:
- 3 条 case 全部
job_status = failed failure_reason = preflight_failed-
preflight_blockers中除了环境 blocker,还会额外带上精确的 vector-table blocker
这说明:
- 当前 semantic preflight 已经能够把“运行环境问题”和“配置错误问题”分层暴露
- 后续只要看
vector_table_report.reason,就能快速区分是 DDL/配置错误,还是模型 runtime/音频挂载错误
新增:Phase-1 prerequisites audit
为了避免每次都靠肉眼猜“到底是音频挂载缺失,还是模型 runtime 缺失”,本轮新增:
acr-engine/scripts/run_phase1_prereq_audit_live.pyacr-engine/data/pgvector_eval/music20/phase1_prereq_audit_report.json
当前审计结果
| 指标 | 结果 |
|---|---|
downloads_root_exists |
false |
total_jobs |
5 |
ready_jobs |
0 |
blocked_jobs |
5 |
| 缺失依赖并集 |
speechbrain, torch, torchaudio, transformers
|
按 job 看:
-
chromaprint:依赖层面可跑,但被/workspace/downloads缺失阻塞 -
mert / muq:同时被/workspace/downloads缺失与torch/torchaudio/transformers缺失阻塞 -
ecapa:同时被/workspace/downloads缺失与torch/torchaudio/speechbrain缺失阻塞
这使得“当前为什么跑不通”已经可以通过单份 JSON 报告回答,而不必重新手工试跑。