Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ SIGNED_URL_EXPIRY_MINUTES=30
RUNPOD_API_KEY=your-runpod-api-key
RUNPOD_ENDPOINT_ID=your-runpod-endpoint-id

# Speech-to-text: Sunbird faster-whisper ASR, 51 African languages
# (Sunbird/faster-whisper-51-african-languages), served behind an
# OpenAI-compatible API. Required by POST /tasks/audio/transcriptions.
# Must include the trailing /v1 — the service appends /audio/transcriptions.
# Authenticates with RUNPOD_API_KEY above.
ASR_BASE_URL=https://your-endpoint-id.api.runpod.ai/v1
# ASR_MODEL_NAME=sunbird-asr-51
# ASR_TIMEOUT_SECONDS=600

# Sunflower chat/inference endpoints (RunPod, OpenAI-compatible).
# The /tasks/chat/completions endpoint serves two models:
# - sunflower-14b (default) -> SUNFLOWER_14B_ENDPOINT_ID
Expand Down
28 changes: 28 additions & 0 deletions app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,34 @@ class Settings(BaseSettings):
default=10000, description="Maximum allowed text length for TTS"
)

# Sunbird ASR (faster-whisper, 51 African languages) Configuration
runpod_api_key: Optional[str] = Field(
default=None,
alias="RUNPOD_API_KEY",
description="RunPod API key, used as the bearer token for the ASR deployment",
)
asr_base_url: str = Field(
default="https://<ENDPOINT_ID>.api.runpod.ai/v1",
alias="ASR_BASE_URL",
description=(
"Base URL of the OpenAI-compatible faster-whisper ASR deployment "
"serving Sunbird/faster-whisper-51-african-languages"
),
)
asr_model_name: str = Field(
default="sunbird-asr-51",
alias="ASR_MODEL_NAME",
description="Model name sent to the ASR deployment",
)
asr_timeout_seconds: int = Field(
default=600,
alias="ASR_TIMEOUT_SECONDS",
description=(
"Timeout for ASR requests in seconds. Generous by default: a cold "
"start plus first-time model download can take several minutes."
),
)

# GCP Storage Configuration
gcp_bucket_name: str = Field(
default="your-tts-audio-bucket",
Expand Down
13 changes: 4 additions & 9 deletions app/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ async def endpoint(
from app.schemas.users import TokenData, User

# Service imports
from app.services.asr_service import ASRService, get_asr_service
from app.services.billing_analytics.service import (
BillingAnalyticsService,
get_billing_analytics_service,
Expand All @@ -65,10 +66,6 @@ async def endpoint(
from app.services.storage_service import StorageService
from app.services.storage_service import get_storage_service as get_new_storage_service
from app.services.stt_service import STTService, get_stt_service
from app.services.transcription_service import (
TranscriptionService,
get_transcription_service,
)
from app.services.translation_service import TranslationService, get_translation_service
from app.services.tts_service import TTSService, get_tts_service
from app.services.whatsapp_service import WhatsAppBusinessService, get_whatsapp_service
Expand All @@ -85,9 +82,7 @@ async def endpoint(
# Service dependencies
STTServiceDep = Annotated[STTService, Depends(get_stt_service)]
ModalSTTServiceDep = Annotated[ModalSTTService, Depends(get_modal_stt_service)]
TranscriptionServiceDep = Annotated[
TranscriptionService, Depends(get_transcription_service)
]
ASRServiceDep = Annotated[ASRService, Depends(get_asr_service)]
TTSServiceDep = Annotated[TTSService, Depends(get_tts_service)]
OrpheusTTSServiceDep = Annotated[OrpheusTTSService, Depends(get_orpheus_tts_service)]
TranslationServiceDep = Annotated[TranslationService, Depends(get_translation_service)]
Expand Down Expand Up @@ -234,7 +229,7 @@ async def get_current_admin(
# Service dependencies
"STTServiceDep",
"ModalSTTServiceDep",
"TranscriptionServiceDep",
"ASRServiceDep",
"TTSServiceDep",
"OrpheusTTSServiceDep",
"TranslationServiceDep",
Expand All @@ -260,7 +255,7 @@ async def get_current_admin(
# Service classes (for type hints)
"STTService",
"ModalSTTService",
"TranscriptionService",
"ASRService",
"TTSService",
"OrpheusTTSService",
"TranslationService",
Expand Down
35 changes: 27 additions & 8 deletions app/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,32 @@
(supports Acholi, Ateso, English, Luganda, Lugbara, Runyankole)

### Speech-to-Text (STT)
- **`POST /tasks/audio/transcriptions`** - Unified STT endpoint (OpenAI-style).
- Accepts an uploaded audio file (`audio`) or a GCS object (`gcs_blob_name`).
- `platform`: `modal` (default, Whisper large-v3) or `runpod`.
- RunPod options: `adapter` (language adapter), `whisper`, `recognise_speakers`
(diarization), and the `org` organization workflow.
- `language`: 3-letter code (e.g. `eng`, `lug`) or full name; improves accuracy.
Supports WAV, MP3, OGG, M4A, and more. Auto-detects when omitted.
- **`POST /tasks/audio/transcriptions`** - STT endpoint, powered by
Sunbird's faster-whisper ASR model covering **51 African languages**
(`Sunbird/faster-whisper-51-african-languages`, a Whisper large-v3 fine-tune).
- `audio`: the audio file to transcribe (**required**). Supports WAV, MP3,
OGG, M4A, and more.
- `language`: ISO 639-3 code (**required**). The model reuses Whisper's
language-token slots for African languages, so automatic detection is
unreliable — always pass a language explicitly.
- `timestamps`: set `true` to also receive per-segment start/end times in the
`segments` field. Defaults to `false`.
- **51 supported languages**: Acholi (`ach`), Afrikaans (`afr`), Akan (`aka`),
Amharic (`amh`), Ateso (`teo`), Bambara (`bam`), Bemba (`bem`),
Berber (`ber`), Chichewa (`nya`), Dagaare (`dga`), Dagbani (`dag`),
English (`eng`), Ewe (`ewe`), French (`fra`), Fulani (`ful`), Hausa (`hau`),
Igbo (`ibo`), Ikposo (`kpo`), Kabyle (`kab`), Kalenjin (`kln`),
Kanuri (`kau`), Kikuyu (`kik`), Kinyarwanda (`kin`), Kwamba (`rwm`),
Lendu (`led`), Lingala (`lin`), Lugbara (`lgg`), Luganda (`lug`),
Luhya (`luy`), Lumasaba (`myx`), Luo (`luo`), Lusoga (`xog`),
Malagasy (`mlg`), Ndebele (`nbl`), Nigerian Pidgin (`pcm`), Oromo (`orm`),
Rukiga (`cgg`), Rukonjo (`koo`), Runyankole (`nyn`), Ruruuli (`ruc`),
Rutooro (`ttj`), Shona (`sna`), Somali (`som`), Sotho (`sot`),
Swahili (`swa`), Thur (`lth`), Tswana (`tsn`), Wolof (`wol`),
Xhosa (`xho`), Yoruba (`yor`), Zulu (`zul`).
- **Removed parameters** (previously accepted, now rejected): `platform`,
`adapter`, `whisper`, `recognise_speakers`, `org`, `gcs_blob_name`. Speaker
diarization and the organization workflow remain on the legacy routes below.
- **Deprecated** → use `POST /tasks/audio/transcriptions`:
- `POST /tasks/stt`, `POST /tasks/stt_from_gcs`, `POST /tasks/org/stt`,
`POST /tasks/modal/stt`
Expand Down Expand Up @@ -116,7 +135,7 @@
},
{
"name": "Speech-to-Text",
"description": "Convert speech audio to text. The unified /tasks/audio/transcriptions endpoint accepts an uploaded file or a GCS object, routes to the Modal or RunPod backend, and supports optional speaker diarization for Acholi, Ateso, English, Luganda, Lugbara, and Runyankole.", # noqa: E501
"description": "Convert speech audio to text. The unified /tasks/audio/transcriptions endpoint is powered by Sunbird's faster-whisper ASR model covering 51 African languages. It takes an uploaded audio file plus a required ISO 639-3 language code, and optionally returns per-segment timestamps (timestamps=true). Speaker diarization and the organization workflow remain on the deprecated /tasks/stt* routes.", # noqa: E501
},
{
"name": "Text-to-Speech",
Expand Down
Loading
Loading