meshagent-livekit 0.0.19__tar.gz → 0.0.21__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of meshagent-livekit might be problematic. Click here for more details.

Files changed (22) hide show
  1. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/CHANGELOG.md +6 -0
  2. {meshagent_livekit-0.0.19/meshagent_livekit.egg-info → meshagent_livekit-0.0.21}/PKG-INFO +10 -10
  3. meshagent_livekit-0.0.21/meshagent/livekit/agents/voice.py +346 -0
  4. meshagent_livekit-0.0.21/meshagent/livekit/version.py +1 -0
  5. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21/meshagent_livekit.egg-info}/PKG-INFO +10 -10
  6. meshagent_livekit-0.0.21/meshagent_livekit.egg-info/requires.txt +13 -0
  7. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/pyproject.toml +9 -9
  8. meshagent_livekit-0.0.19/meshagent/livekit/agents/voice.py +0 -187
  9. meshagent_livekit-0.0.19/meshagent/livekit/version.py +0 -1
  10. meshagent_livekit-0.0.19/meshagent_livekit.egg-info/requires.txt +0 -13
  11. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/LICENSE +0 -0
  12. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/MANIFEST.in +0 -0
  13. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/README.md +0 -0
  14. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent/livekit/__init__.py +0 -0
  15. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent/livekit/agents/transcriber.py +0 -0
  16. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent/livekit/livekit_protocol.py +0 -0
  17. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent/livekit/livekit_protocol_test.py +0 -0
  18. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent/livekit/tools/speech.py +0 -0
  19. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent_livekit.egg-info/SOURCES.txt +0 -0
  20. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent_livekit.egg-info/dependency_links.txt +0 -0
  21. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/meshagent_livekit.egg-info/top_level.txt +0 -0
  22. {meshagent_livekit-0.0.19 → meshagent_livekit-0.0.21}/setup.cfg +0 -0
@@ -1,3 +1,9 @@
1
+ ## [0.0.21]
2
+ - Stability
3
+
4
+ ## [0.0.20]
5
+ - Stability
6
+
1
7
  ## [0.0.19]
2
8
  - Stability
3
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-livekit
3
- Version: 0.0.19
3
+ Version: 0.0.21
4
4
  Summary: Livekit support for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://meshagent.com
@@ -13,13 +13,13 @@ Requires-Dist: pytest~=8.3.5
13
13
  Requires-Dist: pytest-asyncio~=0.26.0
14
14
  Requires-Dist: strip-markdown~=1.3
15
15
  Requires-Dist: livekit-api~=1.0.2
16
- Requires-Dist: livekit-agents~=1.0.11
17
- Requires-Dist: livekit-plugins-openai~=1.0.11
18
- Requires-Dist: livekit-plugins-cartesia~=1.0.11
19
- Requires-Dist: livekit-plugins-elevenlabs~=1.0.11
20
- Requires-Dist: livekit-plugins-playai~=1.0.11
21
- Requires-Dist: livekit-plugins-silero~=1.0.11
22
- Requires-Dist: livekit-plugins-turn-detector~=1.0.11
23
- Requires-Dist: meshagent-api~=0.0.19
24
- Requires-Dist: meshagent-tools~=0.0.19
16
+ Requires-Dist: livekit-agents~=1.0.19
17
+ Requires-Dist: livekit-plugins-openai~=1.0.19
18
+ Requires-Dist: livekit-plugins-cartesia~=1.0.19
19
+ Requires-Dist: livekit-plugins-elevenlabs~=1.0.19
20
+ Requires-Dist: livekit-plugins-playai~=1.0.19
21
+ Requires-Dist: livekit-plugins-silero~=1.0.19
22
+ Requires-Dist: livekit-plugins-turn-detector~=1.0.19
23
+ Requires-Dist: meshagent-api~=0.0.21
24
+ Requires-Dist: meshagent-tools~=0.0.21
25
25
  Dynamic: license-file
@@ -0,0 +1,346 @@
1
+ import logging
2
+ import asyncio
3
+
4
+ from meshagent.api import RoomMessage, ErrorResponse, JsonResponse, FileResponse, Requirement, Participant, JsonResponse, EmptyResponse, TextResponse
5
+ from meshagent.api.room_server_client import RoomClient
6
+
7
+ from meshagent.agents import ToolResponseAdapter
8
+ from meshagent.tools import ToolContext, Toolkit
9
+ from livekit.agents import Agent, AgentSession
10
+ from livekit.agents.llm import RawFunctionTool, ToolError, function_tool
11
+
12
+ from livekit.agents import BackgroundAudioPlayer, AudioConfig, BuiltinAudioClip
13
+
14
+ from typing import Annotated
15
+ from livekit.plugins import openai, silero
16
+ #from livekit.plugins.turn_detector.multilingual import MultilingualModel
17
+ import uuid
18
+ import asyncio
19
+ import logging
20
+
21
+ import os
22
+
23
+ import json
24
+
25
+ from typing import Any
26
+
27
+ from livekit.plugins import openai
28
+
29
+ from livekit.plugins import openai, silero
30
+ from livekit import rtc
31
+ from livekit.agents import Agent, AgentSession, RunContext
32
+
33
+ from typing import Optional
34
+
35
+ from copy import deepcopy
36
+
37
+ from meshagent.api.schema_util import merge, prompt_schema
38
+
39
+ from meshagent.agents import SingleRoomAgent
40
+
41
+ from livekit.plugins.turn_detector.multilingual import MultilingualModel
42
+
43
+ import re
44
+
45
+ logger = logging.getLogger("voice")
46
+
47
+
48
+ def _replace_non_matching(text: str, allowed_chars: str, replacement: str) -> str:
49
+ """
50
+ Replaces every character in `text` that does not match the given
51
+ `allowed_chars` regex set with `replacement`.
52
+
53
+ Parameters:
54
+ -----------
55
+ text : str
56
+ The input string on which the replacement is to be done.
57
+ allowed_chars : str
58
+ A string defining the set of allowed characters (part of a character set).
59
+ For example, "a-zA-Z0-9" will keep only letters and digits.
60
+ replacement : str
61
+ The string to replace non-matching characters with.
62
+
63
+ Returns:
64
+ --------
65
+ str
66
+ A new string where all characters not in `allowed_chars` are replaced.
67
+ """
68
+ # Build a regex that matches any character NOT in allowed_chars
69
+ pattern = rf"[^{allowed_chars}]"
70
+ return re.sub(pattern, replacement, text)
71
+
72
+ def safe_tool_name(name: str):
73
+ return _replace_non_matching(name, "a-zA-Z0-9_-", "_")
74
+
75
+ class VoiceConnection:
76
+ def __init__(self, *, room: RoomClient, breakout_room: str):
77
+ self.room = room
78
+ self.breakout_room = breakout_room
79
+
80
+ async def __aenter__(self):
81
+
82
+ client = self.room
83
+
84
+ room_options = rtc.RoomOptions(auto_subscribe=True)
85
+
86
+ room = rtc.Room()
87
+
88
+ self.livekit_room = room
89
+
90
+ connection_info = await client.livekit.get_connection_info(breakout_room=self.breakout_room)
91
+
92
+ await room.connect(url=connection_info.url, token=connection_info.token, options=room_options)
93
+
94
+ return self
95
+
96
+ async def __aexit__(self, exc_type, exc, tb):
97
+ await self.livekit_room.disconnect()
98
+
99
+ class Voicebot(SingleRoomAgent):
100
+
101
+ def __init__(
102
+ self,
103
+ name: str,
104
+ input_schema: Optional[dict] = None, # the base schema, voice agent parameters will be added
105
+ title: Optional[str] = None,
106
+ description: Optional[str] = None,
107
+ labels: Optional[list[str]] = None,
108
+ rules: Optional[list[str]] = None,
109
+ auto_greet_prompt: Optional[str] = None,
110
+ greeting: Optional[str] = None,
111
+ tool_adapter: ToolResponseAdapter = None,
112
+ toolkits: list[Toolkit] = None,
113
+ requires: list[Requirement] = None
114
+ ):
115
+ if toolkits == None:
116
+ toolkits = []
117
+
118
+ self.toolkits = toolkits
119
+
120
+ if rules == None:
121
+ rules = [ "You are a helpful assistant communicating through voice." ]
122
+
123
+ self.tool_adapter = tool_adapter
124
+ self.auto_greet_prompt = auto_greet_prompt
125
+ self.greeting = greeting
126
+
127
+ self.rules = rules
128
+
129
+ if input_schema == None:
130
+ input_schema = None
131
+
132
+ input_schema = merge(
133
+ schema=input_schema,
134
+ additional_properties={
135
+ })
136
+
137
+ super().__init__(
138
+ name=name,
139
+ description=description,
140
+ title=title,
141
+ labels=labels,
142
+ requires=requires
143
+ )
144
+
145
+ async def start(self, *, room):
146
+ await super().start(room=room)
147
+ await room.local_participant.set_attribute("supports_voice", True)
148
+ await room.messaging.enable()
149
+ room.messaging.on("message", self.on_message)
150
+
151
+ def on_message(self, message: RoomMessage):
152
+ if message.type == "voice_call":
153
+ breakout_room = message.message["breakout_room"]
154
+
155
+ logger.info(f"joining breakout room {breakout_room}")
156
+
157
+ def on_done(task: asyncio.Task):
158
+ try:
159
+ task.result()
160
+ except Exception as e:
161
+ logger.error(f"{e}", exc_info=e)
162
+
163
+ for participant in self.room.messaging.remote_participants:
164
+
165
+ if participant.id == message.from_participant_id:
166
+
167
+ task = asyncio.create_task(self.run_voice_agent(participant=participant, breakout_room=breakout_room))
168
+ task.add_done_callback(on_done)
169
+ return
170
+
171
+ logger.error(f"unable to find participant {message.from_participant_id}")
172
+
173
+
174
+ async def _wait_for_disconnect(self, room: rtc.Room):
175
+ disconnected = asyncio.Future()
176
+ def on_disconnected(_):
177
+ disconnected.set_result(True)
178
+ room.on("disconnected", on_disconnected)
179
+
180
+ logger.info("waiting for disconnection")
181
+ await disconnected
182
+
183
+ async def make_function_tools(self, *, context: ToolContext):
184
+
185
+ toolkits = [
186
+ *await self.get_required_toolkits(context=context),
187
+ *self.toolkits
188
+ ]
189
+
190
+ tools = []
191
+
192
+ for toolkit in toolkits:
193
+
194
+ for tool in toolkit.tools:
195
+
196
+ tools.append(self._make_function_tool(toolkits, context, tool.name, tool.description, tool.input_schema))
197
+
198
+ return tools
199
+
200
+ def _make_function_tool(
201
+ self, toolkits: list[Toolkit], context: ToolContext, name: str, description: str | None, input_schema: dict
202
+ ) -> RawFunctionTool:
203
+
204
+ name = safe_tool_name(name)
205
+ async def _tool_called(raw_arguments: dict) -> Any:
206
+ try:
207
+
208
+ tool = None
209
+ for toolkit in toolkits:
210
+ for t in toolkit.tools:
211
+ if safe_tool_name(t.name) == name:
212
+ tool = t
213
+
214
+ if tool is None:
215
+ raise ToolError(
216
+ f"Could not find tool {name}"
217
+ )
218
+
219
+ try:
220
+ logger.info(f"executing tool {name}: {raw_arguments}")
221
+ tool_result = await tool.execute(context=context, **raw_arguments)
222
+ except Exception as e:
223
+ logger.error(f"failed to call tool {tool.name}: {e}")
224
+ return ToolError("f{e}")
225
+ if self.tool_adapter == None:
226
+
227
+ if isinstance(tool_result, ErrorResponse):
228
+ raise ToolError(tool_result.text)
229
+
230
+ if isinstance(tool_result, JsonResponse):
231
+ return json.dumps(tool_result.json)
232
+
233
+ if isinstance(tool_result, TextResponse):
234
+ return tool_result.text
235
+
236
+ if isinstance(tool_result, EmptyResponse):
237
+ return "success"
238
+
239
+ if tool_result == None:
240
+ return "success"
241
+
242
+
243
+ raise ToolError(
244
+ f"Tool '{name}' returned an unexpected result {type(tool_result)}, attach a tool response adapter"
245
+ )
246
+
247
+ else:
248
+
249
+ text = await self.tool_adapter.to_plain_text(room=context.room, response=tool_result)
250
+ if text == None:
251
+ text = "success"
252
+ return text
253
+
254
+ except Exception as e:
255
+ logger.error("unable to call tool", exc_info=e)
256
+ raise
257
+
258
+
259
+ return function_tool(
260
+ _tool_called,
261
+ raw_schema={"name": name, "description": description, "strict" : True, "parameters": input_schema},
262
+ )
263
+
264
+ async def create_agent(self, *, context: ToolContext, session: AgentSession):
265
+
266
+ @function_tool
267
+ async def say(context: RunContext, text: str):
268
+ "says something out loud to the user"
269
+ logger.info(f"saying: {text}")
270
+ session.say(text)
271
+ return "success"
272
+
273
+ return Agent(
274
+ instructions="\n".join(self.rules),
275
+ allow_interruptions=True,
276
+ tools=[
277
+ *await self.make_function_tools(context=context),
278
+ say
279
+ ]
280
+ )
281
+
282
+ # agent = Agent(
283
+ # instructions="""
284
+ # You are a helpful assistant communicating through voice.
285
+ # """,
286
+ # stt=openai.STT(),
287
+ # llm=openai.LLM(model="gpt-4o"),
288
+ # tts=openai.TTS(),
289
+ # vad=silero.VAD.load(),
290
+ # allow_interruptions=True
291
+ #)
292
+
293
+ def create_session(self) -> AgentSession:
294
+
295
+ session = AgentSession(
296
+ max_tool_steps=50,
297
+ allow_interruptions=True,
298
+ vad=silero.VAD.load(),
299
+ stt=openai.STT(),
300
+ tts=openai.TTS(voice="echo"),
301
+ llm=openai.LLM(),
302
+ #turn_detection=MultilingualModel(),
303
+
304
+ )
305
+ return session
306
+
307
+
308
+ async def run_voice_agent(self, *, participant: Participant, breakout_room: str):
309
+
310
+ async with VoiceConnection(room=self.room, breakout_room=breakout_room) as connection:
311
+
312
+ logger.info("starting voice agent")
313
+
314
+ session = self.create_session()
315
+
316
+ agent = await self.create_agent(context=ToolContext(
317
+ room=self.room,
318
+ caller=self.room.local_participant,
319
+ on_behalf_of=participant
320
+ ), session=session)
321
+
322
+ background_audio = BackgroundAudioPlayer(
323
+ thinking_sound=[
324
+ #AudioConfig(
325
+ # os.path.dirname(os.path.abspath(__file__)) +"/sfx/thinking.mp3", volume=0.2),
326
+ AudioConfig(BuiltinAudioClip.KEYBOARD_TYPING, volume=0.3),
327
+ AudioConfig(BuiltinAudioClip.KEYBOARD_TYPING2, volume=0.4),
328
+ ],
329
+ )
330
+ await background_audio.start(room=connection.livekit_room, agent_session=session)
331
+
332
+ await session.start(agent=agent, room=connection.livekit_room)
333
+
334
+ if self.auto_greet_prompt != None:
335
+ session.generate_reply(user_input=self.auto_greet_prompt)
336
+
337
+ if self.greeting != None:
338
+ session.say(self.greeting)
339
+
340
+ logger.info("started voice agent")
341
+ await self._wait_for_disconnect(room=connection.livekit_room)
342
+
343
+
344
+
345
+
346
+
@@ -0,0 +1 @@
1
+ __version__ = "0.0.21"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-livekit
3
- Version: 0.0.19
3
+ Version: 0.0.21
4
4
  Summary: Livekit support for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://meshagent.com
@@ -13,13 +13,13 @@ Requires-Dist: pytest~=8.3.5
13
13
  Requires-Dist: pytest-asyncio~=0.26.0
14
14
  Requires-Dist: strip-markdown~=1.3
15
15
  Requires-Dist: livekit-api~=1.0.2
16
- Requires-Dist: livekit-agents~=1.0.11
17
- Requires-Dist: livekit-plugins-openai~=1.0.11
18
- Requires-Dist: livekit-plugins-cartesia~=1.0.11
19
- Requires-Dist: livekit-plugins-elevenlabs~=1.0.11
20
- Requires-Dist: livekit-plugins-playai~=1.0.11
21
- Requires-Dist: livekit-plugins-silero~=1.0.11
22
- Requires-Dist: livekit-plugins-turn-detector~=1.0.11
23
- Requires-Dist: meshagent-api~=0.0.19
24
- Requires-Dist: meshagent-tools~=0.0.19
16
+ Requires-Dist: livekit-agents~=1.0.19
17
+ Requires-Dist: livekit-plugins-openai~=1.0.19
18
+ Requires-Dist: livekit-plugins-cartesia~=1.0.19
19
+ Requires-Dist: livekit-plugins-elevenlabs~=1.0.19
20
+ Requires-Dist: livekit-plugins-playai~=1.0.19
21
+ Requires-Dist: livekit-plugins-silero~=1.0.19
22
+ Requires-Dist: livekit-plugins-turn-detector~=1.0.19
23
+ Requires-Dist: meshagent-api~=0.0.21
24
+ Requires-Dist: meshagent-tools~=0.0.21
25
25
  Dynamic: license-file
@@ -0,0 +1,13 @@
1
+ pytest~=8.3.5
2
+ pytest-asyncio~=0.26.0
3
+ strip-markdown~=1.3
4
+ livekit-api~=1.0.2
5
+ livekit-agents~=1.0.19
6
+ livekit-plugins-openai~=1.0.19
7
+ livekit-plugins-cartesia~=1.0.19
8
+ livekit-plugins-elevenlabs~=1.0.19
9
+ livekit-plugins-playai~=1.0.19
10
+ livekit-plugins-silero~=1.0.19
11
+ livekit-plugins-turn-detector~=1.0.19
12
+ meshagent-api~=0.0.21
13
+ meshagent-tools~=0.0.21
@@ -14,15 +14,15 @@ dependencies = [
14
14
  "pytest-asyncio~=0.26.0",
15
15
  "strip-markdown~=1.3",
16
16
  "livekit-api~=1.0.2",
17
- "livekit-agents~=1.0.11",
18
- "livekit-plugins-openai~=1.0.11",
19
- "livekit-plugins-cartesia~=1.0.11",
20
- "livekit-plugins-elevenlabs~=1.0.11",
21
- "livekit-plugins-playai~=1.0.11",
22
- "livekit-plugins-silero~=1.0.11",
23
- "livekit-plugins-turn-detector~=1.0.11",
24
- "meshagent-api~=0.0.19",
25
- "meshagent-tools~=0.0.19"
17
+ "livekit-agents~=1.0.19",
18
+ "livekit-plugins-openai~=1.0.19",
19
+ "livekit-plugins-cartesia~=1.0.19",
20
+ "livekit-plugins-elevenlabs~=1.0.19",
21
+ "livekit-plugins-playai~=1.0.19",
22
+ "livekit-plugins-silero~=1.0.19",
23
+ "livekit-plugins-turn-detector~=1.0.19",
24
+ "meshagent-api~=0.0.21",
25
+ "meshagent-tools~=0.0.21"
26
26
  ]
27
27
 
28
28
  [project.urls]
@@ -1,187 +0,0 @@
1
- import logging
2
- import asyncio
3
-
4
- from meshagent.api import RoomMessage
5
- from meshagent.api.room_server_client import RoomClient
6
-
7
- from livekit.agents import Agent, AgentSession
8
- from livekit.plugins import openai, silero
9
- #from livekit.plugins.turn_detector.multilingual import MultilingualModel
10
- import uuid
11
- import asyncio
12
- import logging
13
-
14
-
15
- from livekit.plugins import openai
16
-
17
- from livekit.plugins import openai, silero
18
- from livekit import rtc
19
- from livekit.agents import Agent, AgentSession
20
-
21
- from typing import Optional
22
-
23
- from copy import deepcopy
24
-
25
- from meshagent.api.schema_util import merge, prompt_schema
26
-
27
- from meshagent.agents import SingleRoomAgent
28
-
29
-
30
- logger = logging.getLogger("voice")
31
-
32
-
33
- from meshagent.agents.agent import AgentCallContext
34
-
35
-
36
- class VoiceConnection:
37
- def __init__(self, *, room: RoomClient, breakout_room: str):
38
- self.room = room
39
- self.breakout_room = breakout_room
40
-
41
- async def __aenter__(self):
42
-
43
- client = self.room
44
-
45
- room_options = rtc.RoomOptions(auto_subscribe=True)
46
-
47
- room = rtc.Room()
48
-
49
- self.livekit_room = room
50
-
51
- connection_info = await client.livekit.get_connection_info(breakout_room=self.breakout_room)
52
-
53
- await room.connect(url=connection_info.url, token=connection_info.token, options=room_options)
54
-
55
- return self
56
-
57
- async def __aexit__(self, exc_type, exc, tb):
58
- await self.livekit_room.disconnect()
59
-
60
- class Voicebot(SingleRoomAgent):
61
-
62
- def __init__(
63
- self,
64
- name: str,
65
- input_schema: Optional[dict] = None, # the base schema, voice agent parameters will be added
66
- title: Optional[str] = None,
67
- description: Optional[str] = None,
68
- labels: Optional[list[str]] = None,
69
- rules: Optional[list[str]] = None,
70
- auto_greet_prompt: Optional[str] = None,
71
- greeting: Optional[str] = None,
72
- ):
73
- if rules == None:
74
- rules = [ "You are a helpful assistant communicating through voice." ]
75
-
76
- self.auto_greet_prompt = auto_greet_prompt
77
- self.greeting = greeting
78
-
79
- self.rules = rules
80
-
81
- if input_schema == None:
82
- input_schema = None
83
-
84
- input_schema = merge(
85
- schema=input_schema,
86
- additional_properties={
87
- })
88
-
89
- super().__init__(
90
- name=name,
91
- description=description,
92
- title=title,
93
- labels=labels
94
- )
95
-
96
- async def start(self, *, room):
97
- await super().start(room=room)
98
- await room.local_participant.set_attribute("supports_voice", True)
99
- await room.messaging.enable()
100
- room.messaging.on("message", self.on_message)
101
-
102
- def on_message(self, message: RoomMessage):
103
- if message.type == "voice_call":
104
- breakout_room = message.message["breakout_room"]
105
-
106
- logger.info(f"joining breakout room {breakout_room}")
107
-
108
- def on_done(task: asyncio.Task):
109
- try:
110
- task.result()
111
- except Exception as e:
112
- logger.error(f"{e}", exc_info=e)
113
-
114
- task = asyncio.create_task(self.run_voice_agent(breakout_room=breakout_room))
115
- task.add_done_callback(on_done)
116
-
117
-
118
- async def _wait_for_disconnect(self, room: rtc.Room):
119
- disconnected = asyncio.Future()
120
- def on_disconnected(_):
121
- disconnected.set_result(True)
122
- room.on("disconnected", on_disconnected)
123
-
124
- logger.info("waiting for disconnection")
125
- await disconnected
126
-
127
- def create_agent(self):
128
- return Agent(
129
- instructions="\n".join(self.rules),
130
- allow_interruptions=True
131
- )
132
-
133
- # agent = Agent(
134
- # instructions="""
135
- # You are a helpful assistant communicating through voice.
136
- # """,
137
- # stt=openai.STT(),
138
- # llm=openai.LLM(model="gpt-4o"),
139
- # tts=openai.TTS(),
140
- # vad=silero.VAD.load(),
141
- # allow_interruptions=True
142
- #)
143
-
144
- def create_session(self) -> AgentSession:
145
-
146
- session = AgentSession(
147
- allow_interruptions=True,
148
- vad=silero.VAD.load(),
149
- stt=openai.STT(),
150
- tts=openai.TTS(voice="echo"),
151
- llm=openai.realtime.RealtimeModel(
152
- # it's necessary to turn off turn detection in the Realtime API in order to use
153
- # LiveKit's turn detection model
154
- voice="alloy",
155
- turn_detection=None,
156
- input_audio_transcription=None,
157
-
158
- ),
159
- )
160
- return session
161
-
162
-
163
- async def run_voice_agent(self, *, breakout_room: str):
164
-
165
- async with VoiceConnection(room=self.room, breakout_room=breakout_room) as connection:
166
-
167
-
168
- logger.info("starting voice agent")
169
-
170
- agent = self.create_agent()
171
- session = self.create_session()
172
-
173
- await session.start(agent=agent, room=connection.livekit_room)
174
-
175
- if self.auto_greet_prompt != None:
176
- session.generate_reply(user_input=self.auto_greet_prompt)
177
-
178
- if self.greeting != None:
179
- session.say(self.greeting)
180
-
181
- logger.info("started voice agent")
182
- await self._wait_for_disconnect(room=connection.livekit_room)
183
-
184
-
185
-
186
-
187
-
@@ -1 +0,0 @@
1
- __version__ = "0.0.19"
@@ -1,13 +0,0 @@
1
- pytest~=8.3.5
2
- pytest-asyncio~=0.26.0
3
- strip-markdown~=1.3
4
- livekit-api~=1.0.2
5
- livekit-agents~=1.0.11
6
- livekit-plugins-openai~=1.0.11
7
- livekit-plugins-cartesia~=1.0.11
8
- livekit-plugins-elevenlabs~=1.0.11
9
- livekit-plugins-playai~=1.0.11
10
- livekit-plugins-silero~=1.0.11
11
- livekit-plugins-turn-detector~=1.0.11
12
- meshagent-api~=0.0.19
13
- meshagent-tools~=0.0.19