# Parakeet ASR via sherpa-onnx + our own thin FastAPI wrapper. # # We previously wrapped Shadowfita/parakeet-tdt-0.6b-v2-fastapi but hit two # unfixed upstream bugs (open issues #16 + #10) the first time we actually sent # a transcription request. Switched to sherpa-onnx — ONNX Runtime + CUDA, a # prebuilt int8 quantized Parakeet-TDT from k2-fsa — and wrote our own ~50-line # wrapper we own end-to-end. # # HOST: fv-ml1, GPU 0 (relocated from irv-ml1 2026-09-15). # # ⚠ GPU 0, NOT the empty GPU 3. This seat holds ~800 MiB — under 1% of a 96 GB # card — so it rides on the card with the most uncommitted headroom rather than # putting the first fingerprint on a pristine one. GPU 0's seats commit # util 0.40 + 0.48 = 0.88, leaving ~13 GB; GPU 1 is at 0.975 and GPU 2 at 0.96, # both too tight. Keeping GPU 3 at 2 MiB means it can still take a full-card seat # (flash-next needs 93 GiB) without a neighbour eating its profiling margin — # vLLM sizes KV cache as a fraction of TOTAL VRAM, not free VRAM, so a resident # tenant on an otherwise-empty card is worth more than its megabytes suggest. # # ⚠ The pin is `deploy.resources.reservations.devices[].device_ids`, the fleet # convention — NOT `runtime: nvidia` + NVIDIA_VISIBLE_DEVICES, and NOT # `count: all` (which is what the dead on-host stub did, and would have let this # tiny ASR seat see all four cards). device_ids presents the pinned card as # cuda:0 INSIDE the container, which is what sherpa-onnx's # CUDAExecutionProvider takes by default. # # Model weights (~460 MB int8) download on first run via the entrypoint to # ${PARAKEET_MODELS_DIR}/ (persistent host bind mount). Subsequent starts skip # the download. # # API: # POST /transcribe — multipart file upload, returns {"text": "..."} # POST /v1/audio/transcriptions — same body, OpenAI-compatible path alias # GET /healthz # # All tunables live in .env — edit that, not this file. services: parakeet: image: local/parakeet:${PARAKEET_TAG} build: context: . dockerfile: Dockerfile container_name: parakeet restart: unless-stopped ports: - "${PARAKEET_BIND:-0.0.0.0}:${PARAKEET_PORT}:8000" environment: - MODEL_DIR=/models - MODEL_URL=${PARAKEET_MODEL_URL} - PROVIDER=${PARAKEET_PROVIDER:-cuda} - NUM_THREADS=${PARAKEET_NUM_THREADS:-1} - LOG_LEVEL=${PARAKEET_LOG_LEVEL:-INFO} volumes: - ${PARAKEET_MODELS_DIR}:/models deploy: resources: reservations: devices: - driver: nvidia device_ids: ["${PARAKEET_GPU:-0}"] capabilities: [gpu] networks: - tnet healthcheck: # Image ships wget (apt) but not curl — use wget so the check actually runs. test: ["CMD-SHELL", "wget -q -O /dev/null http://localhost:8000/healthz || exit 1"] interval: 30s timeout: 10s retries: 3 # First boot may include a ~460 MB model download. start_period: 300s labels: - homepage.group=AI - Audio Tools - homepage.name=Parakeet ASR - homepage.icon=mdi-microphone - homepage.description=Parakeet-TDT speech-to-text via sherpa-onnx (fv-ml1 GPU 0) - homepage.href=http://10.251.50.54:${PARAKEET_PORT} networks: tnet: name: traefik-net external: true