little more cleanup
This commit is contained in:
@@ -2,7 +2,7 @@ import asyncio
|
|||||||
import copy
|
import copy
|
||||||
import functools
|
import functools
|
||||||
from typing import AsyncGenerator, Awaitable, Callable
|
from typing import AsyncGenerator, Awaitable, Callable
|
||||||
from dailyai.queue_aggregators import LLMContextAggregator
|
from dailyai.queue_aggregators import LLMAssistantContextAggregator, LLMContextAggregator, LLMUserContextAggregator
|
||||||
from dailyai.queue_frame import EndStreamQueueFrame, QueueFrame, TranscriptionQueueFrame
|
from dailyai.queue_frame import EndStreamQueueFrame, QueueFrame, TranscriptionQueueFrame
|
||||||
|
|
||||||
|
|
||||||
@@ -17,8 +17,8 @@ class InterruptibleConversationWrapper:
|
|||||||
interrupt: Callable[[], None],
|
interrupt: Callable[[], None],
|
||||||
my_participant_id: str | None,
|
my_participant_id: str | None,
|
||||||
llm_messages: list[dict[str, str]],
|
llm_messages: list[dict[str, str]],
|
||||||
llm_context_aggregator_in=LLMContextAggregator,
|
llm_context_aggregator_in=LLMUserContextAggregator,
|
||||||
llm_context_aggregator_out=LLMContextAggregator,
|
llm_context_aggregator_out=LLMAssistantContextAggregator,
|
||||||
delay_before_speech_seconds: float = 1.0,
|
delay_before_speech_seconds: float = 1.0,
|
||||||
):
|
):
|
||||||
self._frame_generator: Callable[[], AsyncGenerator[QueueFrame, None]] = frame_generator
|
self._frame_generator: Callable[[], AsyncGenerator[QueueFrame, None]] = frame_generator
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class LLMContextAggregator(AIService):
|
|||||||
role: str,
|
role: str,
|
||||||
bot_participant_id=None,
|
bot_participant_id=None,
|
||||||
complete_sentences=True,
|
complete_sentences=True,
|
||||||
pass_through=False):
|
pass_through=True):
|
||||||
self.messages = messages
|
self.messages = messages
|
||||||
self.bot_participant_id = bot_participant_id
|
self.bot_participant_id = bot_participant_id
|
||||||
self.role = role
|
self.role = role
|
||||||
@@ -42,28 +42,32 @@ class LLMContextAggregator(AIService):
|
|||||||
self.pass_through = pass_through
|
self.pass_through = pass_through
|
||||||
|
|
||||||
async def process_frame(self, frame: QueueFrame) -> AsyncGenerator[QueueFrame, None]:
|
async def process_frame(self, frame: QueueFrame) -> AsyncGenerator[QueueFrame, None]:
|
||||||
# TODO: split up transcription by participant
|
# We don't do anything with non-text frames, pass it along to next in the pipeline.
|
||||||
if isinstance(frame, TextQueueFrame):
|
if not isinstance(frame, TextQueueFrame):
|
||||||
|
|
||||||
# Ignore transcription frames from the bot
|
|
||||||
if isinstance(frame, TranscriptionQueueFrame):
|
|
||||||
if frame.participantId == self.bot_participant_id:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.complete_sentences:
|
|
||||||
self.sentence += frame.text
|
|
||||||
if self.sentence.endswith((".", "?", "!")):
|
|
||||||
self.messages.append({"role": self.role, "content": self.sentence})
|
|
||||||
self.sentence = ""
|
|
||||||
yield LLMMessagesQueueFrame(self.messages)
|
|
||||||
else:
|
|
||||||
self.messages.append({"role": self.role, "content": frame.text})
|
|
||||||
yield LLMMessagesQueueFrame(self.messages)
|
|
||||||
|
|
||||||
if self.pass_through:
|
|
||||||
yield frame
|
|
||||||
else:
|
|
||||||
yield frame
|
yield frame
|
||||||
|
return
|
||||||
|
|
||||||
|
# The common case for "pass through" is receiving frames from the LLM that we'll
|
||||||
|
# use to update the "assistant" LLM messages, but also passing the text frames
|
||||||
|
# along to a TTS service to be spoken to the user.
|
||||||
|
if self.pass_through:
|
||||||
|
yield frame
|
||||||
|
|
||||||
|
# Ignore transcription frames from the bot
|
||||||
|
if isinstance(frame, TranscriptionQueueFrame):
|
||||||
|
if frame.participantId == self.bot_participant_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO: split up transcription by participant
|
||||||
|
if self.complete_sentences:
|
||||||
|
self.sentence += frame.text # type: ignore -- the linter thinks this isn't a TextQueueFrame, even though we check it above
|
||||||
|
if self.sentence.endswith((".", "?", "!")):
|
||||||
|
self.messages.append({"role": self.role, "content": self.sentence})
|
||||||
|
self.sentence = ""
|
||||||
|
yield LLMMessagesQueueFrame(self.messages)
|
||||||
|
else:
|
||||||
|
self.messages.append({"role": self.role, "content": frame.text}) # type: ignore -- the linter thinks this isn't a TextQueueFrame, even though we check it above
|
||||||
|
yield LLMMessagesQueueFrame(self.messages)
|
||||||
|
|
||||||
class LLMUserContextAggregator(LLMContextAggregator):
|
class LLMUserContextAggregator(LLMContextAggregator):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ async def main(room_url: str, token):
|
|||||||
transport.mic_enabled = True
|
transport.mic_enabled = True
|
||||||
transport.mic_sample_rate = 16000
|
transport.mic_sample_rate = 16000
|
||||||
transport.camera_enabled = False
|
transport.camera_enabled = False
|
||||||
|
transport.start_transcription = True
|
||||||
|
|
||||||
llm = AzureLLMService()
|
llm = AzureLLMService()
|
||||||
tts = ElevenLabsTTSService(voice_id="ErXwobaYiN019PkySvjV")
|
tts = ElevenLabsTTSService(voice_id="ErXwobaYiN019PkySvjV")
|
||||||
|
|||||||
Reference in New Issue
Block a user