tall-mechanic-24834
02/15/2025, 10:41 PMgray-monkey-83525
02/15/2025, 10:41 PMtall-mechanic-24834
02/15/2025, 10:42 PMgray-monkey-83525
02/15/2025, 10:42 PMtokens
module is not available in the LiveKit package you are using. According to the LiveKit API documentation, there is no mention of a tokens
module. This might be causing the ImportError
.
To resolve this, you can generate tokens using the AccessToken
class from the livekit.api.access_token
module. Here's a brief example of how you can create a token:
from livekit.api.access_token import AccessToken
def create_token(api_key, api_secret, identity, room_name):
token = AccessToken(api_key=api_key, api_secret=api_secret)
token.with_identity(identity)
token.with_grants({
"room": room_name,
"roomJoin": True,
"canPublish": True,
"canSubscribe": True
})
return token.to_jwt()
Would you like more details on how to integrate this into your existing code?
Sources:
- LiveKit API documentation 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/15/2025, 10:44 PMgray-monkey-83525
02/15/2025, 10:44 PMAccessToken
. The with_grants
method expects a VideoGrants
object rather than a dictionary. Here's how you can fix it:
1. Import the VideoGrants
class from the livekit.api.access_token
module.
2. Use VideoGrants
to specify the permissions.
Here's the corrected code for the create_token
method:
from livekit.api.access_token import AccessToken, VideoGrants
def create_token(self, room_name, participant_name):
token = AccessToken(api_key=self.api_key, api_secret=self.api_secret)
token.with_identity(participant_name)
video_grants = VideoGrants(
room=room_name,
room_join=True,
can_publish=True,
can_subscribe=True
)
token.with_grants(video_grants)
return token.to_jwt()
This should resolve the AttributeError
by using the correct VideoGrants
object to set the permissions.
Would you like more details on this solution?
Sources:
- LiveKit API documentation 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/15/2025, 10:46 PMgray-monkey-83525
02/15/2025, 10:46 PMRoom.connect
method. The connect
method is an instance method and should be called on an instance of the Room
class, not as a class method. Here's how you can fix it:
1. Create an instance of the Room
class.
2. Call the connect
method on that instance.
Here's the corrected code for the create_and_connect_to_room
method:
async def create_and_connect_to_room(self, room_name, participant_name):
try:
print(f"Creating token for room: {room_name}, participant: {participant_name}")
token = self.create_token(room_name, participant_name)
print("Token created successfully")
# Create an instance of the Room class
room = rtc.Room()
# Connect to the room using the instance method
await room.connect(
url=self.ws_url,
token=token
)
print("Connected to room successfully")
return room, token
except Exception as e:
print(f"Error creating/connecting to room: {e}")
print("Traceback:")
print(traceback.format_exc())
return None, None
Make sure to replace <http://self.ws|self.ws>_url
with self.ws_url
in the connect
method call. This should resolve the TypeError
by using the connect
method correctly.
Would you like more details on this solution?
Sources:
- https://docs.livekit.io/python/livekit/rtc/room.html#livekit.rtc.room.Room.connection_state
- https://docs.livekit.io/python/livekit/rtc/index.html#livekit.rtc.Room 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/15/2025, 10:47 PMgray-monkey-83525
02/15/2025, 10:47 PM<http://self.ws|self.ws>_url
should be replaced with self.ws_url
to correctly reference the instance variable. Here's the corrected version of your RoomManager
class:
from livekit.api.access_token import AccessToken, VideoGrants
from livekit import rtc
import os
from dotenv import load_dotenv
import traceback
load_dotenv()
class RoomManager:
def __init__(self):
self.api_key = os.getenv('LIVEKIT_API_KEY')
self.api_secret = os.getenv('LIVEKIT_API_SECRET')
self.ws_url = os.getenv('LIVEKIT_WS_URL') # Corrected variable name
print(f"Initializing with URL: {self.ws_url}")
def create_token(self, room_name, participant_name):
token = AccessToken(api_key=self.api_key, api_secret=self.api_secret)
token.with_identity(participant_name)
video_grants = VideoGrants(
room=room_name,
room_join=True,
can_publish=True,
can_subscribe=True
)
token.with_grants(video_grants)
return token.to_jwt() # Corrected method call
async def create_and_connect_to_room(self, room_name, participant_name):
try:
print(f"Creating token for room: {room_name}, participant: {participant_name}")
token = self.create_token(room_name, participant_name)
print("Token created successfully")
# Create a new Room instance first
room = rtc.Room()
# Then connect using the instance
await room.connect(
url=self.ws_url, # Corrected variable name
token=token
)
print("Connected to room successfully")
return room, token
except Exception as e:
print(f"Error creating/connecting to room: {e}")
print("Traceback:")
print(traceback.format_exc())
return None, None
async def close(self):
pass
This version should resolve the issues with the URL and token method call. Let me know if you need further assistance!
Sources:
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1728956116.368569
- https://docs.livekit.io/python/livekit/rtc/index.html#livekit.rtc.Room 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/15/2025, 10:49 PMgray-monkey-83525
02/15/2025, 10:49 PMurl
variable is None
, which is causing a TypeError
when trying to assign it to req.connect.url
. This is likely because the environment variable LIVEKIT_WS_URL
is not being loaded correctly, resulting in self.ws_url
being None
.
Here's how you can troubleshoot and fix this issue:
1. Check Environment Variables: Ensure that the .env
file contains the correct LIVEKIT_WS_URL
and that it is being loaded properly. The .env
file should look something like this:
LIVEKIT_API_KEY=your_api_key
LIVEKIT_API_SECRET=your_api_secret
LIVEKIT_WS_URL=wss://your-livekit-server-url
2. Verify load_dotenv()
: Make sure that load_dotenv()
is called before accessing the environment variables in your RoomManager
class.
3. Debugging: Add a print statement to check if self.ws_url
is being set correctly:
class RoomManager:
def __init__(self):
self.api_key = os.getenv('LIVEKIT_API_KEY')
self.api_secret = os.getenv('LIVEKIT_API_SECRET')
self.ws_url = os.getenv('LIVEKIT_WS_URL')
print(f"Initializing with URL: {self.ws_url}") # Check if this prints the correct URL
4. Correct URL Usage: Ensure that the self.ws_url
is correctly used in the connect
method:
await room.connect(
url=self.ws_url,
token=token
)
If the LIVEKIT_WS_URL
is still None
, double-check the .env
file path and ensure that it is in the correct directory where your script is running.
Would you like more details on this solution?
Sources:
- https://docs.livekit.io/python/livekit/rtc/index.html#livekit.rtc.Room 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/15/2025, 10:53 PMgray-monkey-83525
02/15/2025, 10:53 PM<http://self.ws|self.ws>_url
should be replaced with self.ws_url
to correctly reference the instance variable. Additionally, ensure that the environment variable LIVEKIT_WS_URL
is set correctly in your .env
file. Here's the corrected code:
from livekit.api.access_token import AccessToken, VideoGrants
from livekit import rtc
import os
from dotenv import load_dotenv
import traceback
load_dotenv()
class RoomManager:
def __init__(self):
self.api_key = os.getenv('LIVEKIT_API_KEY')
self.api_secret = os.getenv('LIVEKIT_API_SECRET')
self.ws_url = os.getenv('LIVEKIT_WS_URL') # Corrected variable name
print(f"Initializing with URL: {self.ws_url}")
def create_token(self, room_name, participant_name):
token = AccessToken(api_key=self.api_key, api_secret=self.api_secret)
token.with_identity(participant_name)
video_grants = VideoGrants(
room=room_name,
room_join=True,
can_publish=True,
can_subscribe=True
)
token.with_grants(video_grants)
return token.to_jwt() # Corrected method call
async def create_and_connect_to_room(self, room_name, participant_name):
try:
print(f"Creating token for room: {room_name}, participant: {participant_name}")
token = self.create_token(room_name, participant_name)
print("Token created successfully")
# Create a new Room instance first
room = rtc.Room()
# Then connect using the instance
await room.connect(
url=self.ws_url, # Corrected variable name
token=token
)
print("Connected to room successfully")
return room, token
except Exception as e:
print(f"Error creating/connecting to room: {e}")
print("Traceback:")
print(traceback.format_exc())
return None, None
async def close(self):
pass
Key Points:
- Ensure that your .env
file contains the correct LIVEKIT_WS_URL
and that it is being loaded properly.
- Replace <http://self.ws|self.ws>_url
with self.ws_url
in the code.
- Verify that the LIVEKIT_WS_URL
is not None
by checking the print statement output.
This should resolve the TypeError
by using the correct URL variable. Let me know if you need further assistance!
Sources:
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1728956116.368569
- https://docs.livekit.io/home/quickstarts/nextjs-12/ 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/16/2025, 2:12 AMgray-monkey-83525
02/16/2025, 2:12 AMCreateRoom
API that you can use to create rooms programmatically. This is part of the RoomService API, which allows you to manage rooms, participants, and tracks. You can use the createRoom
method to create a room with specific settings.
Here's a brief overview of how you can use the CreateRoom
API:
1. API Endpoint: The endpoint for creating a room is /twirp/livekit.RoomService/CreateRoom
.
2. Authorization: You need to include a signed access token in the HTTP header for authorization.
3. Parameters: You can specify parameters such as the room name, maximum participants, and metadata.
Here's an example of how you might call this API using a server SDK:
from livekit import RoomServiceClient
# Initialize the RoomServiceClient with your LiveKit server URL and API credentials
client = RoomServiceClient('https://your-livekit-server-url', 'api-key', 'api-secret')
# Create a room with specific options
room_options = {
'name': 'my-new-room',
'empty_timeout': 600, # in seconds
'max_participants': 10,
'metadata': 'Initial room metadata'
}
# Call the createRoom method
room = client.createRoom(room_options)
print(f"Room created: {room.name}")
Would you like more details on how to implement this?
Sources:
- Server APIs | LiveKit Docs 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/16/2025, 2:13 AMgray-monkey-83525
02/16/2025, 2:13 AMcurl
, you can make a POST request to the /twirp/livekit.RoomService/CreateRoom
endpoint. You'll need to include an authorization token in the request header. Here's an example of how you can do this:
curl -X POST https://your-livekit-server-url/twirp/livekit.RoomService/CreateRoom \
-H "Authorization: Bearer <your-access-token>" \
-H 'Content-Type: application/json' \
-d '{
"name": "my-new-room",
"empty_timeout": 600,
"max_participants": 10,
"metadata": "Initial room metadata"
}'
Key Points:
- Authorization: Replace <your-access-token>
with a valid access token that has the roomCreate
permission.
- URL: Replace https://your-livekit-server-url
with your actual LiveKit server URL.
- Parameters: Adjust the JSON payload to set the room name, empty timeout, maximum participants, and any metadata you want to include.
Would you like more details on generating the access token or any other part of this process?
Sources:
- Server APIs | LiveKit Docs 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/16/2025, 2:14 AMgray-monkey-83525
02/16/2025, 2:14 AMv1/rooms/rs-[company]-[room-id]
, does not appear to be part of the LiveKit API as per the available documentation. The correct endpoint for creating a room using LiveKit's API is /twirp/livekit.RoomService/CreateRoom
, which is accessed via a POST request.
If you are trying to use a different API or service, please ensure that you are referencing the correct documentation for that service. For LiveKit, you should use the /twirp/livekit.RoomService/CreateRoom
endpoint as described in the LiveKit Server APIs documentation.
Would you like more details on how to use the LiveKit API for room management?
Sources:
- Server APIs | LiveKit Docs 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/16/2025, 2:16 AMgray-monkey-83525
02/16/2025, 2:16 AMroomCreate
permission. You can generate the token using the AccessToken
class from the LiveKit SDK.
2. Token Format: Verify that the token is in the correct format (JWT) and is not expired. Tokens typically have a time-to-live (TTL) and will expire after a certain period.
3. Authorization Header: Make sure the token is included in the Authorization
header of your request as a Bearer token. The header should look like this:
Authorization: Bearer <your-access-token>
4. API Key and Secret: Double-check that the API key and secret used to generate the token are correct and match those configured on your LiveKit server.
Here's an example of how to generate a token with the necessary permissions:
from livekit.api.access_token import AccessToken, VideoGrants
def generate_token(api_key, api_secret, room_name):
token = AccessToken(api_key=api_key, api_secret=api_secret)
video_grants = VideoGrants(room_create=True)
token.with_grants(video_grants)
return token.to_jwt()
If you need further assistance, please let me know!
Sources:
- Server APIs | LiveKit Docs 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/16/2025, 2:17 AMtall-mechanic-24834
02/16/2025, 2:17 AMgray-monkey-83525
02/16/2025, 2:17 AMroomCreate
for creating rooms.
2. Use Access Token: Include the generated access token in the Authorization
header of your API request as a Bearer token.
Here's an example of generating an access token with the roomCreate
permission:
from livekit.api.access_token import AccessToken, VideoGrants
def generate_access_token(api_key, api_secret):
token = AccessToken(api_key=api_key, api_secret=api_secret)
video_grants = VideoGrants(room_create=True)
token.with_grants(video_grants)
return token.to_jwt()
Would you like more details on generating and using access tokens?
Sources:
- Authentication | LiveKit Docs 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/16/2025, 2:18 AMgray-monkey-83525
02/16/2025, 2:18 AMcurl
, you would typically need a backend service to create the token using your API key and secret, as the token generation involves signing the token with your API secret, which should not be exposed on the client side.
However, if you want to simulate this process locally or in a secure environment, you can use a script to generate the token and then use curl
to make requests with it. Here's a basic example of how you might generate a token using Python and then use it with `curl`:
Step 1: Generate the Access Token with Python
from livekit.api.access_token import AccessToken, VideoGrants
def generate_access_token(api_key, api_secret, room_name):
token = AccessToken(api_key=api_key, api_secret=api_secret)
video_grants = VideoGrants(room_create=True)
token.with_grants(video_grants)
return token.to_jwt()
# Replace with your actual API key and secret
api_key = 'your_api_key'
api_secret = 'your_api_secret'
room_name = 'my-room'
access_token = generate_access_token(api_key, api_secret, room_name)
print(access_token)
Step 2: Use the Access Token with curl
Once you have the access token, you can use it in a curl
command like this:
curl -X POST https://your-livekit-server-url/twirp/livekit.RoomService/CreateRoom \
-H "Authorization: Bearer <your-access-token>" \
-H 'Content-Type: application/json' \
-d '{
"name": "my-new-room",
"empty_timeout": 600,
"max_participants": 10,
"metadata": "Initial room metadata"
}'
Key Points:
- Security: Ensure that the API key and secret are kept secure and not exposed to the client side.
- Backend Service: Ideally, the token generation should be handled by a backend service that your client can request a token from.
Would you like more details on setting up a backend service for token generation?
Sources:
- https://livekit-users.slack.com/archives/C07FYCB7FRQ/p1728399936.393609
- https://docs.livekit.io/home/quickstarts/nextjs-12/ 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 4:20 AMgray-monkey-83525
02/17/2025, 4:20 AMVoicePipelineAgent
to integrate STT, TTS, and other functionalities. Here's a brief example of how you might set up an agent with plugins:
from livekit.agents import VoicePipelineAgent
from livekit.plugins import deepgram, cartesia, silero
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
tts=cartesia.TTS()
)
# Start the agent in a room
agent.start(room, participant)
If you want to make API calls to manage these plugins, you would typically do so through the agent's setup and configuration, rather than direct API calls to the plugins themselves.
Would you like more details on setting up agents with plugins?
Sources:
- https://docs.livekit.io/agents/plugins/#VAD-and-StreamAdapter
- https://livekit-users.slack.com/archives/C07FRP66XGE/p1731298782.627559 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.gray-monkey-83525
02/17/2025, 4:22 AMtall-mechanic-24834
02/17/2025, 4:24 AMgray-monkey-83525
02/17/2025, 4:24 AMfrom livekit.agents import VoicePipelineAgent
from livekit.plugins import cartesia, deepgram, google, silero
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
llm=google.LLM(),
tts=cartesia.TTS()
)
2. Backend Deployment: Deploy your agent on a server that can communicate with LiveKit Cloud. This server will handle the agent's lifecycle and interactions with LiveKit rooms.
3. Frontend Integration: On your frontend (e.g., Bubble.io), you need to establish a connection to the LiveKit room where the agent is running. This typically involves:
- Generating an access token for the frontend participant.
- Using LiveKit's SDKs to connect to the room and interact with the agent.
4. Communication: Ensure that your frontend can send and receive audio/video streams to/from the LiveKit room. The agent will process these streams using the configured plugins.
5. Testing and Iteration: Test the integration thoroughly to ensure that the agent behaves as expected and that the frontend can interact with it seamlessly.
Would you like more details on any specific part of this process?
Sources:
- https://livekit-users.slack.com/archives/C048FRL1N2C/p1728484288.395119 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 4:30 AMgray-monkey-83525
02/17/2025, 4:30 AMtall-mechanic-24834
02/17/2025, 4:36 AMgray-monkey-83525
02/17/2025, 4:36 AMfrom livekit.agents import VoicePipelineAgent
from livekit.plugins import cartesia, deepgram, google, silero
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
llm=google.LLM(),
tts=cartesia.TTS()
)
2. Deploy the Agent: Run the agent on a server that can connect to LiveKit. This server will handle the agent's lifecycle and interactions with the LiveKit room.
3. Generate Access Token: Create an access token for the agent to join the room. This token should include the necessary permissions for the agent to publish and subscribe to media tracks.
from livekit.api.access_token import AccessToken, VideoGrants
def generate_access_token(api_key, api_secret, room_name):
token = AccessToken(api_key=api_key, api_secret=api_secret)
video_grants = VideoGrants(room_join=True, can_publish=True, can_subscribe=True)
token.with_grants(video_grants)
return token.to_jwt()
4. Connect the Agent to the Room: Use the generated token to connect the agent to the LiveKit room. The agent will join as a participant and can interact with other participants in the room.
room = rtc.Room()
await room.connect(
url='wss://your-livekit-server-url',
token=generate_access_token(api_key, api_secret, 'room-name')
)
5. Frontend Integration: On the frontend, use LiveKit's SDKs to connect to the same room. The frontend can interact with the agent by sending and receiving audio/video streams.
By following these steps, you can integrate an agent into a LiveKit call, allowing it to participate as a conversational AI or perform other tasks.
Would you like more details on any specific part of this process?
Sources:
- https://docs.livekit.io/agents/openai/client-apps/
- https://livekit-users.slack.com/archives/C07FVFM5NA1/p1729608787.477739 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 4:38 AMgray-monkey-83525
02/17/2025, 4:38 AMtall-mechanic-24834
02/17/2025, 12:49 PMgray-monkey-83525
02/17/2025, 12:49 PMfrom livekit.agents import VoicePipelineAgent
from livekit.plugins import cartesia, deepgram, google, silero
from livekit import rtc
# Define the initial context for the agent
initial_ctx = {
"role": "system",
"text": "You are a professional customer service assistant."
}
# Create the agent with the necessary plugins
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
llm=google.LLM(),
tts=cartesia.TTS(),
chat_ctx=initial_ctx
)
# Function to connect the agent to a room
async def connect_agent_to_room(room_name, token, ws_url):
room = rtc.Room()
await room.connect(
url=ws_url,
token=token
)
agent.start(room)
# Example usage
# You need to generate a token with the necessary permissions
# and provide the WebSocket URL of your LiveKit server
# connect_agent_to_room('room-name', 'your-access-token', 'wss://your-livekit-server-url')
Key Steps:
1. Initialize Plugins: Set up the agent with plugins for VAD, STT, LLM, and TTS.
2. Create Agent: Use the VoicePipelineAgent
class to create an agent with the desired configuration.
3. Connect to Room: Use the rtc.Room
class to connect the agent to a LiveKit room using a valid access token and WebSocket URL.
Documentation
For more detailed information, you can refer to the LiveKit Agents Overview and the LiveKit Plugins Documentation.
Would you like more details on any specific part of this process?
Sources:
- LiveKit Agents Overview 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 12:58 PMagent_name
set can be explicitly dispatched to a room via AgentDispatchService
.
import asyncio
from livekit import api
room_name = "my-room"
agent_name = "test-agent"
async def create_explicit_dispatch():
lkapi = api.LiveKitAPI()
dispatch = await lkapi.agent_dispatch.create_dispatch(
api.CreateAgentDispatchRequest(
agent_name=agent_name, room=room_name, metadata="my_job_metadata"
)
)
print("created dispatch", dispatch)
dispatches = await lkapi.agent_dispatch.list_dispatch(room_name=room_name)
print(f"there are {len(dispatches)} dispatches in {room_name}")
await lkapi.aclose()
asyncio.run(create_explicit_dispatch())
If
my-room
does not exist, it is created automatically during dispatch, and an instance of
t`est-agent`
is assigned to it.
Would it be more effecient to not create rooms but run this have agent and room automatically created and it return data via api?gray-monkey-83525
02/17/2025, 12:58 PMAgentDispatchService
to automatically create rooms and dispatch agents can be an efficient approach, especially if you want to streamline the process of setting up rooms and assigning agents without manually managing room creation. Here's why this method can be beneficial:
1. Automatic Room Creation: If the specified room does not exist, it is automatically created during the dispatch process. This reduces the need for separate room management logic in your application.
2. Efficient Agent Assignment: By using AgentDispatchService
, you can explicitly control which agents are dispatched to which rooms, allowing for more precise management of agent resources.
3. Simplified Workflow: This approach simplifies the workflow by combining room creation and agent dispatch into a single step, reducing the complexity of your application logic.
4. Scalability: Automatically managing rooms and agents can help scale your application more effectively, as it reduces the overhead of manually handling these operations.
Here's a brief example of how you might use this approach:
import asyncio
from livekit import api
room_name = "my-room"
agent_name = "test-agent"
async def create_explicit_dispatch():
lkapi = api.LiveKitAPI()
dispatch = await lkapi.agent_dispatch.create_dispatch(
api.CreateAgentDispatchRequest(
agent_name=agent_name, room=room_name, metadata="my_job_metadata"
)
)
print("created dispatch", dispatch)
dispatches = await lkapi.agent_dispatch.list_dispatch(room_name=room_name)
print(f"there are {len(dispatches)} dispatches in {room_name}")
await lkapi.aclose()
asyncio.run(create_explicit_dispatch())
Considerations:
- Resource Management: Ensure that your application can handle the automatic creation of rooms and agents, especially in terms of resource allocation and cost.
- Use Case Suitability: This approach is suitable if your application benefits from dynamic room and agent management. If you need more control over room configurations, you might still want to manage rooms separately.
Would you like more details on implementing this approach?
Sources:
- Dispatching Agents | LiveKit Docs 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 12:59 PMgray-monkey-83525
02/17/2025, 12:59 PMVoicePipelineAgent
class to integrate these components.
2. Customize the Agent: Use the appropriate plugins for each functionality. For example, use Google for LLM, Deepgram for STT, and Cartesia for TTS.
3. Dispatch the Agent: Use the AgentDispatchService
to dispatch the customized agent to a room.
Here's an example of how you might configure and dispatch a customized agent:
from livekit.agents import VoicePipelineAgent
from livekit.plugins import cartesia, deepgram, google, silero
from livekit import api
# Define the initial context for the agent
initial_ctx = {
"role": "system",
"text": "You are a professional assistant with vision capabilities."
}
# Create the agent with the necessary plugins
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
llm=google.LLM(),
tts=cartesia.TTS(),
chat_ctx=initial_ctx
)
# Function to dispatch the agent to a room
async def create_explicit_dispatch():
lkapi = api.LiveKitAPI()
dispatch = await lkapi.agent_dispatch.create_dispatch(
api.CreateAgentDispatchRequest(
agent_name="custom-agent", room="my-room", metadata="my_job_metadata"
)
)
print("created dispatch", dispatch)
dispatches = await lkapi.agent_dispatch.list_dispatch(room_name="my-room")
print(f"there are {len(dispatches)} dispatches in my-room")
await lkapi.aclose()
# Run the dispatch function
import asyncio
asyncio.run(create_explicit_dispatch())
Key Points:
- Plugin Configuration: Ensure each plugin is correctly configured with any necessary API keys or settings.
- Agent Name: Use a unique agent_name
to identify and manage your customized agent.
- Room Management: The room is automatically created if it doesn't exist, and the agent is dispatched to it.
This setup allows you to customize the agent's capabilities and dispatch it to a room using LiveKit's infrastructure.
Would you like more details on any specific part of this process?
Sources:
- Dispatching Agents | LiveKit Docs 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 1:07 PMgray-monkey-83525
02/17/2025, 1:07 PM<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
This script tag will load the LiveKit client SDK into your application, and you can access it via the LivekitClient
global object. For example, you can create a room using LivekitClient.Room
.
Example Usage:
<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
<script>
const room = new LivekitClient.Room();
// Use the room object to connect and manage your LiveKit room
</script>
This approach allows you to quickly integrate LiveKit into your web application without the need for additional build tools or package management.
Would you like more details on using the LiveKit client SDK?
Sources:
- LiveKit JS Client SDK Documentation 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 1:47 PMgray-monkey-83525
02/17/2025, 1:47 PMtall-mechanic-24834
02/17/2025, 1:51 PMgray-monkey-83525
02/17/2025, 1:51 PMLiveKitClient
.
<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
2. Check Script Loading Order: Ensure that the script tag is placed before your custom JavaScript code that initializes or uses LiveKitClient
. This ensures that the library is loaded and available when your code runs.
3. Verify Network Access: Ensure that your application has network access to load the script from the CDN. Check for any network errors in the browser's developer console that might indicate issues with loading the script.
4. Check for JavaScript Errors: Look for any other JavaScript errors in the console that might prevent the script from executing correctly.
5. Test in Isolation: Try creating a simple HTML file with just the script tag and a basic initialization of LiveKitClient
to verify that the library loads correctly:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LiveKit Test</title>
<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
</head>
<body>
<script>
if (typeof LivekitClient !== 'undefined') {
console.log('LiveKitClient is loaded');
const room = new LivekitClient.Room();
console.log('Room created:', room);
} else {
console.error('LiveKitClient is not defined');
}
</script>
</body>
</html>
If the issue persists, it might be related to how your environment or platform (e.g., Bubble.io) handles external scripts. In such cases, you may need to consult the platform's documentation or support for guidance on including external libraries.
Would you like more details on any specific part of this process?
Sources:
- https://docs.livekit.io/client-sdk-js/
- https://docs.livekit.io/client-sdk-js/index.html 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 1:52 PMgray-monkey-83525
02/17/2025, 1:52 PMtall-mechanic-24834
02/17/2025, 1:53 PMgray-monkey-83525
02/17/2025, 1:53 PMe2ee
option in the room configuration to enable encryption. You will also need to manage the encryption keys and ensure they are securely exchanged between participants.
Here's an example of how you might set up E2EE:
function(instance, properties, context) {
const wsUrl = 'wss://connect.roleshape.com'; // Your fixed WebSocket URL
const token = properties.token; // The JWT token from your properties
const roomOptions = {
e2ee: {
enabled: true,
keyProvider: {
// Implement your key exchange mechanism here
getKey: async (participantId) => {
// Return the encryption key for the participant
}
}
}
};
// Create the room instance with E2EE enabled
const room = new LiveKitClient.Room(roomOptions);
// Connect to the room
room.connect(wsUrl, token).then(() => {
console.log('Connected to room with E2EE');
instance.publishState('isConnected', true); // Update state if connected
}).catch((error) => {
console.error('Error connecting to room:', error);
instance.publishState('isConnected', false); // Update state if connection fails
});
// Store the room instance for later use
instance.data.room = room;
}
Key Points:
- Key Management: Implement a secure key exchange mechanism to provide encryption keys to participants. This is crucial for maintaining the security of E2EE.
- Testing: Test the E2EE setup thoroughly to ensure that encryption and decryption are working correctly for all participants.
Would you like more details on implementing the key exchange mechanism or any other part of this process?
Sources:
- https://livekit-users.slack.com/archives/C07FVFGAUKX/p1728910196.473049
- https://livekit-users.slack.com/archives/C07FYCB7FRQ/p1728354754.401459 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 1:56 PMgray-monkey-83525
02/17/2025, 1:56 PMtall-mechanic-24834
02/17/2025, 1:59 PMgray-monkey-83525
02/17/2025, 2:00 PMtall-mechanic-24834
02/17/2025, 2:02 PMgray-monkey-83525
02/17/2025, 2:02 PMroomOptions
parameter in LiveKit is used to configure various settings and behaviors for a room when a participant connects. It allows you to customize aspects such as video and audio capture, publishing options, adaptive streaming, and more.
Key Properties of `RoomOptions`:
1. Adaptive Stream: Automatically manages the quality of subscribed video tracks to optimize for bandwidth and CPU usage. It adjusts the resolution based on the size of the video element.
2. Dynacast: Enables dynamic broadcasting, which pauses video layers that are not being consumed by any subscribers, reducing CPU and bandwidth usage.
3. Audio and Video Options: Configure default options for capturing and publishing audio and video, such as enabling/disabling echo cancellation, noise suppression, and setting video resolutions.
4. End-to-End Encryption (E2EE): Options for enabling and configuring E2EE for secure media transmission.
5. Stop Local Track on Unpublish: Determines whether local tracks should be stopped when they are unpublished.
Example Usage:
const roomOptions = {
adaptiveStream: true,
dynacast: true,
defaultAudioCaptureOptions: {
echoCancellation: true,
noiseSuppression: true
},
defaultVideoPublishOptions: {
resolution: { width: 1280, height: 720 }
}
};
const room = new LiveKitClient.Room(roomOptions);
This configuration allows you to tailor the room's behavior to meet the specific needs of your application, optimizing performance and resource usage.
Would you like more details on any specific property of RoomOptions
?
Sources:
- RoomOptions Class - LiveKit Client SDK Flutter
- RoomOptions Interface - LiveKit JS Client SDK 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 2:08 PMgray-monkey-83525
02/17/2025, 2:08 PMroomOptions
are defined when a participant is joining a room, rather than during the initial creation of the room. The roomOptions
are used to configure the participant's connection settings, such as media capture and publishing options, adaptive streaming, and encryption, which are specific to the participant's session.
Key Points:
1. Joining a Room: When a participant connects to a room, they can specify roomOptions
to customize their connection. This includes settings for audio and video capture, adaptive streaming, and other participant-specific configurations.
2. Room Creation: The initial creation of a room typically involves setting up server-side configurations, such as room name, maximum participants, and other server-managed settings. roomOptions
are not typically involved in this process.
Example Usage:
When a participant joins a room, they can specify roomOptions
like this:
const roomOptions = {
adaptiveStream: true,
dynacast: true,
defaultAudioCaptureOptions: {
echoCancellation: true,
noiseSuppression: true
}
};
const room = new LiveKitClient.Room(roomOptions);
room.connect(wsUrl, token).then(() => {
console.log('Connected to room with custom options');
});
This setup allows each participant to have a tailored experience based on their device capabilities and network conditions.
Would you like more details on configuring roomOptions
?
Sources:
- RoomOptions Interface - LiveKit JS Client SDK 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 2:10 PMgray-monkey-83525
02/17/2025, 2:10 PMroomOptions
. Here are a few points to consider:
1. WebSocket URL and Token: Ensure that the wsUrl
and token
are correctly set and valid. The WebSocket URL should point to your LiveKit server, and the token should be a valid JWT with the necessary permissions.
2. Room Options: The roomOptions
you have set are appropriate for enabling adaptive streaming and Dynacast, which optimize resource usage by adjusting video quality based on network conditions and pausing unused video layers.
3. Error Handling: The catch
block is correctly set up to handle connection errors and update the state accordingly.
4. Disconnect on Page Leave: The disconnectOnPageLeave
option is a good practice to ensure that the participant is disconnected when they navigate away from the page, freeing up resources.
5. HTML Entity: Ensure that the >
and <
are replaced with >
and <
in your actual code, as these are HTML entities used in text representation.
Here's a slightly refined version of your code:
function(instance, properties, context) {
const wsUrl = 'wss://connect.roleshape.com'; // Your fixed WebSocket URL
const token = properties.token; // The JWT token from your properties
// Room options defined for joining the room
const roomOptions = {
adaptiveStream: true, // Enable adaptive streaming
dynacast: true, // Enable Dynacast to optimize resource usage
disconnectOnPageLeave: true // Automatically disconnect when the page is left
};
// Create the room instance
const room = new LiveKitClient.Room(roomOptions);
// Connect to the room with these options
room.connect(wsUrl, token).then(() => {
console.log('Connected to room with adaptive stream and dynacast enabled');
instance.publishState('isConnected', true); // Update state if connected
}).catch((error) => {
console.error('Error connecting to room:', error);
instance.publishState('isConnected', false); // Update state if connection fails
});
// Store the room instance for later use
instance.data.room = room;
}
This setup should work as expected, provided that the WebSocket URL and token are valid. If you encounter any issues, double-check the server configuration and token generation.
Would you like more details on any specific part of this process?
Sources:
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1728956116.368569
- https://runllm.slack.com/archives/C080YTD3YRZ/p1733463132.499869 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 2:22 PMgray-monkey-83525
02/17/2025, 2:22 PMfrom livekit.agents import VoicePipelineAgent
from livekit.plugins import deepgram, cartesia, silero
# Example of integrating a custom vision model
def process_video_frame(frame):
# Your vision model processing logic here
pass
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
tts=cartesia.TTS(),
# Add your vision processing logic
vision_callback=process_video_frame
)
Key Points:
- Flexibility: You can choose any vision model or service that fits your needs.
- Integration: Ensure that the vision processing logic is integrated into the agent's workflow, typically by processing video frames as they are received.
Would you like more details on integrating specific vision models or services?
Sources:
- LiveKit Agents Overview 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 2:23 PMgray-monkey-83525
02/17/2025, 2:23 PMgray-monkey-83525
02/17/2025, 2:24 PMimport os
import uuid
import asyncio
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from livekit.api.access_token import AccessToken, VideoGrants
from livekit import api
from livekit.agents import VoicePipelineAgent
from livekit.plugins import cartesia, deepgram, google, silero
from dotenv import load_dotenv
load_dotenv()
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Custom vision processing function
def process_video_frame(frame):
# Implement your vision processing logic here
pass
@app.post("/create-call")
async def create_call(user_name: str):
try:
api_key = os.getenv('LIVEKIT_API_KEY')
api_secret = os.getenv('LIVEKIT_API_SECRET')
# Create unique room name with RS prefix and UUID
room_name = f"rs-{str(uuid.uuid4())}"
# Create a token for the user
token = AccessToken(api_key, api_secret)
token.with_identity(user_name)
grant = VideoGrants(
room=room_name,
room_join=True,
can_publish=True,
can_subscribe=True
)
token.with_grants(grant)
# Define the initial context for the agent
initial_ctx = {
"role": "system",
"text": "You are a professional assistant with vision capabilities."
}
# Create the agent with the necessary plugins
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
llm=google.LLM(),
tts=cartesia.TTS(),
chat_ctx=initial_ctx,
vision_callback=process_video_frame # Add vision processing
)
# Dispatch the agent
async def dispatch_agent():
lkapi = api.LiveKitAPI()
await lkapi.agent_dispatch.create_dispatch(
api.CreateAgentDispatchRequest(
agent_name="agent",
room=room_name,
metadata="Dispatch metadata related to the task"
)
)
dispatches = await lkapi.agent_dispatch.list_dispatch(room=room_name)
print(f"there are {len(dispatches)} dispatches in {room_name}")
await lkapi.aclose()
await dispatch_agent()
return {
"room_name": room_name,
"token": token.to_jwt()
}
except Exception as e:
return {"error": str(e)}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
gray-monkey-83525
02/17/2025, 2:24 PMprocess_video_frame
function.
- Integration: Add the vision_callback
parameter to the VoicePipelineAgent
to integrate the vision processing function.
This setup allows you to process video frames using your custom logic or a third-party service.
Would you like more details on implementing specific vision processing logic?
Sources:
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1730233417.503479
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1728470919.983699 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 2:39 PMgray-monkey-83525
02/17/2025, 2:39 PMrequirements.txt
file looks like it includes the essential packages for setting up a FastAPI application with LiveKit integration. However, depending on the specific plugins and functionalities you are using, you might need to include additional packages. Here's an example of what your requirements.txt
might look like, including some common plugins and tools:
fastapi
uvicorn
python-dotenv
livekit
livekit-api
livekit-agents
livekit-plugins-cartesia
livekit-plugins-deepgram
livekit-plugins-google
livekit-plugins-silero
Explanation:
- fastapi: The web framework for building your API.
- uvicorn: An ASGI server for running your FastAPI application.
- python-dotenv: For loading environment variables from a .env
file.
- livekit: The core LiveKit package.
- livekit-api: Provides API functionalities for LiveKit.
- livekit-agents: For creating and managing agents in LiveKit.
- livekit-plugins-cartesia, livekit-plugins-deepgram, livekit-plugins-google, livekit-plugins-silero: These are plugins for TTS, STT, LLM, and VAD functionalities, respectively. Include the ones you are using in your application.
Additional Considerations:
- Versioning: You might want to specify versions for each package to ensure compatibility and stability.
- Dependencies: Ensure that all dependencies for the plugins you are using are also included.
Would you like more details on any specific package or functionality? 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 2:41 PMgray-monkey-83525
02/17/2025, 2:41 PMlivekit-agents
package is not installed in your Python environment. To resolve this issue, you need to ensure that the package is installed correctly.
Steps to Resolve:
1. Install the Package: Make sure you have livekit-agents
installed. You can install it using pip:
pip install livekit-agents
2. Check Your Environment: Ensure that you are installing the package in the correct Python environment. If you are using a virtual environment, activate it before running the pip install command.
3. Verify Installation: After installation, verify that the package is installed by listing the installed packages:
pip list | grep livekit-agents
4. Check Python Path: Ensure that your Python script is running in the environment where livekit-agents
is installed. You can check the Python path in your script to confirm:
import sys
print(sys.path)
5. Restart Your Application: If you are running a server or application, restart it to ensure that the changes take effect.
If you continue to experience issues, double-check that there are no typos in the import statement and that the package is compatible with your Python version.
Would you like more details on setting up your environment or troubleshooting this issue further?
Sources:
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1733379670.713629
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1730293289.619029 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 3:39 PMgray-monkey-83525
02/17/2025, 3:39 PMcore
directory is correctly structured and accessible, and ensure that the EnhancedAgent
module is properly defined within it. If this doesn't help, please reach out to the Livekit support team for further assistance. 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 5:51 PMgray-monkey-83525
02/17/2025, 5:51 PMreturn {
"room_name": room_name,
"token": token.to_jwt(), # Ensure this is correctly formatted
"config": {
"video_enabled": True,
"audio_enabled": True
}
}
2. String Formatting: Check for any string formatting issues, especially in the create_dynamic_context
function. Ensure that all variables are correctly formatted and concatenated.
3. Environment Variables: Double-check that all environment variables are correctly set and accessible. Missing or incorrectly formatted environment variables can lead to type errors.
4. Function Calls: Review any function calls, especially those involving external libraries or APIs, to ensure that the arguments being passed are of the expected types.
5. Logging: Add additional logging to pinpoint where the error occurs. This can help identify which operation is causing the type error.
6. Check Imports and Dependencies: Ensure that all necessary packages are installed and correctly imported. Sometimes, missing or outdated packages can lead to unexpected errors.
If the issue persists, consider isolating parts of the code to identify the specific operation causing the error. This can help narrow down the problem and find a solution.
Would you like more details on any specific part of this process?
Sources:
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1730233417.503479
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1729785405.894609 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 8:40 PMgray-monkey-83525
02/17/2025, 8:40 PMCreateAgentDispatchRequest
is correctly structured. Ensure that all fields are populated with the expected data types.
4. Token Generation: Ensure that the token is generated and used correctly. The token.to_jwt()
method should return a valid JWT string.
5. Logging and Debugging: Add additional logging to identify the specific operation or function call causing the error. This can help pinpoint the issue and provide more context for debugging.
6. Dependencies and Imports: Ensure that all necessary packages are installed and correctly imported. Sometimes, missing or outdated packages can lead to unexpected errors.
7. Function Calls: Review any function calls, especially those involving external libraries or APIs, to ensure that the arguments being passed are of the expected types.
If the issue persists, consider isolating parts of the code to identify the specific operation causing the error. This can help narrow down the problem and find a solution.
Would you like more details on any specific part of this process?
Sources:
- https://livekit-users.slack.com/archives/C07FY8WHGPM/p1730673248.486419 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.tall-mechanic-24834
02/17/2025, 8:41 PMgray-monkey-83525
02/17/2025, 8:41 PMtall-mechanic-24834
02/17/2025, 8:43 PMgray-monkey-83525
02/17/2025, 8:43 PMgray-monkey-83525
02/17/2025, 8:43 PMimport os
import uuid
import logging
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from livekit.api.access_token import AccessToken, VideoGrants
from livekit import api
from livekit.agents import llm
from livekit.agents.voice_assistant import VoiceAssistant
from livekit.plugins import cartesia, deepgram, google, silero
from pydantic import BaseModel, Field
from typing import Optional, List
from dotenv import load_dotenv
# Enhanced logging configuration
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
load_dotenv()
def verify_env_variables():
env_vars = {
'LIVEKIT_API_KEY': os.getenv('LIVEKIT_API_KEY'),
'LIVEKIT_API_SECRET': os.getenv('LIVEKIT_API_SECRET'),
'LIVEKIT_WS_URL': os.getenv('LIVEKIT_WS_URL'),
'DEEPGRAM_API_KEY': os.getenv('DEEPGRAM_API_KEY'),
'GOOGLE_API_KEY': os.getenv('GOOGLE_API_KEY'),
'CARTESIA_API_KEY': os.getenv('CARTESIA_API_KEY'),
'GOOGLE_APPLICATION_CREDENTIALS': os.getenv('GOOGLE_APPLICATION_CREDENTIALS'),
}
missing = [k for k, v in env_vars.items() if not v]
if missing:
logger.error(f"Missing environment variables: {', '.join(missing)}")
raise ValueError(f"Missing environment variables: {', '.join(missing)}")
<http://logger.info|logger.info>(f"Environment variables verified: {env_vars.keys()}")
return env_vars
class CustomerProfile(BaseModel):
industry: str
company_size: str
pain_points: List[str]
budget_range: str
technical_expertise: str
communication_style: str
personality_traits: List[str]
decision_making_process: str
typical_objections: List[str]
success_metrics: List[str]
class ScenarioConfig(BaseModel):
difficulty_level: str
scenario_type: str
specific_challenges: List[str] = []
success_criteria: List[str] = []
conversation_phase: Optional[str] = None
class TrainingRequest(BaseModel):
user_name: str
customer_profile: CustomerProfile
scenario_config: ScenarioConfig
additional_context: Optional[str] = None
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
def create_dynamic_context(request: TrainingRequest) -> str:
profile = request.customer_profile
scenario = request.scenario_config
return f"""Training session for {request.user_name}
Industry: {profile.industry}
Scenario: {scenario.scenario_type}
Difficulty: {scenario.difficulty_level}"""
@app.post("/create-training-session")
async def create_training_session(request: TrainingRequest):
lkapi = None
try:
# Verify environment variables
env_vars = verify_env_variables()
logger.debug("Environment variables verified")
# Create room name
room_name = f"training-{str(uuid.uuid4())}"
gray-monkey-83525
02/17/2025, 8:43 PMlogger.debug(f"Created room: {room_name}")
# Create token
token = AccessToken(
env_vars['LIVEKIT_API_KEY'],
env_vars['LIVEKIT_API_SECRET']
)
token.with_identity(str(request.user_name))
token.with_grants(VideoGrants(
room=str(room_name),
room_join=True,
can_publish=True,
can_subscribe=True
))
logger.debug("Token created successfully")
# Create basic assistant
initial_ctx = llm.ChatContext().append(
role="system",
text=create_dynamic_context(request)
)
logger.debug("Context created successfully")
assistant = VoiceAssistant(
vad=silero.VAD.load(),
stt=deepgram.STT(),
llm=google.LLM(api_key=env_vars['GOOGLE_API_KEY']),
tts=cartesia.TTS(api_key=env_vars['CARTESIA_API_KEY']),
chat_ctx=initial_ctx
)
logger.debug("Assistant created successfully")
# Dispatch agent
try:
lkapi = api.LiveKitAPI(
url=env_vars['LIVEKIT_WS_URL'],
api_key=env_vars['LIVEKIT_API_KEY'],
api_secret=env_vars['LIVEKIT_API_SECRET']
)
# Convert metadata to strings
metadata = {
"video_enabled": "true",
"room_name": room_name,
"user_name": request.user_name,
"scenario_type": request.scenario_config.scenario_type,
"difficulty_level": request.scenario_config.difficulty_level
}
logger.debug(f"Dispatch metadata: {metadata}")
await lkapi.agent_dispatch.create_dispatch(
api.CreateAgentDispatchRequest(
agent_name=room_name,
room=room_name,
metadata=json.dumps(metadata) # Ensure metadata is a JSON string
)
)
logger.debug("Agent dispatched successfully")
except Exception as e:
logger.error(f"Agent dispatch failed: {e}")
raise HTTPException(status_code=500, detail=f"Agent dispatch failed: {str(e)}")
# Create response
response = {
"room_name": room_name,
"token": token.to_jwt(), # Ensure token is returned as a JWT string
"config": {
"video_enabled": True,
"audio_enabled": True,
"scenario_type": request.scenario_config.scenario_type,
"difficulty_level": request.scenario_config.difficulty_level
}
}
logger.debug("Response created successfully")
return response
except Exception as e:
logger.error(f"Training session creation failed: {e}")
raise HTTPException(status_code=500, detail=str(e))
finally:
if lkapi:
try:
await lkapi.aclose()
gray-monkey-83525
02/17/2025, 8:43 PMlogger.debug("LiveKit API connection closed")
except Exception as e:
logger.error(f"Error closing LiveKit API connection: {e}")
@app.get("/health")
async def health_check():
try:
verify_env_variables()
return {
"status": "healthy",
"environment_check": "passed"
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/")
async def root():
return {
"service": "LiveKit Training Assistant",
"status": "running",
"endpoints": [
"/create-training-session",
"/health"
]
}
gray-monkey-83525
02/17/2025, 8:43 PMjson.dumps(metadata)
.
- Token: Ensure that the token is returned as a JWT string using token.to_jwt()
.
- Logging: Ensure that logging statements are correctly formatted and provide useful information.
These changes should help resolve potential issues related to argument types and ensure that the API functions as expected. If you encounter further issues, consider adding more detailed logging to identify the specific operation causing the error.
Sources:
- https://livekit-users.slack.com/archives/C07FRP66XGE/p1728949068.420199
- https://docs.livekit.io/python/livekit/api/access_token.html 👍 0 button 👎 0 button 💡 Hint: Mention @runllm in the thread for followups.