For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
PlaygroundChangelogSign In
OverviewAPI ReferencePre-recorded STTStreaming STTVoice AgentsSpeech UnderstandingGuardrailsLLM GatewayFAQ
OverviewAPI ReferencePre-recorded STTStreaming STTVoice AgentsSpeech UnderstandingGuardrailsLLM GatewayFAQ
  • Getting started
    • Overview
    • Apply LLM Gateway to pre-recorded audio
    • Apply LLM Gateway to streaming audio
    • Specify fallback models
    • Prompt caching
    • Post-processing
    • Cloud endpoints & data residency
    • Troubleshooting
  • Use cases
    • Ask questions about your audio data
    • Build agentic workflows
    • Basic chat completions
    • Multi-turn conversations
    • Use tool calling with LLMs
    • Get structured JSON outputs
  • Guides
      • Analyze The Sentiment Of A Customer Call using LLM Gateway
      • Custom Topic Tags
      • Redact PII from Text Using LLM Gateway
LogoLogo
PlaygroundChangelogSign In
On this page
  • Quickstart
  • Get Started
  • Step-by-Step Instructions
  • Install dependencies
GuidesSubstitute Speech Understanding with LLM Gateway

Analyze The Sentiment Of A Customer Call using LLM Gateway

Was this page helpful?
Previous

Custom Topic Tags Using LLM Gateway

Next
Built with

In this guide, we’ll show you how to use AssemblyAI’s LLM Gateway framework to process an audio file and then use LLM Gateway to automatically detect sentiment analysis from customer calls as “positive”, “negative”, or “neutral”. In addition, we will glean additional insights beyond these three sentiments and learn the reasoning behind these detected sentiments.

Quickstart

Python
JavaScript
1import requests
2import time
3
4API_KEY = "YOUR_API_KEY"
5audio_file_path = "./meeting.mp3"
6
7# ------------------------------------------
8# Step 1: Upload the audio file
9# ------------------------------------------
10def upload_file(filename):
11 with open(filename, "rb") as f:
12 upload_url = "https://api.assemblyai.com/v2/upload"
13 headers = {"authorization": API_KEY}
14 response = requests.post(upload_url, headers=headers, data=f)
15 response.raise_for_status()
16 return response.json()["upload_url"]
17
18audio_url = upload_file(audio_file_path)
19print(f"Uploaded audio file. URL: {audio_url}")
20
21# ------------------------------------------
22# Step 2: Request transcription
23# ------------------------------------------
24transcript_request = requests.post(
25 "https://api.assemblyai.com/v2/transcript",
26 headers={"authorization": API_KEY, "content-type": "application/json"},
27 json={"audio_url": audio_url, "speech_models": ["universal-3-pro"]},
28)
29
30transcript_id = transcript_request.json()["id"]
31
32# Poll until completed
33while True:
34 polling_response = requests.get(
35 f"https://api.assemblyai.com/v2/transcript/{transcript_id}",
36 headers={"authorization": API_KEY},
37 )
38 status = polling_response.json()["status"]
39
40 if status == "completed":
41 break
42 elif status == "error":
43 raise RuntimeError(f"Transcription failed: {polling_response.json()['error']}")
44 else:
45 print(f"Transcription status: {status}")
46 time.sleep(3)
47
48print("\nTranscription complete.\n")
49
50# ------------------------------------------
51# Step 3: Define questions
52# ------------------------------------------
53agent_context = "The agent is trying to get the customer to go through with the update to their car."
54customer_context = "The customer is calling to check how much it would cost to update the map in his car."
55
56answer_format = "<answer in one sentence> <reason in one sentence>"
57
58questions = [
59 {
60 "question": "What was the overall sentiment of the call?",
61 "context": customer_context,
62 "answer_format": answer_format,
63 },
64 {
65 "question": "What was the sentiment of the agent in this call?",
66 "context": agent_context,
67 "answer_format": answer_format,
68 },
69 {
70 "question": "What was the sentiment of the customer in this call?",
71 "context": customer_context,
72 "answer_format": answer_format,
73 },
74 {
75 "question": "What quote best demonstrates the customer's level of interest?",
76 "context": customer_context,
77 "answer_format": answer_format,
78 },
79 {
80 "question": "Provide a quote from the agent that demonstrates their level of enthusiasm.",
81 "context": agent_context,
82 "answer_format": answer_format,
83 },
84]
85
86# ------------------------------------------
87# Step 4: Build prompt for the LLM
88# ------------------------------------------
89question_strs = []
90for q in questions:
91 q_str = f"Question: {q['question']}"
92 if q.get("context"):
93 q_str += f"\nContext: {q['context']}"
94 if q.get("answer_format"):
95 q_str += f"\nAnswer Format: {q['answer_format']}"
96 question_strs.append(q_str)
97
98questions_prompt = "\n\n".join(question_strs)
99
100prompt = f"""
101You are an expert at analyzing call transcripts.
102Given the series of questions below, answer them accurately and concisely.
103When context or answer format is provided, use it to guide your answers.
104
105Transcript:
106{{{{ transcript }}}}
107
108Questions:
109{questions_prompt}
110"""
111
112# ------------------------------------------
113# Step 5: Query the LLM Gateway
114# ------------------------------------------
115headers = {"authorization": API_KEY}
116
117response = requests.post(
118 "https://llm-gateway.assemblyai.com/v1/chat/completions",
119 headers=headers,
120 json={
121 "model": "claude-sonnet-4-5-20250929",
122 "messages": [{"role": "user", "content": prompt}],
123 "transcript_id": transcript_id,
124 "max_tokens": 2000,
125 },
126)
127
128response_json = response.json()
129llm_output = response_json["choices"][0]["message"]["content"]
130
131# ------------------------------------------
132# Step 6: Parse and display the results
133# ------------------------------------------
134print("\n--- LLM Responses ---\n")
135print(llm_output)

Get Started

Before we begin, make sure you have an AssemblyAI account and an API key. You can sign up for an AssemblyAI account and get your API key from your dashboard.

See our pricing page for LLM Gateway pricing rates.

Step-by-Step Instructions

In this guide, we will ask five questions to learn about the sentiment of the customer and agent. You can adjust the questions to suit your project’s needs.

Install dependencies

Install the required packages.

Python
JavaScript
$pip install requests

Import the required libraries and set your AssemblyAI API key.

Python
JavaScript
1import requests
2import time
3
4API_KEY = "YOUR_API_KEY"

Next, you’ll upload your audio file to AssemblyAI’s servers. Once the upload is complete, the API will return a temporary URL that can be used to start the transcription.

After submitting the transcription request, your script will poll the API until the transcription is finished.

Python
JavaScript
1audio_file_path = "./meeting.mp3"
2# ------------------------------------------
3# Step 1: Upload the audio file
4# ------------------------------------------
5def upload_file(filename):
6 with open(filename, "rb") as f:
7 upload_url = "https://api.assemblyai.com/v2/upload"
8 headers = {"authorization": API_KEY}
9 response = requests.post(upload_url, headers=headers, data=f)
10 response.raise_for_status()
11 return response.json()["upload_url"]
12audio_url = upload_file(audio_file_path)
13print(f"Uploaded audio file. URL: {audio_url}")
14# ------------------------------------------
15# Step 2: Request transcription
16# ------------------------------------------
17transcript_request = requests.post(
18 "https://api.assemblyai.com/v2/transcript",
19 headers={"authorization": API_KEY, "content-type": "application/json"},
20 json={"audio_url": audio_url, "speech_models": ["universal-3-pro"]},
21)
22transcript_id = transcript_request.json()["id"]
23# Poll until completed
24while True:
25 polling_response = requests.get(
26 f"https://api.assemblyai.com/v2/transcript/{transcript_id}",
27 headers={"authorization": API_KEY},
28 )
29 status = polling_response.json()["status"]
30 if status == "completed":
31 break
32 elif status == "error":
33 raise RuntimeError(f"Transcription failed: {polling_response.json()['error']}")
34 else:
35 print(f"Transcription status: {status}")
36 time.sleep(3)
37print("\nTranscription complete.\n")

Once you have the transcript, you’ll define short context strings for both the agent and the customer. These will help the model better understand the roles and perspectives in the conversation.

Python
JavaScript
1agent_context = "The agent is trying to get the customer to go through with the update to their car."
2customer_context = "The customer is calling to check how much it would cost to update the map in his car."

You can now specify the exact questions you want the LLM Gateway to answer. Each question can include optional context and an answer format that tells the model how to structure its response.

Python
JavaScript
1answer_format = "<answer in one sentence> <reason in one sentence>"
2questions = [
3 {
4 "question": "What was the overall sentiment of the call?",
5 "context": customer_context,
6 "answer_format": answer_format,
7 },
8 {
9 "question": "What was the sentiment of the agent in this call?",
10 "context": agent_context,
11 "answer_format": answer_format,
12 },
13 {
14 "question": "What was the sentiment of the customer in this call?",
15 "context": customer_context,
16 "answer_format": answer_format,
17 },
18 {
19 "question": "What quote best demonstrates the customer's level of interest?",
20 "context": customer_context,
21 "answer_format": answer_format,
22 },
23 {
24 "question": "Provide a quote from the agent that demonstrates their level of enthusiasm.",
25 "context": agent_context,
26 "answer_format": answer_format,
27 },
28]

Now that the questions are defined, combine them into a single formatted prompt. This prompt includes both the call transcript and the questions you want the model to address. The model will use these details to generate accurate and concise responses.

Python
JavaScript
1# ------------------------------------------
2# Step 4: Build prompt for the LLM
3# ------------------------------------------
4question_strs = []
5for q in questions:
6 q_str = f"Question: {q['question']}"
7 if q.get("context"):
8 q_str += f"\nContext: {q['context']}"
9 if q.get("answer_format"):
10 q_str += f"\nAnswer Format: {q['answer_format']}"
11 question_strs.append(q_str)
12questions_prompt = "\n\n".join(question_strs)
13prompt = f"""
14You are an expert at analyzing call transcripts.
15Given the series of questions below, answer them accurately and concisely.
16When context or answer format is provided, use it to guide your answers.
17Transcript:
18{{{{ transcript }}}}
19Questions:
20{questions_prompt}
21"""

With the prompt prepared, query LLM Gateway then extract and print the answers returned by the LLM Gateway. This step displays the model’s assessment of each question, including the identified sentiments and their reasoning.

Python
JavaScript
1# ------------------------------------------
2# Step 5: Query the LLM Gateway
3# ------------------------------------------
4headers = {"authorization": API_KEY}
5response = requests.post(
6 "https://llm-gateway.assemblyai.com/v1/chat/completions",
7 headers=headers,
8 json={
9 "model": "claude-sonnet-4-5-20250929",
10 "messages": [{"role": "user", "content": prompt}],
11 "transcript_id": transcript_id,
12 "max_tokens": 2000,
13 },
14)
15response_json = response.json()
16llm_output = response_json["choices"][0]["message"]["content"]
17# ------------------------------------------
18# Step 6: Parse and display the results
19# ------------------------------------------
20print("\n--- LLM Responses ---\n")
21print(llm_output)