Skip to content

Commit 585b134

Browse files
committed
Add more complex agent
1 parent c1d3a57 commit 585b134

File tree

2 files changed

+89
-13
lines changed

2 files changed

+89
-13
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,18 @@ You can also do this automatically using the LiveKit CLI:
3939
lk app env -w .env
4040
```
4141

42-
Run the agent:
42+
Run the agent in console mode:
4343

4444
```console
45-
uv run python src/agent.py dev
45+
uv run python src/agent.py console
4646
```
4747

48+
4849
This agent requires a frontend application to communicate with. Use a [starter app](https://docs.livekit.io/agents/start/frontend/#starter-apps), our hosted [Sandbox](https://cloud.livekit.io/projects/p_/sandbox) frontends, or the [LiveKit Agents Playground](https://agents-playground.livekit.io/).
4950

5051

51-
Run tests
52+
Run evals
5253

5354
```console
54-
uv run pytest
55+
uv run pytest evals
5556
```

src/agent.py

Lines changed: 84 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,115 @@
1+
import logging
2+
13
from dotenv import load_dotenv
24

3-
from livekit import agents
4-
from livekit.agents import AgentSession, Agent, RoomInputOptions
5-
from livekit.plugins import openai, noise_cancellation, silero, deepgram, cartesia
5+
from livekit.agents import (
6+
Agent,
7+
AgentSession,
8+
JobContext,
9+
JobProcess,
10+
RoomInputOptions,
11+
RoomOutputOptions,
12+
RunContext,
13+
WorkerOptions,
14+
cli,
15+
metrics,
16+
)
17+
from livekit.agents.llm import function_tool
18+
from livekit.agents.voice import MetricsCollectedEvent
19+
from livekit.plugins import cartesia, deepgram, openai, silero
620
from livekit.plugins.turn_detector.multilingual import MultilingualModel
21+
from livekit.plugins import noise_cancellation
22+
23+
logger = logging.getLogger("agent")
724

825
load_dotenv()
926

1027

1128
class Assistant(Agent):
1229
def __init__(self) -> None:
13-
super().__init__(instructions="You are a helpful voice AI assistant.")
30+
super().__init__(
31+
instructions="Your name is Kelly. You would interact with users via voice."
32+
"with that in mind keep your responses concise and to the point."
33+
"You are curious and friendly, and have a sense of humor.",
34+
)
35+
36+
async def on_enter(self):
37+
# when the agent is added to the session, it'll generate a reply
38+
# according to its instructions
39+
self.session.generate_reply()
40+
41+
# all functions annotated with @function_tool will be passed to the LLM when this
42+
# agent is active
43+
@function_tool
44+
async def lookup_weather(
45+
self, context: RunContext, location: str, latitude: str, longitude: str
46+
):
47+
"""Called when the user asks for weather related information.
48+
Ensure the user's location (city or region) is provided.
49+
When given a location, please estimate the latitude and longitude of the location and
50+
do not ask the user for them.
51+
52+
Args:
53+
location: The location they are asking for
54+
latitude: The latitude of the location, do not ask user for it
55+
longitude: The longitude of the location, do not ask user for it
56+
"""
57+
58+
logger.info(f"Looking up weather for {location}")
59+
60+
return "sunny with a temperature of 70 degrees."
1461

1562

16-
async def entrypoint(ctx: agents.JobContext):
63+
def prewarm(proc: JobProcess):
64+
proc.userdata["vad"] = silero.VAD.load()
65+
66+
67+
async def entrypoint(ctx: JobContext):
68+
# each log entry will include these fields
69+
ctx.log_context_fields = {
70+
"room": ctx.room.name,
71+
}
72+
1773
session = AgentSession(
18-
stt=deepgram.STT(),
74+
vad=ctx.proc.userdata["vad"],
75+
# any combination of STT, LLM, TTS, or realtime API can be used
1976
llm=openai.LLM(model="gpt-4o-mini"),
77+
stt=deepgram.STT(model="nova-3", language="multi"),
2078
tts=cartesia.TTS(),
21-
vad=silero.VAD.load(),
79+
# use LiveKit's turn detection model
2280
turn_detection=MultilingualModel(),
2381
)
2482

83+
# log metrics as they are emitted, and total usage after session is over
84+
usage_collector = metrics.UsageCollector()
85+
86+
@session.on("metrics_collected")
87+
def _on_metrics_collected(ev: MetricsCollectedEvent):
88+
metrics.log_metrics(ev.metrics)
89+
usage_collector.collect(ev.metrics)
90+
91+
async def log_usage():
92+
summary = usage_collector.get_summary()
93+
logger.info(f"Usage: {summary}")
94+
95+
# shutdown callbacks are triggered when the session is over
96+
ctx.add_shutdown_callback(log_usage)
97+
2598
await session.start(
99+
agent=MyAgent(),
26100
room=ctx.room,
27-
agent=Assistant(),
28101
room_input_options=RoomInputOptions(
29102
# LiveKit Cloud enhanced noise cancellation
30103
# - If self-hosting, omit this parameter
31104
# - For telephony applications, use `BVCTelephony` for best results
32105
noise_cancellation=noise_cancellation.BVC(),
33106
),
107+
room_output_options=RoomOutputOptions(transcription_enabled=True),
34108
)
35109

110+
# join the room when agent is ready
36111
await ctx.connect()
37112

38113

39114
if __name__ == "__main__":
40-
agents.cli.run_app(agents.WorkerOptions(entrypoint_fnc=entrypoint))
115+
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint, prewarm_fnc=prewarm))

0 commit comments

Comments
 (0)