-
Notifications
You must be signed in to change notification settings - Fork 129
Expand file tree
/
Copy pathsurvey_calling_agent.py
More file actions
118 lines (93 loc) · 4.09 KB
/
Copy pathsurvey_calling_agent.py
File metadata and controls
118 lines (93 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""
---
title: Survey Calling Agent
category: telephony
tags: [surveys, data-collection, csv-handling, automated-calling, metadata-processing, deepgram, openai, cartesia]
difficulty: intermediate
description: Automated survey calling agent with CSV data management and response recording
demonstrates:
- Survey data collection via phone calls
- CSV file integration for response tracking
- Metadata-based call configuration
- Automated room deletion after completion
- Function tools for survey response recording
- Professional survey caller persona
---
"""
import logging
import asyncio
import pandas as pd
import json
from pathlib import Path
from dotenv import load_dotenv
from livekit.agents import JobContext, JobProcess, AgentServer, cli, Agent, AgentSession, inference, RunContext, function_tool
from livekit.plugins import silero
from livekit.api import DeleteRoomRequest
load_dotenv()
logger = logging.getLogger("calling-agent")
logger.setLevel(logging.INFO)
csv_file_path = Path(__file__).parent / "survey_data.csv"
class SurveyAgent(Agent):
def __init__(self, question="Do you prefer chocolate or vanilla ice cream?", context=None, job_context=None) -> None:
self.survey_question = question
self.context = context or {}
self.job_context = job_context
self.survey_answer = None
self.phone_number = self.context.get("phone_number", "unknown")
self.row_index = self.context.get("row_index", 1)
instructions = f"""
You are conducting a brief phone survey. Your goal is to ask the following question:
'{self.survey_question}'
Be polite and professional. Introduce yourself as a survey caller named "Sam", ask the question,
and thank them for their time. Keep the call brief and focused on getting their answer.
Don't ask any follow-up questions.
Note: When you have an answer to the question, use the `record_survey_answer` function
to persist what the user said.
"""
super().__init__(instructions=instructions)
@function_tool
async def record_survey_answer(self, context: RunContext, answer: str):
logger.info(f"Survey answer recorded: {answer}")
logger.info(f"Row index: {self.row_index}")
self.survey_answer = answer
df = pd.read_csv(csv_file_path, dtype=str)
logger.info(f"CSV contents before update: {df.head()}")
df.loc[self.row_index - 1, 'Answer'] = answer
df.loc[self.row_index - 1, 'Status'] = 'Completed'
logger.info(f"CSV contents after update: {df.head()}")
df.to_csv(csv_file_path, index=False)
await asyncio.sleep(5)
await self.job_context.api.room.delete_room(DeleteRoomRequest(
room=self.job_context.room.name
))
return None, f"[Call ended]"
server = AgentServer()
def prewarm(proc: JobProcess):
proc.userdata["vad"] = silero.VAD.load()
server.setup_fnc = prewarm
@server.rtc_session()
async def entrypoint(ctx: JobContext):
ctx.log_context_fields = {"room": ctx.room.name}
metadata_json = ctx.job.metadata
logger.info(f"Received metadata: {metadata_json}")
metadata = json.loads(metadata_json)
phone_number = metadata.get("phone_number", "unknown")
row_index = metadata.get("row_index", 1)
question = metadata.get("question", "Do you prefer chocolate or vanilla ice cream?")
logger.info(f"Parsed metadata - phone_number: {phone_number}, row_index: {row_index}, question: {question}")
context = {
"phone_number": phone_number,
"row_index": row_index
}
session = AgentSession(
stt=inference.STT(model="deepgram/nova-3-general"),
llm=inference.LLM(model="openai/gpt-4.1-mini"),
tts=inference.TTS(model="cartesia/sonic-3", voice="9626c31c-bec5-4cca-baa8-f8ba9e84c8bc"),
vad=ctx.proc.userdata["vad"],
preemptive_generation=True,
)
agent = SurveyAgent(question=question, context=context, job_context=ctx)
await session.start(agent=agent, room=ctx.room)
await ctx.connect()
if __name__ == "__main__":
cli.run_app(server)