feat(asr): FunASR/SenseVoice support for the Remote API engine (#468)

* feat(asr): add chat audio remote benchmarking

* style(asr): apply black formatting

* test(main): include remote API model kwarg

* test(asr): add coverage for chat-completions error handling and parsing

Add 10 new tests to cover uncovered lines in PR #468:
- ConnectionError handler in _try_chat_completions_audio_api (lines 1601-1602)
- _parse_chat_completion_transcription edge cases: None, list content,
  empty/whitespace strings, JSON without text field, plain text, and
  single-line language metadata (lines 1610, 1613-1621, 1625, 1629-1640)

Coverage for recognition_manager.py improved from 85% to 86%.

* feat(asr): support FunASR remote responses

* refactor(asr): scope remote FunASR support to the #469 path

Drop chat-completions/Qwen client, evaluation notes, and the remote ASR
benchmark harness. Keep model field, tolerant OpenAI response parsing,
SenseVoice label stripping, FunASR docs, and tests.
This commit is contained in:
Jatin K Malik
2026-07-13 15:03:19 -07:00
committed by GitHub
parent 9d9638e854
commit 85927be4b4
11 changed files with 236 additions and 25 deletions
+13 -7
View File
@@ -3,7 +3,8 @@
Vocalinux Remote API Test Server
A simple mock server for testing Vocalinux's remote API feature.
Supports both whisper.cpp (/inference) and OpenAI-compatible (/v1/audio/transcriptions) formats.
Supports whisper.cpp (/inference) and OpenAI/FunASR-compatible
(/v1/audio/transcriptions) formats.
Usage:
python test_remote_server.py [--port PORT] [--delay SECONDS]
@@ -17,8 +18,7 @@ Examples:
import argparse
import json
import time
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import parse_qs
from http.server import BaseHTTPRequestHandler, HTTPServer
class RemoteAPITestHandler(BaseHTTPRequestHandler):
@@ -40,7 +40,7 @@ class RemoteAPITestHandler(BaseHTTPRequestHandler):
"message": "Vocalinux Remote API Test Server",
"endpoints": [
"/inference (whisper.cpp format)",
"/v1/audio/transcriptions (OpenAI format)",
"/v1/audio/transcriptions (OpenAI/FunASR format)",
"/v1/models (OpenAI models list)",
],
}
@@ -58,7 +58,13 @@ class RemoteAPITestHandler(BaseHTTPRequestHandler):
"object": "model",
"created": 1234567890,
"owned_by": "openai",
}
},
{
"id": "sensevoice",
"object": "model",
"created": 1767225600,
"owned_by": "mock",
},
],
"object": "list",
}
@@ -113,7 +119,7 @@ class RemoteAPITestHandler(BaseHTTPRequestHandler):
# whisper.cpp format
response = {"text": transcription}
else:
# OpenAI format
# OpenAI/FunASR-compatible format
response = {"text": transcription}
self.wfile.write(json.dumps(response, indent=2).encode())
@@ -187,7 +193,7 @@ def main():
print(" GET /v1/models - OpenAI models list")
print(" GET /inference - whisper.cpp health check")
print(" POST /inference - whisper.cpp transcription")
print(" POST /v1/audio/transcriptions - OpenAI transcription")
print(" POST /v1/audio/transcriptions - OpenAI/FunASR transcription")
print()
print("Press Ctrl+C to stop")
print("=" * 60)