meshagent-livekit 0.8.3__py3-none-any.whl → 0.20.3__py3-none-any.whl
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.
- meshagent/livekit/agents/meeting_transcriber.py +40 -44
- meshagent/livekit/agents/transcript_logger.py +119 -0
- meshagent/livekit/agents/voice.py +121 -68
- meshagent/livekit/version.py +1 -1
- {meshagent_livekit-0.8.3.dist-info → meshagent_livekit-0.20.3.dist-info}/METADATA +9 -8
- meshagent_livekit-0.20.3.dist-info/RECORD +13 -0
- meshagent_livekit-0.8.3.dist-info/RECORD +0 -12
- {meshagent_livekit-0.8.3.dist-info → meshagent_livekit-0.20.3.dist-info}/WHEEL +0 -0
- {meshagent_livekit-0.8.3.dist-info → meshagent_livekit-0.20.3.dist-info}/licenses/LICENSE +0 -0
- {meshagent_livekit-0.8.3.dist-info → meshagent_livekit-0.20.3.dist-info}/top_level.txt +0 -0
|
@@ -3,28 +3,28 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
|
-
from datetime import datetime, timezone
|
|
7
6
|
from livekit import rtc
|
|
8
7
|
from livekit.agents import (
|
|
9
|
-
Agent,
|
|
10
8
|
AgentSession,
|
|
11
9
|
RoomInputOptions,
|
|
12
10
|
RoomIO,
|
|
13
11
|
RoomOutputOptions,
|
|
14
|
-
StopResponse,
|
|
15
|
-
llm,
|
|
16
12
|
utils,
|
|
17
13
|
)
|
|
18
14
|
from livekit.agents.stt import STT
|
|
19
15
|
|
|
16
|
+
from meshagent.api import RoomException
|
|
17
|
+
|
|
20
18
|
from meshagent.openai.proxy import get_client
|
|
21
19
|
from livekit.plugins import openai, silero
|
|
22
|
-
from meshagent.api import
|
|
20
|
+
from meshagent.api import SchemaRegistration, SchemaRegistry
|
|
23
21
|
from meshagent.agents import SingleRoomAgent
|
|
24
22
|
from meshagent.tools import RemoteToolkit, ToolContext, Tool
|
|
25
23
|
from meshagent.api.room_server_client import Requirement
|
|
26
24
|
from meshagent.livekit.agents.voice import VoiceConnection
|
|
27
25
|
from meshagent.agents.schemas.transcript import transcript_schema
|
|
26
|
+
from meshagent.livekit.agents.transcript_logger import Transcriber
|
|
27
|
+
|
|
28
28
|
|
|
29
29
|
logger = logging.getLogger("meeting_transcriber")
|
|
30
30
|
|
|
@@ -127,14 +127,14 @@ class MeetingTranscriber(SingleRoomAgent):
|
|
|
127
127
|
async with VoiceConnection(
|
|
128
128
|
room=self.room, breakout_room=breakout_room
|
|
129
129
|
) as conn:
|
|
130
|
-
doc = await self.room.sync.open(path=path, create=True)
|
|
131
|
-
|
|
132
130
|
stt = self.stt
|
|
133
131
|
if stt is None:
|
|
134
132
|
openai_client = get_client(room=self.room)
|
|
135
133
|
stt = openai.STT(client=openai_client)
|
|
136
134
|
|
|
137
|
-
transcriber = MultiUserTranscriber(
|
|
135
|
+
transcriber = MultiUserTranscriber(
|
|
136
|
+
conn, path, self.room, self._vad, stt
|
|
137
|
+
)
|
|
138
138
|
transcriber.start()
|
|
139
139
|
|
|
140
140
|
for participant in conn.livekit_room.remote_participants.values():
|
|
@@ -147,8 +147,6 @@ class MeetingTranscriber(SingleRoomAgent):
|
|
|
147
147
|
f"transcribing.{breakout_room}", False
|
|
148
148
|
)
|
|
149
149
|
|
|
150
|
-
await self.room.sync.close(path=path)
|
|
151
|
-
|
|
152
150
|
await transcriber.aclose()
|
|
153
151
|
except Exception as ex:
|
|
154
152
|
logger.error(f"error during transcription {ex}", exc_info=ex)
|
|
@@ -193,35 +191,11 @@ class TranscriptRegistry(SchemaRegistry):
|
|
|
193
191
|
)
|
|
194
192
|
|
|
195
193
|
|
|
196
|
-
class Transcriber(Agent):
|
|
197
|
-
def __init__(self, *, participant, doc: MeshDocument, stt):
|
|
198
|
-
super().__init__(
|
|
199
|
-
instructions="not-needed",
|
|
200
|
-
stt=stt,
|
|
201
|
-
)
|
|
202
|
-
self.doc = doc
|
|
203
|
-
self.participant = participant
|
|
204
|
-
|
|
205
|
-
async def on_user_turn_completed(
|
|
206
|
-
self, chat_ctx: llm.ChatContext, new_message: llm.ChatMessage
|
|
207
|
-
):
|
|
208
|
-
segments = self.doc.root
|
|
209
|
-
segments.append_child(
|
|
210
|
-
"segment",
|
|
211
|
-
{
|
|
212
|
-
"text": new_message.text_content,
|
|
213
|
-
"participant_name": self.participant.name,
|
|
214
|
-
"participant_id": self.participant.sid,
|
|
215
|
-
"time": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
|
|
216
|
-
},
|
|
217
|
-
)
|
|
218
|
-
raise StopResponse()
|
|
219
|
-
|
|
220
|
-
|
|
221
194
|
class MultiUserTranscriber:
|
|
222
|
-
def __init__(self, ctx: VoiceConnection,
|
|
195
|
+
def __init__(self, ctx: VoiceConnection, path: str, room, vad, stt):
|
|
223
196
|
self.ctx = ctx
|
|
224
|
-
self.
|
|
197
|
+
self.path = path
|
|
198
|
+
self.room = room
|
|
225
199
|
self.vad = vad
|
|
226
200
|
self.stt = stt
|
|
227
201
|
self._sessions: dict[str, AgentSession] = {}
|
|
@@ -240,6 +214,8 @@ class MultiUserTranscriber:
|
|
|
240
214
|
*[self._close_session(session) for session in self._sessions.values()]
|
|
241
215
|
)
|
|
242
216
|
|
|
217
|
+
self._sessions.clear()
|
|
218
|
+
|
|
243
219
|
self.ctx.livekit_room.off(
|
|
244
220
|
"participant_connected", self.on_participant_connected
|
|
245
221
|
)
|
|
@@ -273,12 +249,38 @@ class MultiUserTranscriber:
|
|
|
273
249
|
task.add_done_callback(lambda _: self._tasks.discard(task))
|
|
274
250
|
|
|
275
251
|
async def _start_session(self, participant: rtc.RemoteParticipant) -> AgentSession:
|
|
252
|
+
logger.info(
|
|
253
|
+
f"Creating transcription session for {participant.name} ({participant.sid})"
|
|
254
|
+
)
|
|
255
|
+
|
|
276
256
|
if participant.identity in self._sessions:
|
|
277
257
|
return self._sessions[participant.identity]
|
|
278
258
|
|
|
259
|
+
remote_participant = next(
|
|
260
|
+
p
|
|
261
|
+
for p in self.room.messaging.remote_participants
|
|
262
|
+
if p.id == participant.identity
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
if remote_participant is None:
|
|
266
|
+
raise RoomException(
|
|
267
|
+
f"participant was connected to room {participant.identiy}"
|
|
268
|
+
)
|
|
269
|
+
|
|
279
270
|
session = AgentSession(
|
|
280
271
|
vad=self.vad,
|
|
281
272
|
)
|
|
273
|
+
|
|
274
|
+
agent = Transcriber(
|
|
275
|
+
events={"user_turn_completed"},
|
|
276
|
+
transcript_path=self.path,
|
|
277
|
+
room=self.room,
|
|
278
|
+
user=remote_participant,
|
|
279
|
+
agent=self.room.local_participant,
|
|
280
|
+
instructions="not-needed",
|
|
281
|
+
stt=self.stt,
|
|
282
|
+
)
|
|
283
|
+
|
|
282
284
|
room_io = RoomIO(
|
|
283
285
|
agent_session=session,
|
|
284
286
|
room=self.ctx.livekit_room,
|
|
@@ -296,13 +298,7 @@ class MultiUserTranscriber:
|
|
|
296
298
|
),
|
|
297
299
|
)
|
|
298
300
|
await room_io.start()
|
|
299
|
-
await session.start(
|
|
300
|
-
agent=Transcriber(
|
|
301
|
-
participant=participant,
|
|
302
|
-
doc=self.doc,
|
|
303
|
-
stt=self.stt,
|
|
304
|
-
)
|
|
305
|
-
)
|
|
301
|
+
await session.start(agent=agent)
|
|
306
302
|
return session
|
|
307
303
|
|
|
308
304
|
async def _close_session(self, sess: AgentSession) -> None:
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Literal
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from livekit.agents import Agent, llm, StopResponse
|
|
5
|
+
from livekit.agents.llm import ChatMessage
|
|
6
|
+
from livekit.agents.voice import ConversationItemAddedEvent
|
|
7
|
+
from meshagent.api import MeshDocument, Participant
|
|
8
|
+
from meshagent.api.room_server_client import RoomClient
|
|
9
|
+
from meshagent.agents.schemas.transcript import transcript_schema
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger("transcript_logger")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Transcriber(Agent):
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
*,
|
|
18
|
+
user: Participant,
|
|
19
|
+
agent: Participant,
|
|
20
|
+
events: set[Literal["user_turn_completed", "conversation_item_added"]],
|
|
21
|
+
transcript_path: str,
|
|
22
|
+
room: RoomClient,
|
|
23
|
+
**kwargs,
|
|
24
|
+
):
|
|
25
|
+
super().__init__(**kwargs)
|
|
26
|
+
self.user = user
|
|
27
|
+
self.agent = agent
|
|
28
|
+
self.events = events
|
|
29
|
+
self.transcript_path = transcript_path
|
|
30
|
+
self.room = room
|
|
31
|
+
self.doc: MeshDocument | None = None
|
|
32
|
+
|
|
33
|
+
def _append_segment(self, *, role: str, text: str, created_at: float):
|
|
34
|
+
if not text:
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
if not self.doc:
|
|
38
|
+
logger.warning("Cannot append segment, document not opened")
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
if role == "user":
|
|
42
|
+
participant_id = self.user.id
|
|
43
|
+
participant_name = self.user.get_attribute("name")
|
|
44
|
+
elif role == "assistant":
|
|
45
|
+
participant_id = self.agent.id
|
|
46
|
+
participant_name = self.agent.get_attribute("name")
|
|
47
|
+
else:
|
|
48
|
+
# skip system / developer / function_call, etc
|
|
49
|
+
return
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
segments = self.doc.root
|
|
53
|
+
segments.append_child(
|
|
54
|
+
"segment",
|
|
55
|
+
{
|
|
56
|
+
"text": text,
|
|
57
|
+
"participant_name": participant_name,
|
|
58
|
+
"participant_id": participant_id,
|
|
59
|
+
"time": datetime.fromtimestamp(created_at, tz=timezone.utc)
|
|
60
|
+
.isoformat()
|
|
61
|
+
.replace("+00:00", "Z"),
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
logger.error(f"Failed to write sgement: {e}", exc_info=e)
|
|
66
|
+
|
|
67
|
+
def _on_conversation_item(self, event: ConversationItemAddedEvent):
|
|
68
|
+
item = event.item
|
|
69
|
+
# Only care about ChatMessages (ignore tool calls, etc.)
|
|
70
|
+
if not isinstance(item, ChatMessage):
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
text = item.text_content
|
|
74
|
+
if text is None:
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
# item.role is Literal["developer", "system", "user", "assistant"]
|
|
78
|
+
self._append_segment(role=item.role, text=text, created_at=item.created_at)
|
|
79
|
+
|
|
80
|
+
async def on_enter(self):
|
|
81
|
+
"""Open MeshDocument and attach handler for voicebot transcriptions"""
|
|
82
|
+
try:
|
|
83
|
+
self.doc = await self.room.sync.open(
|
|
84
|
+
path=self.transcript_path, create=True, schema=transcript_schema
|
|
85
|
+
)
|
|
86
|
+
except Exception as e:
|
|
87
|
+
logger.warning(
|
|
88
|
+
f"Failed to open transcript doc: {e}. This meeting will not be transcribed."
|
|
89
|
+
)
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
if "conversation_item_added" in self.events:
|
|
93
|
+
self.session.on("conversation_item_added", self._on_conversation_item)
|
|
94
|
+
|
|
95
|
+
async def on_exit(self):
|
|
96
|
+
"""Cleanup handler when voicebot transcription ends and close MeshDocument"""
|
|
97
|
+
if "conversation_item_added" in self.events:
|
|
98
|
+
try:
|
|
99
|
+
self.session.off("conversation_item_added", self._on_conversation_item)
|
|
100
|
+
except Exception as e:
|
|
101
|
+
logger.warning(f"Failed to remove handler: {e}")
|
|
102
|
+
# only close doc if it was successfully opened
|
|
103
|
+
if self.doc:
|
|
104
|
+
try:
|
|
105
|
+
await self.room.sync.close(path=self.transcript_path)
|
|
106
|
+
logger.info("transcript saved at %s", self.transcript_path)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
logger.warning("failed to close transcript doc: %s", e)
|
|
109
|
+
|
|
110
|
+
async def on_user_turn_completed(
|
|
111
|
+
self, turn_ctx: llm.ChatContext, new_message: llm.ChatMessage
|
|
112
|
+
):
|
|
113
|
+
if "user_turn_completed" in self.events:
|
|
114
|
+
self._append_segment(
|
|
115
|
+
role="user",
|
|
116
|
+
text=new_message.text_content,
|
|
117
|
+
created_at=new_message.created_at,
|
|
118
|
+
)
|
|
119
|
+
raise StopResponse()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import asyncio
|
|
3
3
|
from asyncio import CancelledError
|
|
4
|
+
from dataclasses import dataclass
|
|
4
5
|
|
|
5
6
|
from meshagent.api import (
|
|
6
7
|
RoomMessage,
|
|
@@ -20,6 +21,7 @@ from livekit.agents.llm import RawFunctionTool, ToolError, function_tool
|
|
|
20
21
|
|
|
21
22
|
from meshagent.openai.proxy import get_client
|
|
22
23
|
from meshagent.agents import AgentChatContext
|
|
24
|
+
from meshagent.livekit.agents.transcript_logger import Transcriber
|
|
23
25
|
from livekit.agents import (
|
|
24
26
|
BackgroundAudioPlayer,
|
|
25
27
|
AudioConfig,
|
|
@@ -31,20 +33,11 @@ from livekit.agents import (
|
|
|
31
33
|
from livekit.plugins import openai, silero
|
|
32
34
|
# from livekit.plugins.turn_detector.multilingual import MultilingualModel
|
|
33
35
|
|
|
34
|
-
|
|
35
36
|
import json
|
|
36
37
|
|
|
37
|
-
from typing import Any
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
from typing import Any, Optional
|
|
40
39
|
from livekit import rtc
|
|
41
|
-
|
|
42
|
-
from typing import Optional
|
|
43
|
-
|
|
44
|
-
|
|
45
40
|
from meshagent.agents import SingleRoomAgent
|
|
46
|
-
|
|
47
|
-
|
|
48
41
|
import re
|
|
49
42
|
|
|
50
43
|
logger = logging.getLogger("voice")
|
|
@@ -107,6 +100,14 @@ class VoiceConnection:
|
|
|
107
100
|
await self.livekit_room.disconnect()
|
|
108
101
|
|
|
109
102
|
|
|
103
|
+
@dataclass
|
|
104
|
+
class VoiceBotContext:
|
|
105
|
+
room: RoomClient
|
|
106
|
+
caller: Participant
|
|
107
|
+
connection: VoiceConnection
|
|
108
|
+
transcript_path: Optional[str] = None
|
|
109
|
+
|
|
110
|
+
|
|
110
111
|
class VoiceBot(SingleRoomAgent):
|
|
111
112
|
def __init__(
|
|
112
113
|
self,
|
|
@@ -155,6 +156,9 @@ class VoiceBot(SingleRoomAgent):
|
|
|
155
156
|
def on_message(self, message: RoomMessage):
|
|
156
157
|
if message.type == "voice_call":
|
|
157
158
|
breakout_room = message.message["breakout_room"]
|
|
159
|
+
transcript_path = message.message.get(
|
|
160
|
+
"transcript_path"
|
|
161
|
+
) # get the transcript_path if the client sends one
|
|
158
162
|
|
|
159
163
|
logger.info(f"joining breakout room {breakout_room}")
|
|
160
164
|
|
|
@@ -167,10 +171,15 @@ class VoiceBot(SingleRoomAgent):
|
|
|
167
171
|
logger.error(f"{e}", exc_info=e)
|
|
168
172
|
|
|
169
173
|
for participant in self.room.messaging.remote_participants:
|
|
170
|
-
if
|
|
174
|
+
if (
|
|
175
|
+
participant.id == message.message.get("participant_id")
|
|
176
|
+
or participant.id == message.from_participant_id
|
|
177
|
+
):
|
|
171
178
|
task = asyncio.create_task(
|
|
172
179
|
self.run_voice_agent(
|
|
173
|
-
participant=participant,
|
|
180
|
+
participant=participant,
|
|
181
|
+
breakout_room=breakout_room,
|
|
182
|
+
transcript_path=transcript_path,
|
|
174
183
|
)
|
|
175
184
|
)
|
|
176
185
|
task.add_done_callback(on_done)
|
|
@@ -234,7 +243,7 @@ class VoiceBot(SingleRoomAgent):
|
|
|
234
243
|
tool_result = await tool.execute(context=context, **raw_arguments)
|
|
235
244
|
except Exception as e:
|
|
236
245
|
logger.error(f"failed to call tool {tool.name}: {e}")
|
|
237
|
-
return ToolError("
|
|
246
|
+
return ToolError(f"{e}")
|
|
238
247
|
if self.tool_adapter is None:
|
|
239
248
|
if isinstance(tool_result, ErrorResponse):
|
|
240
249
|
raise ToolError(tool_result.text)
|
|
@@ -277,38 +286,51 @@ class VoiceBot(SingleRoomAgent):
|
|
|
277
286
|
},
|
|
278
287
|
)
|
|
279
288
|
|
|
280
|
-
async def create_agent(
|
|
289
|
+
async def create_agent(
|
|
290
|
+
self,
|
|
291
|
+
*,
|
|
292
|
+
context: VoiceBotContext,
|
|
293
|
+
session: AgentSession,
|
|
294
|
+
):
|
|
281
295
|
ctx = ChatContext()
|
|
282
296
|
|
|
283
297
|
initial_context = await self.init_chat_context()
|
|
284
298
|
|
|
285
|
-
|
|
299
|
+
tool_context = ToolContext(
|
|
300
|
+
room=context.room,
|
|
301
|
+
caller=context.room.local_participant,
|
|
302
|
+
on_behalf_of=context.caller,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
rules = await self.get_rules(participant=context.room.local_participant)
|
|
286
306
|
|
|
287
307
|
initial_context.replace_rules(rules)
|
|
288
308
|
|
|
289
309
|
for message in initial_context.messages:
|
|
290
310
|
ctx.add_message(role=message["role"], content=message["content"])
|
|
291
311
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
312
|
+
if context.transcript_path:
|
|
313
|
+
return Transcriber(
|
|
314
|
+
room=context.room,
|
|
315
|
+
transcript_path=context.transcript_path,
|
|
316
|
+
events={"conversation_item_added"},
|
|
317
|
+
user=context.caller,
|
|
318
|
+
agent=context.room.local_participant,
|
|
319
|
+
chat_ctx=ctx,
|
|
320
|
+
instructions=initial_context.get_system_instructions(),
|
|
321
|
+
allow_interruptions=True,
|
|
322
|
+
tools=[*await self.make_function_tools(context=tool_context)],
|
|
323
|
+
)
|
|
324
|
+
else:
|
|
325
|
+
return Agent(
|
|
326
|
+
chat_ctx=ctx,
|
|
327
|
+
instructions=initial_context.get_system_instructions(),
|
|
328
|
+
allow_interruptions=True,
|
|
329
|
+
tools=[*await self.make_function_tools(context=tool_context)],
|
|
330
|
+
)
|
|
309
331
|
|
|
310
332
|
async def get_rules(self, *, participant: Participant):
|
|
311
|
-
rules = [*self.
|
|
333
|
+
rules = [*self.rules]
|
|
312
334
|
client = participant.get_attribute("client")
|
|
313
335
|
|
|
314
336
|
if self.client_rules is not None and client is not None:
|
|
@@ -321,7 +343,7 @@ class VoiceBot(SingleRoomAgent):
|
|
|
321
343
|
async def init_chat_context(self) -> AgentChatContext:
|
|
322
344
|
return AgentChatContext()
|
|
323
345
|
|
|
324
|
-
def create_session(self, *, context:
|
|
346
|
+
def create_session(self, *, context: VoiceBotContext) -> AgentSession:
|
|
325
347
|
oaiclient = get_client(room=self.room)
|
|
326
348
|
|
|
327
349
|
session = AgentSession(
|
|
@@ -335,55 +357,86 @@ class VoiceBot(SingleRoomAgent):
|
|
|
335
357
|
)
|
|
336
358
|
return session
|
|
337
359
|
|
|
338
|
-
async def
|
|
360
|
+
async def on_session_created(
|
|
361
|
+
self, *, context: VoiceBotContext, session: AgentSession
|
|
362
|
+
) -> None:
|
|
363
|
+
return
|
|
364
|
+
|
|
365
|
+
async def on_session_started(
|
|
366
|
+
self, *, context: VoiceBotContext, session: AgentSession
|
|
367
|
+
) -> None:
|
|
368
|
+
return
|
|
369
|
+
|
|
370
|
+
async def on_session_ended(
|
|
371
|
+
self, *, context: VoiceBotContext, session: AgentSession
|
|
372
|
+
) -> None:
|
|
373
|
+
return
|
|
374
|
+
|
|
375
|
+
async def run_voice_agent(
|
|
376
|
+
self,
|
|
377
|
+
*,
|
|
378
|
+
participant: Participant,
|
|
379
|
+
breakout_room: str,
|
|
380
|
+
transcript_path: Optional[str] = None,
|
|
381
|
+
):
|
|
339
382
|
async with VoiceConnection(
|
|
340
383
|
room=self.room, breakout_room=breakout_room
|
|
341
384
|
) as connection:
|
|
342
385
|
logger.info("starting voice agent")
|
|
343
386
|
|
|
344
|
-
context =
|
|
387
|
+
context = VoiceBotContext(
|
|
345
388
|
room=self.room,
|
|
346
|
-
caller=
|
|
347
|
-
|
|
389
|
+
caller=participant,
|
|
390
|
+
connection=connection,
|
|
391
|
+
transcript_path=transcript_path,
|
|
348
392
|
)
|
|
349
393
|
|
|
350
394
|
session = self.create_session(context=context)
|
|
351
395
|
|
|
352
|
-
|
|
396
|
+
try:
|
|
397
|
+
await self.on_session_created(context=context, session=session)
|
|
353
398
|
|
|
354
|
-
|
|
355
|
-
thinking_sound=[
|
|
356
|
-
# AudioConfig(
|
|
357
|
-
# os.path.dirname(os.path.abspath(__file__)) +"/sfx/thinking.mp3", volume=0.2),
|
|
358
|
-
AudioConfig(BuiltinAudioClip.KEYBOARD_TYPING, volume=0.3),
|
|
359
|
-
AudioConfig(BuiltinAudioClip.KEYBOARD_TYPING2, volume=0.4),
|
|
360
|
-
],
|
|
361
|
-
)
|
|
362
|
-
await background_audio.start(
|
|
363
|
-
room=connection.livekit_room, agent_session=session
|
|
364
|
-
)
|
|
399
|
+
agent = await self.create_agent(context=context, session=session)
|
|
365
400
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
)
|
|
377
|
-
|
|
401
|
+
background_audio = BackgroundAudioPlayer(
|
|
402
|
+
thinking_sound=[
|
|
403
|
+
# AudioConfig(
|
|
404
|
+
# os.path.dirname(os.path.abspath(__file__)) +"/sfx/thinking.mp3", volume=0.2),
|
|
405
|
+
AudioConfig(BuiltinAudioClip.KEYBOARD_TYPING, volume=0.3),
|
|
406
|
+
AudioConfig(BuiltinAudioClip.KEYBOARD_TYPING2, volume=0.4),
|
|
407
|
+
],
|
|
408
|
+
)
|
|
409
|
+
await background_audio.start(
|
|
410
|
+
room=connection.livekit_room, agent_session=session
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
await session.start(
|
|
414
|
+
agent=agent,
|
|
415
|
+
room=connection.livekit_room,
|
|
416
|
+
room_input_options=RoomInputOptions(
|
|
417
|
+
text_enabled=False,
|
|
418
|
+
delete_room_on_close=False,
|
|
419
|
+
),
|
|
420
|
+
room_output_options=RoomOutputOptions(
|
|
421
|
+
transcription_enabled=True,
|
|
422
|
+
audio_enabled=True,
|
|
423
|
+
),
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
await self.on_session_started(context=context, session=session)
|
|
427
|
+
if self.auto_greet_prompt is not None:
|
|
428
|
+
session.generate_reply(user_input=self.auto_greet_prompt)
|
|
378
429
|
|
|
379
|
-
|
|
380
|
-
|
|
430
|
+
if self.auto_greet_message is not None:
|
|
431
|
+
session.say(self.auto_greet_message)
|
|
381
432
|
|
|
382
|
-
|
|
383
|
-
|
|
433
|
+
logger.info("started voice agent")
|
|
434
|
+
await self._wait_for_disconnect(room=connection.livekit_room)
|
|
435
|
+
|
|
436
|
+
except Exception as e:
|
|
437
|
+
logger.error(f"Error during voice session: {e}", exc_info=e)
|
|
384
438
|
|
|
385
|
-
|
|
386
|
-
await self._wait_for_disconnect(room=connection.livekit_room)
|
|
439
|
+
await self.on_session_ended(context=context, session=session)
|
|
387
440
|
|
|
388
441
|
|
|
389
442
|
class Voicebot(VoiceBot):
|
meshagent/livekit/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.20.3"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-livekit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.3
|
|
4
4
|
Summary: Livekit support for Meshagent
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Documentation, https://docs.meshagent.com
|
|
@@ -12,13 +12,14 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: pytest~=8.4
|
|
13
13
|
Requires-Dist: pytest-asyncio~=0.26
|
|
14
14
|
Requires-Dist: strip-markdown~=1.3
|
|
15
|
-
Requires-Dist: livekit
|
|
16
|
-
Requires-Dist: livekit-
|
|
17
|
-
Requires-Dist: livekit-
|
|
18
|
-
Requires-Dist: livekit-plugins-
|
|
19
|
-
Requires-Dist: livekit-plugins-
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist: meshagent-
|
|
15
|
+
Requires-Dist: livekit==1.0.20
|
|
16
|
+
Requires-Dist: livekit-api~=1.1
|
|
17
|
+
Requires-Dist: livekit-agents~=1.3
|
|
18
|
+
Requires-Dist: livekit-plugins-openai~=1.3
|
|
19
|
+
Requires-Dist: livekit-plugins-silero~=1.3
|
|
20
|
+
Requires-Dist: livekit-plugins-turn-detector~=1.3
|
|
21
|
+
Requires-Dist: meshagent-api~=0.20.3
|
|
22
|
+
Requires-Dist: meshagent-tools~=0.20.3
|
|
22
23
|
Dynamic: license-file
|
|
23
24
|
|
|
24
25
|
# [Meshagent](https://www.meshagent.com)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
meshagent/livekit/__init__.py,sha256=X78Z4yEg5XfkNKH0HiIdG4k1q5ktB-ampTuXHLNFrAw,58
|
|
2
|
+
meshagent/livekit/livekit_protocol.py,sha256=5Zu4ymLWEGt5SGXLNu94gOeyjnjhaV6uTS2FhSdODqs,1470
|
|
3
|
+
meshagent/livekit/livekit_protocol_test.py,sha256=o7yYxXad4tMazcxFkq44yW-A9tJ0Lk6WdZpG5ifxcU4,2980
|
|
4
|
+
meshagent/livekit/version.py,sha256=gbf7freb96tMI3GZmlo8Yd1Od2bGCv9ECLz-l6H8pns,23
|
|
5
|
+
meshagent/livekit/agents/meeting_transcriber.py,sha256=7dZEuUUpVFHHltrcZ9T4ei5UcKGXvF9uTNRZjbZYm8M,10038
|
|
6
|
+
meshagent/livekit/agents/transcriber.py,sha256=S992oVVBt3ShWDQQWprLjyl6Yh0hyNRd8d3qCmg_toU,5795
|
|
7
|
+
meshagent/livekit/agents/transcript_logger.py,sha256=kRESlbvS7CgrMzTrDhhlaMYEY2bUS2VTxluTurWZ0TM,4299
|
|
8
|
+
meshagent/livekit/agents/voice.py,sha256=f3zm9EfTSCV_0V5VMkEfaZ8ByEJed26picWASDXoDmc,14495
|
|
9
|
+
meshagent_livekit-0.20.3.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
|
|
10
|
+
meshagent_livekit-0.20.3.dist-info/METADATA,sha256=pWfqYX7ST6rPKzCmfc0jdu-fX3ZzX5GFvp49eSjOe-g,1783
|
|
11
|
+
meshagent_livekit-0.20.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
+
meshagent_livekit-0.20.3.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
|
|
13
|
+
meshagent_livekit-0.20.3.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
meshagent/livekit/__init__.py,sha256=X78Z4yEg5XfkNKH0HiIdG4k1q5ktB-ampTuXHLNFrAw,58
|
|
2
|
-
meshagent/livekit/livekit_protocol.py,sha256=5Zu4ymLWEGt5SGXLNu94gOeyjnjhaV6uTS2FhSdODqs,1470
|
|
3
|
-
meshagent/livekit/livekit_protocol_test.py,sha256=o7yYxXad4tMazcxFkq44yW-A9tJ0Lk6WdZpG5ifxcU4,2980
|
|
4
|
-
meshagent/livekit/version.py,sha256=otnwfmvJLUamPajTPUaIekiO9mA-2HPi-_h_E0N-uOQ,22
|
|
5
|
-
meshagent/livekit/agents/meeting_transcriber.py,sha256=4B5Qi0vKP0TU00vR4KsNdIiR2uyvfgiOL2hjuzhLotw,10210
|
|
6
|
-
meshagent/livekit/agents/transcriber.py,sha256=S992oVVBt3ShWDQQWprLjyl6Yh0hyNRd8d3qCmg_toU,5795
|
|
7
|
-
meshagent/livekit/agents/voice.py,sha256=Fayrgi9JYNDVSGLEnMbBpzkrQF70P5RrfUHSyd1WKwM,12417
|
|
8
|
-
meshagent_livekit-0.8.3.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
|
|
9
|
-
meshagent_livekit-0.8.3.dist-info/METADATA,sha256=QpqzZpHIAZHRj91j7ncNhgKfbanuNBEuWEghgFBq8qY,1749
|
|
10
|
-
meshagent_livekit-0.8.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
meshagent_livekit-0.8.3.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
|
|
12
|
-
meshagent_livekit-0.8.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|