Skip to content

Commit b86c7f9

Browse files
authored
Add source for hosted agent (#48)
1 parent 3e342b9 commit b86c7f9

File tree

5 files changed

+346
-371
lines changed

5 files changed

+346
-371
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Python bytecode and artifacts
2+
**/__pycache__/
3+
**/*.py[cod]
4+
**/*.pyo
5+
**/*.pyd
6+
**/*.egg-info/
7+
**/dist/
8+
**/build/
9+
10+
# Virtual environments
11+
**/.venv/
12+
**/venv/
13+
14+
# Caches and test output
15+
**/.cache/
16+
**/.pytest_cache/
17+
**/.ruff_cache/
18+
**/coverage/
19+
20+
# Logs and temp files
21+
**/*.log
22+
**/*.gz
23+
**/*.tgz
24+
**/.tmp
25+
**/.cache
26+
27+
# Environment variables
28+
**/.env
29+
**/.env.*
30+
31+
# VCS, editor, OS
32+
.git
33+
.gitignore
34+
.gitattributes
35+
.github/
36+
.idea/
37+
.vscode/
38+
.DS_Store
39+
40+
# Project docs and misc
41+
README.md
42+
LICENSE
43+
44+
# Project tests
45+
test/
46+
tests/
47+
eval/
48+
evals/
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# This is an example Dockerfile that builds a minimal container for running LK Agents
2+
# For more information on the build process, see https://docs.livekit.io/agents/ops/deployment/builds/
3+
# syntax=docker/dockerfile:1
4+
5+
# Use the official UV Python base image with Python 3.13 on Debian Bookworm
6+
# UV is a fast Python package manager that provides better performance than pip
7+
# We use the slim variant to keep the image size smaller while still having essential tools
8+
ARG PYTHON_VERSION=3.13
9+
FROM ghcr.io/astral-sh/uv:python${PYTHON_VERSION}-bookworm-slim AS base
10+
11+
# Keeps Python from buffering stdout and stderr to avoid situations where
12+
# the application crashes without emitting any logs due to buffering.
13+
ENV PYTHONUNBUFFERED=1
14+
15+
# Create a non-privileged user that the app will run under.
16+
# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user
17+
ARG UID=10001
18+
RUN adduser \
19+
--disabled-password \
20+
--gecos "" \
21+
--home "/app" \
22+
--shell "/sbin/nologin" \
23+
--uid "${UID}" \
24+
appuser
25+
26+
# Install build dependencies required for Python packages with native extensions
27+
# gcc: C compiler needed for building Python packages with C extensions
28+
# g++: C++ compiler needed for building Python packages with C++ extensions
29+
# python3-dev: Python development headers needed for compilation
30+
# We clean up the apt cache after installation to keep the image size down
31+
RUN apt-get update && apt-get install -y \
32+
gcc \
33+
g++ \
34+
python3-dev \
35+
&& rm -rf /var/lib/apt/lists/*
36+
37+
# Create a new directory for our application code
38+
# And set it as the working directory
39+
WORKDIR /app
40+
41+
# Copy just the dependency files first, for more efficient layer caching
42+
COPY pyproject.toml uv.lock ./
43+
RUN mkdir -p src
44+
45+
# Install Python dependencies using UV's lock file
46+
# --locked ensures we use exact versions from uv.lock for reproducible builds
47+
# This creates a virtual environment and installs all dependencies
48+
# Ensure your uv.lock file is checked in for consistency across environments
49+
RUN uv sync --locked
50+
51+
# Copy all remaining pplication files into the container
52+
# This includes source code, configuration files, and dependency specifications
53+
# (Excludes files specified in .dockerignore)
54+
COPY . .
55+
56+
# Change ownership of all app files to the non-privileged user
57+
# This ensures the application can read/write files as needed
58+
RUN chown -R appuser:appuser /app
59+
60+
# Switch to the non-privileged user for all subsequent operations
61+
# This improves security by not running as root
62+
USER appuser
63+
64+
# Pre-download any ML models or files the agent needs
65+
# This ensures the container is ready to run immediately without downloading
66+
# dependencies at runtime, which improves startup time and reliability
67+
RUN uv run "agent.py" download-files
68+
69+
# Run the application using UV
70+
# UV will activate the virtual environment and run the agent.
71+
# The "start" command tells the worker to connect to LiveKit and begin waiting for jobs.
72+
CMD ["uv", "run", "agent.py", "start"]

components/livekit/examples/voice_agent/agent/agent.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@
1313
)
1414
from livekit.plugins import (
1515
openai,
16-
cartesia,
17-
deepgram,
18-
silero,
16+
noise_cancellation
1917
)
20-
from livekit.plugins.turn_detector.multilingual import MultilingualModel
2118

2219
# If enabled, RPC calls will not be performed.
2320
TEST_MODE = False
@@ -31,18 +28,13 @@ class LEDColor(str, Enum):
3128
class Assistant(Agent):
3229
def __init__(self) -> None:
3330
super().__init__(
34-
instructions="""You are a helpful voice AI assistant running on an ESP-32 dev board.
31+
instructions="""You are a helpful voice AI assistant running on an ESP32 dev board.
3532
You answer user's questions about the hardware state and control the hardware based on their requests.
3633
The board has discrete LEDs that can be controlled independently. Each LED has a static color
3734
that cannot be changed. While you are able to set the state of the LEDs, you are not able to read the
3835
state which could be changed without your knowledge. No markdown is allowed in your responses.
3936
"""
4037
)
41-
async def on_enter(self) -> None:
42-
await self.session.say(
43-
"Hi, how can I help you today?",
44-
allow_interruptions=False
45-
)
4638

4739
@function_tool()
4840
async def set_led_state(self, _: RunContext, led: LEDColor, state: bool) -> None:
@@ -92,16 +84,17 @@ async def get_cpu_temp(self, _: RunContext) -> float:
9284

9385
async def entrypoint(ctx: agents.JobContext):
9486
session = AgentSession(
95-
stt=deepgram.STT(model="nova-3", language="multi"),
96-
llm=openai.LLM(model="gpt-4o-mini"),
97-
tts=cartesia.TTS(model="sonic-2", voice="c99d36f3-5ffd-4253-803a-535c1bc9c306"),
98-
vad=silero.VAD.load(),
99-
turn_detection=MultilingualModel(),
87+
llm=openai.realtime.RealtimeModel(
88+
voice="echo",
89+
model="gpt-4o-mini-realtime-preview-2024-12-17"
90+
)
10091
)
10192
await session.start(
10293
room=ctx.room,
10394
agent=Assistant(),
104-
room_input_options=RoomInputOptions()
95+
room_input_options=RoomInputOptions(
96+
noise_cancellation=noise_cancellation.BVC()
97+
)
10598
)
10699
await ctx.connect()
107100

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
[project]
22
name = "esp-example-agent"
33
version = "0.1.0"
4-
description = "Example agent for interacting with the ESP-32 voice chat example."
4+
description = "Example agent for ESP32 voice agent example."
55
readme = "README.md"
66
license = {text = "MIT"}
77
requires-python = ">=3.13"
88
dependencies = [
9-
"livekit-agents[cartesia,deepgram,openai,silero,turn-detector]~=1.0",
9+
"livekit-agents[openai]~=1.2.14",
10+
"livekit-plugins-noise-cancellation~=0.2",
1011
"python-dotenv>=1.1.1"
11-
]
12+
]

0 commit comments

Comments
 (0)