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
179 changes: 144 additions & 35 deletions docs/my-website/docs/pass_through/assembly_ai.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,194 @@
# Assembly AI
# AssemblyAI

Pass-through endpoints for Assembly AI - call Assembly AI endpoints, in native format (no translation).
Pass-through endpoints for AssemblyAI - call AssemblyAI endpoints, in native format (no translation).

| Feature | Supported | Notes |
| Feature | Supported | Notes |
|-------|-------|-------|
| Cost Tracking | ✅ | works across all integrations |
| Logging | ✅ | works across all integrations |


Supports **ALL** Assembly AI Endpoints
Supports **ALL** AssemblyAI Endpoints

[**See All Assembly AI Endpoints**](https://www.assemblyai.com/docs/api-reference)
[**See All AssemblyAI Endpoints**](https://www.assemblyai.com/docs/api-reference)


<iframe width="840" height="500" src="https://www.loom.com/embed/aac3f4d74592448992254bfa79b9f62d?sid=267cd0ab-d92b-42fa-b97a-9f385ef8930c" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
## Supported Routes

| AssemblyAI Service | LiteLLM Route | AssemblyAI Base URL |
|-------------------|---------------|---------------------|
| Speech-to-Text (US) | `/assemblyai/*` | `api.assemblyai.com` |
| Speech-to-Text (EU) | `/eu.assemblyai/*` | `eu.api.assemblyai.com` |

## Quick Start

Let's call the Assembly AI [`/v2/transcripts` endpoint](https://www.assemblyai.com/docs/api-reference/transcripts)
Let's call the AssemblyAI [`/v2/transcripts` endpoint](https://www.assemblyai.com/docs/api-reference/transcripts)

1. Add Assembly AI API Key to your environment
1. Add AssemblyAI API Key to your environment

```bash
export ASSEMBLYAI_API_KEY=""
```

2. Start LiteLLM Proxy
2. Start LiteLLM Proxy

```bash
litellm

# RUNNING on http://0.0.0.0:4000
```

3. Test it!
3. Test it!

Let's call the Assembly AI `/v2/transcripts` endpoint
Let's call the AssemblyAI [`/v2/transcripts` endpoint](https://www.assemblyai.com/docs/api-reference/transcripts). Includes commented-out [Speech Understanding](https://www.assemblyai.com/docs/speech-understanding) features you can toggle on.

```python
import assemblyai as aai

LITELLM_VIRTUAL_KEY = "sk-1234" # <your-virtual-key>
LITELLM_PROXY_BASE_URL = "http://0.0.0.0:4000/assemblyai" # <your-proxy-base-url>/assemblyai
aai.settings.base_url = "http://0.0.0.0:4000/assemblyai" # <your-proxy-base-url>/assemblyai
aai.settings.api_key = "Bearer sk-1234" # Bearer <your-virtual-key>

aai.settings.api_key = f"Bearer {LITELLM_VIRTUAL_KEY}"
aai.settings.base_url = LITELLM_PROXY_BASE_URL
# Use a publicly-accessible URL
audio_file = "https://assembly.ai/wildfires.mp3"

# URL of the file to transcribe
FILE_URL = "https://assembly.ai/wildfires.mp3"
# Or use a local file:
# audio_file = "./example.mp3"

# You can also transcribe a local file by passing in a file path
# FILE_URL = './path/to/file.mp3'
config = aai.TranscriptionConfig(
speech_models=["universal-3-pro", "universal-2"],
language_detection=True,
speaker_labels=True,
# Speech understanding features
# sentiment_analysis=True,
# entity_detection=True,
# auto_chapters=True,
# summarization=True,
# summary_type=aai.SummarizationType.bullets,
# redact_pii=True,
# content_safety=True,
)

transcriber = aai.Transcriber()
transcript = transcriber.transcribe(FILE_URL)
print(transcript)
print(transcript.id)
```
transcript = aai.Transcriber().transcribe(audio_file, config=config)

## Calling Assembly AI EU endpoints
if transcript.status == aai.TranscriptStatus.error:
raise RuntimeError(f"Transcription failed: {transcript.error}")

If you want to send your request to the Assembly AI EU endpoint, you can do so by setting the `LITELLM_PROXY_BASE_URL` to `<your-proxy-base-url>/eu.assemblyai`
print(f"\nFull Transcript:\n\n{transcript.text}")

# Optionally print speaker diarization results
# for utterance in transcript.utterances:
# print(f"Speaker {utterance.speaker}: {utterance.text}")
```

4. [Prompting with Universal-3 Pro](https://www.assemblyai.com/docs/speech-to-text/prompting) (optional)

```python
import assemblyai as aai

LITELLM_VIRTUAL_KEY = "sk-1234" # <your-virtual-key>
LITELLM_PROXY_BASE_URL = "http://0.0.0.0:4000/eu.assemblyai" # <your-proxy-base-url>/eu.assemblyai
aai.settings.base_url = "http://0.0.0.0:4000/assemblyai" # <your-proxy-base-url>/assemblyai
aai.settings.api_key = "Bearer sk-1234" # Bearer <your-virtual-key>

audio_file = "https://assemblyaiassets.com/audios/verbatim.mp3"

config = aai.TranscriptionConfig(
speech_models=["universal-3-pro", "universal-2"],
language_detection=True,
prompt="Produce a transcript suitable for conversational analysis. Every disfluency is meaningful data. Include: fillers (um, uh, er, ah, hmm, mhm, like, you know, I mean), repetitions (I I, the the), restarts (I was- I went), stutters (th-that, b-but, no-not), and informal speech (gonna, wanna, gotta)",
)

transcript = aai.Transcriber().transcribe(audio_file, config)

print(transcript.text)
```

## Calling AssemblyAI EU endpoints

If you want to send your request to the AssemblyAI EU endpoint, you can do so by setting the `LITELLM_PROXY_BASE_URL` to `<your-proxy-base-url>/eu.assemblyai`

aai.settings.api_key = f"Bearer {LITELLM_VIRTUAL_KEY}"
aai.settings.base_url = LITELLM_PROXY_BASE_URL

# URL of the file to transcribe
FILE_URL = "https://assembly.ai/wildfires.mp3"
```python
import assemblyai as aai

aai.settings.base_url = "http://0.0.0.0:4000/eu.assemblyai" # <your-proxy-base-url>/eu.assemblyai
aai.settings.api_key = "Bearer sk-1234" # Bearer <your-virtual-key>

# You can also transcribe a local file by passing in a file path
# FILE_URL = './path/to/file.mp3'
# Use a publicly-accessible URL
audio_file = "https://assembly.ai/wildfires.mp3"

# Or use a local file:
# audio_file = "./path/to/file.mp3"

transcriber = aai.Transcriber()
transcript = transcriber.transcribe(FILE_URL)
transcript = transcriber.transcribe(audio_file)
print(transcript)
print(transcript.id)
```

## LLM Gateway

Use AssemblyAI's [LLM Gateway](https://www.assemblyai.com/docs/llm-gateway) as an OpenAI-compatible provider — a unified API for Claude, GPT, and Gemini models with full LiteLLM logging, guardrails, and cost tracking support.

[**See Available Models**](https://www.assemblyai.com/docs/llm-gateway#available-models)

### Usage

#### LiteLLM Python SDK

```python
import litellm
import os

os.environ["ASSEMBLYAI_API_KEY"] = "your-assemblyai-api-key"

response = litellm.completion(
model="assemblyai/claude-sonnet-4-5-20250929",
messages=[{"role": "user", "content": "What is the capital of France?"}]
)

print(response.choices[0].message.content)
```

#### LiteLLM Proxy

1. Config

```yaml
model_list:
- model_name: assemblyai/*
litellm_params:
model: assemblyai/*
api_key: os.environ/ASSEMBLYAI_API_KEY
```

2. Start proxy

```bash
litellm --config config.yaml

# RUNNING on http://0.0.0.0:4000
```

3. Test it!

```python
import requests

headers = {
"authorization": "Bearer sk-1234" # Bearer <your-virtual-key>
}

response = requests.post(
"http://0.0.0.0:4000/v1/chat/completions",
headers=headers,
json={
"model": "assemblyai/claude-sonnet-4-5-20250929",
"messages": [
{"role": "user", "content": "What is the capital of France?"}
],
"max_tokens": 1000
}
)

result = response.json()
print(result["choices"][0]["message"]["content"])
```
4 changes: 4 additions & 0 deletions litellm/llms/openai_like/providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,9 @@
"headers": {
"api-subscription-key": "{api_key}"
}
},
"assemblyai": {
"base_url": "https://llm-gateway.assemblyai.com/v1",
"api_key_env": "ASSEMBLYAI_API_KEY"
}
}
77 changes: 77 additions & 0 deletions tests/litellm/llms/openai_like/test_assemblyai_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Unit tests for the AssemblyAI LLM Gateway OpenAI-like provider.
"""

import os
import sys

sys.path.insert(
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../.."))
)

from litellm.llms.openai_like.dynamic_config import create_config_class
from litellm.llms.openai_like.json_loader import JSONProviderRegistry

ASSEMBLYAI_BASE_URL = "https://llm-gateway.assemblyai.com/v1"


def _get_config():
provider = JSONProviderRegistry.get("assemblyai")
assert provider is not None
config_class = create_config_class(provider)
return config_class()


def test_assemblyai_provider_registered():
provider = JSONProviderRegistry.get("assemblyai")
assert provider is not None
assert provider.base_url == ASSEMBLYAI_BASE_URL
assert provider.api_key_env == "ASSEMBLYAI_API_KEY"


def test_assemblyai_resolves_env_api_key(monkeypatch):
config = _get_config()
monkeypatch.setenv("ASSEMBLYAI_API_KEY", "test-key")
api_base, api_key = config._get_openai_compatible_provider_info(None, None)
assert api_base == ASSEMBLYAI_BASE_URL
assert api_key == "test-key"


def test_assemblyai_complete_url_appends_endpoint():
config = _get_config()
url = config.get_complete_url(
api_base=ASSEMBLYAI_BASE_URL,
api_key="test-key",
model="assemblyai/claude-sonnet-4-5-20250929",
optional_params={},
litellm_params={},
stream=False,
)
assert url == f"{ASSEMBLYAI_BASE_URL}/chat/completions"


def test_assemblyai_provider_resolution():
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider

model, provider, api_key, api_base = get_llm_provider(
model="assemblyai/claude-sonnet-4-5-20250929",
custom_llm_provider=None,
api_base=None,
api_key=None,
)

assert model == "claude-sonnet-4-5-20250929"
assert provider == "assemblyai"
assert api_base == ASSEMBLYAI_BASE_URL


def test_assemblyai_provider_config_manager():
from litellm import LlmProviders
from litellm.utils import ProviderConfigManager

config = ProviderConfigManager.get_provider_chat_config(
model="claude-sonnet-4-5-20250929", provider=LlmProviders.ASSEMBLYAI
)

assert config is not None
assert config.custom_llm_provider == "assemblyai"
Loading