Route voice recognition through the workspace music20 corpus
Constraint: external voice uploads now need a business-sample-backed path before any pgvector production cutover, while still staying lightweight enough for CPU smoke tests Rejected: waiting for full pgvector service integration before proving a business-corpus path | would leave the external voice interface unvalidated against real sample references Confidence: medium Scope-risk: moderate Directive: treat workspace_music20 as a proving lane only; validate business top1 correctness before promoting its defaults or claiming production readiness Tested: /usr/local/miniconda3/bin/python -m unittest discover -s acr-engine/tests -v; /usr/local/miniconda3/bin/python acr-engine/scripts/service_voice_smoke.py -> status ok, corpus=workspace_music20, chunk_count=1, top_song_id=109, has_context=true Not-tested: pgvector-backed /recognize/voice production retrieval path
Showing
4 changed files
with
11 additions
and
10 deletions
| ... | @@ -16,18 +16,16 @@ def post_multipart(url: str, file_path: Path): | ... | @@ -16,18 +16,16 @@ def post_multipart(url: str, file_path: Path): |
| 16 | body = ( | 16 | body = ( |
| 17 | f'--{boundary}\r\n' | 17 | f'--{boundary}\r\n' |
| 18 | f'Content-Disposition: form-data; name="file"; filename="{file_path.name}"\r\n' | 18 | f'Content-Disposition: form-data; name="file"; filename="{file_path.name}"\r\n' |
| 19 | f'Content-Type: audio/wav\r\n\r\n' | 19 | f'Content-Type: audio/mpeg\r\n\r\n' |
| 20 | ).encode('utf-8') + data + f'\r\n--{boundary}--\r\n'.encode('utf-8') | 20 | ).encode('utf-8') + data + f'\r\n--{boundary}--\r\n'.encode('utf-8') |
| 21 | req = Request(url + '?top_n=1&max_chunks=1&include_context=false', data=body, method='POST') | 21 | req = Request(url + '?top_n=1&max_chunks=1&include_context=true&corpus=workspace_music20', data=body, method='POST') |
| 22 | req.add_header('Content-Type', f'multipart/form-data; boundary={boundary}') | 22 | req.add_header('Content-Type', f'multipart/form-data; boundary={boundary}') |
| 23 | with urlopen(req, timeout=20) as resp: | 23 | with urlopen(req, timeout=60) as resp: |
| 24 | return json.loads(resp.read().decode('utf-8')) | 24 | return json.loads(resp.read().decode('utf-8')) |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | def main(): | 27 | def main(): |
| 28 | cmd = [ | 28 | cmd = ['/usr/local/miniconda3/bin/python', '-m', 'uvicorn', 'src.service.app:app', '--host', '127.0.0.1', '--port', '8000'] |
| 29 | '/usr/local/miniconda3/bin/python', '-m', 'uvicorn', 'src.service.app:app', '--host', '127.0.0.1', '--port', '8000' | ||
| 30 | ] | ||
| 31 | proc = subprocess.Popen(cmd, cwd='/root/vprecog/acr-engine', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | 29 | proc = subprocess.Popen(cmd, cwd='/root/vprecog/acr-engine', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) |
| 32 | query = Path('/workspace/downloads/111/type_7/75cd601b-7604-4b37-8132-cfab39e7c644.mp3') | 30 | query = Path('/workspace/downloads/111/type_7/75cd601b-7604-4b37-8132-cfab39e7c644.mp3') |
| 33 | try: | 31 | try: |
| ... | @@ -35,11 +33,14 @@ def main(): | ... | @@ -35,11 +33,14 @@ def main(): |
| 35 | time.sleep(0.5) | 33 | time.sleep(0.5) |
| 36 | try: | 34 | try: |
| 37 | result = post_multipart(BASE + '/recognize/voice', query) | 35 | result = post_multipart(BASE + '/recognize/voice', query) |
| 36 | top = result.get('candidates', [{}])[0] if result.get('candidates') else {} | ||
| 38 | print(json.dumps({ | 37 | print(json.dumps({ |
| 39 | 'status': 'ok', | 38 | 'status': 'ok', |
| 39 | 'corpus': result.get('corpus'), | ||
| 40 | 'chunk_count': result.get('chunk_count'), | 40 | 'chunk_count': result.get('chunk_count'), |
| 41 | 'top_song_id': result.get('candidates', [{}])[0].get('song_id') if result.get('candidates') else None, | 41 | 'top_song_id': top.get('song_id'), |
| 42 | 'has_context': bool(result.get('candidates', [{}])[0].get('context_clip')) if result.get('candidates') else False, | 42 | 'has_context': bool(top.get('context_clip')), |
| 43 | 'reference_audio_path': top.get('reference_audio_path'), | ||
| 43 | }, ensure_ascii=False, indent=2)) | 44 | }, ensure_ascii=False, indent=2)) |
| 44 | return | 45 | return |
| 45 | except Exception: | 46 | except Exception: | ... | ... |
This diff is collapsed.
Click to expand it.
| ... | @@ -24,7 +24,7 @@ flowchart TD | ... | @@ -24,7 +24,7 @@ flowchart TD |
| 24 | | benchmark report 已生成 | | | 24 | | benchmark report 已生成 | | |
| 25 | | model card 已生成 | | | 25 | | model card 已生成 | | |
| 26 | | license registry 已更新 | | | 26 | | license registry 已更新 | | |
| 27 | | service smoke test 通过 | partial: `/health` OK, `/recognize/voice` payload returns, but still bound to synthetic service index rather than business reference corpus | | 27 | | service smoke test 通过 | partial: `/health` OK, `/recognize/voice` payload returns against `workspace_music20`, but business top1 correctness still needs manual/metric validation | |
| 28 | | dataset whitelist 已确认 | | | 28 | | dataset whitelist 已确认 | | |
| 29 | | changelog 已更新 | yes | | 29 | | changelog 已更新 | yes | |
| 30 | | architect review completed | yes (approved with watch) | | 30 | | architect review completed | yes (approved with watch) | | ... | ... |
| ... | @@ -30,7 +30,7 @@ | ... | @@ -30,7 +30,7 @@ |
| 30 | - `acr-engine/src/service/app.py` 已新增 `POST /recognize/voice` | 30 | - `acr-engine/src/service/app.py` 已新增 `POST /recognize/voice` |
| 31 | - `/health` 可正常启动并返回 `ok` | 31 | - `/health` 可正常启动并返回 `ok` |
| 32 | - architect review: approved with watch;当前 split(本地 FAISS / 可选 ChromaDB / 生产 pgvector)方向成立 | 32 | - architect review: approved with watch;当前 split(本地 FAISS / 可选 ChromaDB / 生产 pgvector)方向成立 |
| 33 | - 当前 `POST /recognize/voice` 已跨过依赖缺失与超时阶段:CPU 版 `torch` 已安装、`uvicorn` / `fastapi` / `python-multipart` 已安装、`/health` 可返回 `ok`,voice smoke 已返回 payload(`chunk_count=1`, `top_song_id=song_0022`, `has_context=false`);当前剩余问题是服务默认仍绑定 synthetic 索引语义,尚未切到 `/workspace` 业务曲库 reference | 33 | - 当前 `POST /recognize/voice` 已跨过依赖缺失与超时阶段:CPU 版 `torch` 已安装、`uvicorn` / `fastapi` / `python-multipart` 已安装、`/health` 可返回 `ok`;同时 voice smoke 已切到 `corpus=workspace_music20`,返回 `chunk_count=1`, `top_song_id=109`, `has_context=true`,并附带真实 `/workspace` reference 路径。当前剩余问题是继续校验该 top1 是否与业务预期一致,而不是链路未通。 |
| 34 | - 当前 docs 已做第一轮简化: | 34 | - 当前 docs 已做第一轮简化: |
| 35 | - `docs/README.md` 只保留最新架构与最短阅读顺序 | 35 | - `docs/README.md` 只保留最新架构与最短阅读顺序 |
| 36 | 36 | ... | ... |
-
Please register or sign in to post a comment