> For clean Markdown of any page, append `.md` to the page URL. > For a complete documentation index, see https://docs.sarvam.ai/llms.txt. > For full documentation content in one file, see https://docs.sarvam.ai/llms-full.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sarvam.ai/_mcp/server. # Keyterm Prompting > Use keyterms to help Saaras v4 recognize important names, places, brands, and technical terms. > **Note** > > **`saaras:v4` only.** Keyterms are supported only with `model="saaras:v4"`, on the REST, Batch, and WebSocket streaming APIs (both the legacy `/speech-to-text/ws` and realtime `/speech-to-text-realtime/ws` endpoints). Keyterms help Saaras v4 recognize important names, places, brands, and technical terms that may occur in an audio file, for example: ```json ["Sarvam", "New Delhi", "Vistaar"] ``` Keyterms bias recognition; they do not guarantee that a term will appear in the transcript. ### Rules | Rule | Detail | | ----------------- | --------------------------------------------------- | | Model support | Only `model="saaras:v4"` | | Format | JSON list of strings under `keyterms` | | Max terms | 50 distinct keyterms | | Max length | 64 characters per keyterm | | Phrases | Put phrases such as `New Delhi` in one list item | | Delimiting | Do not send comma-separated terms in one string | | Deprecated fields | Do not use the older `keyterm` or `hotwords` fields | > **Note** > > Use `mode="codemix"` instead of `mode="transcribe"` when a keyterm such as `PhonePe` must remain in Latin script, the `keyterms` format is unchanged across all supported modes. See [Choosing the transcription mode](#choosing-the-transcription-mode) below. > **Tip** > > Upgrade your SDK before using `keyterms`. Python: verified on `sarvamai>=0.1.33a1` for REST, `sarvamai>=0.1.33a3` for `speech_to_text_job.create_job()`. JavaScript: verified on `sarvamai>=1.1.10-alpha.1` for `speechToTextJob.createJob()`, a fix for REST `speechToText.transcribe()` has not shipped to npm yet; until it's released, use the JavaScript Batch example below, or the REST cURL/Python examples. ## REST API REST requests use `multipart/form-data`. Send `keyterms` as a JSON-encoded array in one form field. #### Python ```python import os from sarvamai import SarvamAI client = SarvamAI(api_subscription_key=os.environ["SARVAM_API_KEY"]) response = client.speech_to_text.transcribe( file=open("audio.wav", "rb"), model="saaras:v4", mode="transcribe", language_code="hi-IN", keyterms=["Sarvam", "New Delhi", "Vistaar"], ) print(response.transcript) ``` #### JavaScript ```javascript // Requires an upcoming sarvamai release. See the Tip above import { SarvamAIClient } from "sarvamai"; import fs from "fs"; const client = new SarvamAIClient({ apiSubscriptionKey: process.env.SARVAM_API_KEY }); const response = await client.speechToText.transcribe({ file: fs.createReadStream("audio.wav"), model: "saaras:v4", mode: "transcribe", languageCode: "hi-IN", keyterms: ["Sarvam", "New Delhi", "Vistaar"], }); console.log(response.transcript); ``` #### cURL ```bash curl -X POST https://api.sarvam.ai/speech-to-text \ -H "api-subscription-key: $SARVAM_API_KEY" \ -F 'model=saaras:v4' \ -F 'mode=transcribe' \ -F 'language_code=hi-IN' \ -F 'keyterms=["Sarvam","New Delhi","Vistaar"]' \ -F 'file=@audio.wav;type=audio/wav' ``` Omit `language_code` to use automatic language detection. ## Batch API For batch jobs, `keyterms` is a normal JSON array inside `job_parameters`. #### Python ```python job = client.speech_to_text_job.create_job( model="saaras:v4", mode="transcribe", language_code="hi-IN", with_diarization=True, keyterms=["Sarvam", "New Delhi", "Vistaar"], ) job.upload_files(file_paths=["interview.wav"]) job.start() job.wait_until_complete() job.download_outputs(output_dir="./output") ``` #### JavaScript ```javascript const job = await client.speechToTextJob.createJob({ model: "saaras:v4", mode: "transcribe", languageCode: "hi-IN", withDiarization: true, keyterms: ["Sarvam", "New Delhi", "Vistaar"], }); await job.uploadFiles(["interview.wav"]); await job.start(); await job.waitUntilComplete(); await job.downloadOutputs("./output"); ``` #### cURL ```bash curl --fail-with-body -X POST \ 'https://api.sarvam.ai/speech-to-text/job/v1' \ -H "api-subscription-key: $SARVAM_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "job_parameters": { "model": "saaras:v4", "mode": "transcribe", "language_code": "hi-IN", "keyterms": ["Sarvam", "New Delhi", "Vistaar"] } }' ``` After creating the job, use the returned job ID to upload the audio, start the job, poll its status, and download the output using the standard [Batch API](/api/api-guides-tutorials/speech-to-text/batch-api) workflow. ### Batch with diarization Add `with_diarization`. The same keyterms are applied while transcribing every audio chunk in the job, the downloaded result includes the full transcript and, when requested, speaker-attributed entries under `diarized_transcript`. #### Python ```python job = client.speech_to_text_job.create_job( model="saaras:v4", mode="transcribe", language_code="hi-IN", with_diarization=True, with_timestamps=True, keyterms=["Sarvam", "New Delhi", "Vistaar"], ) ``` #### JavaScript ```javascript const job = await client.speechToTextJob.createJob({ model: "saaras:v4", mode: "transcribe", languageCode: "hi-IN", withDiarization: true, withTimestamps: true, keyterms: ["Sarvam", "New Delhi", "Vistaar"], }); ``` #### cURL ```bash curl --fail-with-body -X POST \ 'https://api.sarvam.ai/speech-to-text/job/v1' \ -H "api-subscription-key: $SARVAM_API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "job_parameters": { "model": "saaras:v4", "mode": "transcribe", "language_code": "hi-IN", "with_diarization": true, "with_timestamps": true, "keyterms": ["Sarvam", "New Delhi", "Vistaar"] } }' ``` See [Enable Speaker Diarization](/api/api-guides-tutorials/speech-to-text/how-to/enable-speaker-diarization) for the full diarization output format. ## Streaming WebSockets Both WebSocket endpoints accept `keyterms` as a query parameter on the connection URL, sent as a JSON-encoded (and URL-encoded) array: ``` wss://api.sarvam.ai/speech-to-text/ws?model=saaras:v4&language_code=hi-IN&keyterms=%5B%22Sarvam%22%2C%22New%20Delhi%22%5D wss://api.sarvam.ai/speech-to-text-realtime/ws?model=saaras:v4&language_code=hi-IN&keyterms=%5B%22Sarvam%22%2C%22New%20Delhi%22%5D ``` The Python and JavaScript SDK `connect()` helpers do not expose `keyterms` yet, so use a raw WebSocket client and append the query parameter yourself: #### Legacy WSS (Python) ```python import asyncio import base64 import json import os import urllib.parse import websockets async def transcribe_with_keyterms(): params = urllib.parse.urlencode({ "model": "saaras:v4", "language_code": "hi-IN", "keyterms": json.dumps(["Sarvam", "New Delhi", "Vistaar"]), }) async with websockets.connect( f"wss://api.sarvam.ai/speech-to-text/ws?{params}", additional_headers={"api-subscription-key": os.environ["SARVAM_API_KEY"]}, ) as ws: audio = base64.b64encode(open("audio.wav", "rb").read()).decode("utf-8") await ws.send(json.dumps({ "audio": audio, "encoding": "audio/wav", "sample_rate": 16000, })) print(await ws.recv()) asyncio.run(transcribe_with_keyterms()) ``` #### Realtime streaming (Python) ```python import asyncio import base64 import json import os import urllib.parse import websockets async def transcribe_with_keyterms(): params = urllib.parse.urlencode({ "model": "saaras:v4", "language_code": "hi-IN", "keyterms": json.dumps(["Sarvam", "New Delhi", "Vistaar"]), }) async with websockets.connect( f"wss://api.sarvam.ai/speech-to-text-realtime/ws?{params}", additional_headers={"api-subscription-key": os.environ["SARVAM_API_KEY"]}, ) as ws: with open("audio.pcm", "rb") as f: while chunk := f.read(3200): # ~100ms of 16 kHz mono 16-bit audio await ws.send(json.dumps({ "event": "audio_input", "audio": base64.b64encode(chunk).decode("utf-8"), })) await ws.send(json.dumps({"event": "end"})) async for message in ws: event = json.loads(message) if event["event"] == "transcript.final": print(event["text"]) return asyncio.run(transcribe_with_keyterms()) ``` Keyterms are set when the connection is opened and apply for the whole session; they cannot be changed mid-stream. ## Choosing the transcription mode The `keyterms` format is unchanged across all supported modes: | Mode | Behavior | | ------------ | ----------------------------------------------------------------- | | `transcribe` | Native-script transcription; English words use native script | | `codemix` | Native-script transcription; English words remain in Latin script | | `verbatim` | Speech as spoken, without punctuation | | `translit` | Transcription in Latin script | | `translate` | English translation | For example, use `mode="codemix"` instead of `mode="transcribe"` when a keyterm such as `PhonePe` must remain in Latin script. > **Note** > > Need help choosing between REST and Batch? See [Which API to Use](/api/api-guides-tutorials/speech-to-text/which-api-to-use). > Use keyterms to help Saaras v4 recognize important names, places, brands, and technical terms.