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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -790,14 +790,15 @@ aai.settings.api_key = "<YOUR_API_KEY>"

config = aai.DictationConfig(
language_codes=["en", "es"], # one code, or several for multilingual audio
stt_prompt="A doctor dictating a visit note.", # what the audio is about; ≤4096 chars
keyterms_prompt=["AssemblyAI", "Universal"], # bias the decoder; ≤2048 chars total
llm_instruction="Fix punctuation only.", # optional LLM pass
)

result = aai.DictationTranscriber().transcribe_live("./note.wav", config=config)
```

`sample_rate` and `channels` are required only for raw PCM; WAV carries them in its own header. A config passed to `transcribe_live()` or `open_live()` overrides the transcriber's default config for that call. `DictationConfig` rejects unknown fields, so a typo or a sync-only option surfaces as a validation error instead of a setting that quietly does nothing.
`stt_prompt` describes the situation the audio was recorded in and steers the decoder as it writes the transcript; `llm_instruction` reshapes that transcript afterwards. `sample_rate` and `channels` are required only for raw PCM; WAV carries them in its own header. A config passed to `transcribe_live()` or `open_live()` overrides the transcriber's default config for that call. `DictationConfig` rejects unknown fields, so a typo or a sync-only option surfaces as a validation error instead of a setting that quietly does nothing.

</details>

Expand Down
2 changes: 1 addition & 1 deletion assemblyai/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.5.0"
__version__ = "1.5.1"
14 changes: 12 additions & 2 deletions assemblyai/dictation/v1/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ def __init__(

_DICTATION_MAX_KEYTERMS_PROMPT_LEN = 2048
_DICTATION_MAX_LLM_INSTRUCTION_LEN = 2048
_DICTATION_MAX_STT_PROMPT_LEN = 4096


class DictationConfig(BaseModel):
"""
Options for a Dictation API request.

`language_codes` and `keyterms_prompt` shape the transcript;
`llm_instruction` asks the server to run a follow-up LLM pass over it
`language_codes`, `stt_prompt` and `keyterms_prompt` shape the
transcript; `llm_instruction` asks the server to run a follow-up LLM pass over it
(the rewrite lands in `DictationResponse.llm_response`). `sample_rate`
and `channels` are required only for raw PCM audio — container formats
carry them in their own headers.
Expand Down Expand Up @@ -87,6 +88,15 @@ class DictationConfig(BaseModel):
`["en", "es"]`) for multilingual audio. Defaults to None, which leaves
the language to the server's default."""

stt_prompt: Optional[str] = Field(
default=None, max_length=_DICTATION_MAX_STT_PROMPT_LEN
)
"""Context for the transcription: a description of what the audio is
about, e.g. "A doctor dictating a patient visit note." It describes the
situation rather than instructing the model, and steers the decoder as it
writes the transcript — where `llm_instruction` reshapes the transcript
afterwards. Max 4096 characters."""

keyterms_prompt: Optional[List[str]] = None
"Keyterms biasing the decoder. Whitespace is stripped and empty terms dropped. Max 2048 characters total."

Expand Down
30 changes: 29 additions & 1 deletion tests/unit/test_dictation.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,35 @@ def test_config_rejects_unknown_fields():
# Given an option the Dictation API does not accept
# When building the config, then it is rejected rather than dropped
with pytest.raises(ValueError):
aai.DictationConfig(prompt="Transcribe verbatim.")
aai.DictationConfig(word_boost=["AssemblyAI"])


def test_config_rejects_the_prompt_spelling():
# Given the server-side alias for stt_prompt
# When building the config, then the one spelling the SDK exposes wins —
# sending both is a 400, so there is nothing to gain from accepting two
with pytest.raises(ValueError):
aai.DictationConfig(prompt="A doctor dictating a visit note.")


def test_transcribe_live_sends_stt_prompt(httpx_mock: HTTPXMock):
# Given a mocked live endpoint
_mock_ok(httpx_mock)

# When streaming with transcription context
config = aai.DictationConfig(stt_prompt="A doctor dictating a visit note.")
aai.DictationTranscriber().transcribe_live(_chunks(b"RIFF"), config=config)

# Then the config part carries it under the name the API documents
body = httpx_mock.get_requests()[0].read()
assert b'"stt_prompt"' in body
assert b"A doctor dictating a visit note." in body


def test_stt_prompt_too_long_raises():
# Given an stt_prompt exceeding the 4096-char cap
with pytest.raises(ValueError):
aai.DictationConfig(stt_prompt="x" * 5000)


def test_keyterms_prompt_too_long_raises():
Expand Down
Loading