fix: normalize faster-whisper segments to dicts + in-proc auto-worker

Colab run 3 (A100) surfaced three GPU/API-path bugs mocks couldn't catch:

1. faster-whisper yields namedtuple Segments, but batch/bench consume
   them as dicts (.get) -> AttributeError 'Segment' has no attribute
   'get' on every real transcription. Engine now normalizes segments
   to dicts (_to_dict_segments) at the boundary.

2. API TranscribeOptions carries engine-irrelevant keys (formats,
   timestamps, glossary_id, post_correction, diarize); worker's
   TranscriptionOptions(**job.options) crashed with TypeError. Worker
   now filters job.options to TranscriptionOptions.__slots__.

3. in-proc server never consumed its own queue (jobs stayed queued
   forever). Added opt-in Settings.auto_worker (default off): lifespan
   starts a daemon Worker thread for inproc backend, stopped on
   shutdown. Notebook enables it via LUKESCRIBE_AUTO_WORKER=true so the
   API upload -> completed flow works end to end.

Notebook: bench manifest now uses clips schema (audio_path/duration_sec/
entities); cell 22 reads error_message/error_code; upload poll window
raised to 4min (first-run model download).

+ 5 tests (namedtuple/dict segments, API-style options, auto_worker
on/off); 136 tests pass, ruff clean.
This commit is contained in:
2026-08-12 17:32:18 +09:00
parent 741bce9fc6
commit 20777386fe
9 changed files with 218 additions and 16 deletions
+28
View File
@@ -44,6 +44,34 @@ class TestHealth:
assert body["model_ready"] is False # 모델 캐시 없음 → 프로비저닝 보류
class TestAutoWorker:
def test_auto_worker_off_by_default(self, client: TestClient):
"""기본(False)에서는 워커 스레드를 띄우지 않는다 (테스트/프로덕션 안전)."""
assert client.app.state.inproc_worker is None
def test_auto_worker_started_when_enabled(self, tmp_path):
"""auto_worker=true + inproc → lifespan이 워커 스레드를 시작하고 종료 시 정지."""
from luke_scribe.api.app import create_app
from luke_scribe.config import Settings
settings = Settings(
_env_file=None,
results_dir=str(tmp_path / "results"),
api_key_file=str(tmp_path / "api_keys.json"),
queue_backend="inproc",
model_cache_dir=None,
tunnel="none",
auto_worker=True,
)
app = create_app(settings)
with TestClient(app) as c:
w = c.app.state.inproc_worker
assert w is not None
assert not w._stop.is_set()
# lifespan 종료 → 워커 정지 요청
assert w._stop.is_set()
class TestAuth:
def test_missing_key_rejected(self, client: TestClient):
r = client.get("/v1/jobs")