371 lines
13 KiB
Python
371 lines
13 KiB
Python
#
|
|
# Copyright (c) 2024, Daily
|
|
#
|
|
# SPDX-License-Identifier: BSD 2-Clause License
|
|
#
|
|
|
|
import unittest
|
|
|
|
from pipecat.frames.frames import (
|
|
BotInterruptionFrame,
|
|
InterimTranscriptionFrame,
|
|
LLMFullResponseEndFrame,
|
|
LLMFullResponseStartFrame,
|
|
StartInterruptionFrame,
|
|
StopInterruptionFrame,
|
|
TextFrame,
|
|
TranscriptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
UserStoppedSpeakingFrame,
|
|
)
|
|
from pipecat.processors.aggregators.llm_response import (
|
|
LLMAssistantContextAggregator,
|
|
LLMFullResponseAggregator,
|
|
LLMUserContextAggregator,
|
|
)
|
|
from pipecat.processors.aggregators.openai_llm_context import (
|
|
OpenAILLMContext,
|
|
OpenAILLMContextFrame,
|
|
)
|
|
from tests.utils import run_test
|
|
|
|
|
|
class TestLLMUserContextAggregator(unittest.IsolatedAsyncioTestCase):
|
|
# S E ->
|
|
async def test_s_e(self):
|
|
"""S E case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
]
|
|
await run_test(context_aggregator, frames_to_send, expected_returned_frames)
|
|
|
|
# S T E -> T
|
|
async def test_s_t_e(self):
|
|
"""S T E case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
TranscriptionFrame("Hello", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
await run_test(context_aggregator, frames_to_send, expected_returned_frames)
|
|
|
|
# S I T E -> T
|
|
async def test_s_i_t_e(self):
|
|
"""S I T E case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
InterimTranscriptionFrame("This", "", ""),
|
|
TranscriptionFrame("This is a test", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
await run_test(context_aggregator, frames_to_send, expected_returned_frames)
|
|
|
|
# S I E T -> T
|
|
async def test_s_i_e_t(self):
|
|
"""S I E T case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
InterimTranscriptionFrame("This", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
TranscriptionFrame("This is a test", "", ""),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
await run_test(context_aggregator, frames_to_send, expected_returned_frames)
|
|
|
|
# S I E I T -> T
|
|
async def test_s_i_e_i_t(self):
|
|
"""S I E I T case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
InterimTranscriptionFrame("This", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
InterimTranscriptionFrame("This is", "", ""),
|
|
TranscriptionFrame("This is a test", "", ""),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
await run_test(context_aggregator, frames_to_send, expected_returned_frames)
|
|
|
|
# S E T -> T
|
|
async def test_s_e_t(self):
|
|
"""S E case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
TranscriptionFrame("This is a test", "", ""),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
await run_test(context_aggregator, frames_to_send, expected_returned_frames)
|
|
|
|
# S E I T -> T
|
|
async def test_s_e_i_t(self):
|
|
"""S E I T case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
InterimTranscriptionFrame("This", "", ""),
|
|
TranscriptionFrame("This is a test", "", ""),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
await run_test(context_aggregator, frames_to_send, expected_returned_frames)
|
|
|
|
# S T1 I E S T2 E -> "T1 T2"
|
|
async def test_s_t1_i_e_s_t2_e(self):
|
|
"""S T1 I E S T2 E case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
TranscriptionFrame("T1", "", ""),
|
|
InterimTranscriptionFrame("", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
TranscriptionFrame("T2", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
]
|
|
expected_returned_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
(received_down, _) = await run_test(
|
|
context_aggregator, frames_to_send, expected_returned_frames
|
|
)
|
|
assert received_down[-1].context.messages[-1]["content"] == "T1 T2"
|
|
|
|
# S I E T1 I T2 -> T1 Interruption T2
|
|
async def test_s_i_e_t1_i_t2(self):
|
|
"""S I E T1 I T2 case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
InterimTranscriptionFrame("", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
TranscriptionFrame("T1", "", ""),
|
|
InterimTranscriptionFrame("", "", ""),
|
|
TranscriptionFrame("T2", "", ""),
|
|
]
|
|
expected_down_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
expected_up_frames = [
|
|
BotInterruptionFrame,
|
|
]
|
|
(received_down, _) = await run_test(
|
|
context_aggregator, frames_to_send, expected_down_frames, expected_up_frames
|
|
)
|
|
assert received_down[-1].context.messages[-2]["content"] == "T1"
|
|
assert received_down[-1].context.messages[-1]["content"] == "T2"
|
|
|
|
# S T1 E T2 -> T1 Interruption T2
|
|
async def test_s_t1_e_t2(self):
|
|
"""S T1 E T2 case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
TranscriptionFrame("T1", "", ""),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
TranscriptionFrame("T2", "", ""),
|
|
]
|
|
expected_down_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
expected_up_frames = [
|
|
BotInterruptionFrame,
|
|
]
|
|
(received_down, _) = await run_test(
|
|
context_aggregator, frames_to_send, expected_down_frames, expected_up_frames
|
|
)
|
|
assert received_down[-1].context.messages[-2]["content"] == "T1"
|
|
assert received_down[-1].context.messages[-1]["content"] == "T2"
|
|
|
|
# S E T1 T2 -> T1 Interruption T2
|
|
async def test_s_e_t1_t2(self):
|
|
"""S E T1 T2 case"""
|
|
context_aggregator = LLMUserContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
StartInterruptionFrame(),
|
|
UserStartedSpeakingFrame(),
|
|
StopInterruptionFrame(),
|
|
UserStoppedSpeakingFrame(),
|
|
TranscriptionFrame("T1", "", ""),
|
|
TranscriptionFrame("T2", "", ""),
|
|
]
|
|
expected_down_frames = [
|
|
StartInterruptionFrame,
|
|
UserStartedSpeakingFrame,
|
|
StopInterruptionFrame,
|
|
UserStoppedSpeakingFrame,
|
|
OpenAILLMContextFrame,
|
|
OpenAILLMContextFrame,
|
|
]
|
|
expected_up_frames = [
|
|
BotInterruptionFrame,
|
|
]
|
|
(received_down, _) = await run_test(
|
|
context_aggregator, frames_to_send, expected_down_frames, expected_up_frames
|
|
)
|
|
assert received_down[-1].context.messages[-2]["content"] == "T1"
|
|
assert received_down[-1].context.messages[-1]["content"] == "T2"
|
|
|
|
|
|
class TestLLMAssistantContextAggregator(unittest.IsolatedAsyncioTestCase):
|
|
# S T E -> T
|
|
async def test_s_t_e(self):
|
|
"""S T E case"""
|
|
context_aggregator = LLMAssistantContextAggregator(
|
|
OpenAILLMContext(messages=[{"role": "", "content": ""}])
|
|
)
|
|
frames_to_send = [
|
|
LLMFullResponseStartFrame(),
|
|
TextFrame("Hello this is Pipecat speaking!"),
|
|
TextFrame("How are you?"),
|
|
LLMFullResponseEndFrame(),
|
|
]
|
|
expected_returned_frames = [
|
|
LLMFullResponseStartFrame,
|
|
OpenAILLMContextFrame,
|
|
LLMFullResponseEndFrame,
|
|
]
|
|
(received_down, _) = await run_test(
|
|
context_aggregator, frames_to_send, expected_returned_frames
|
|
)
|
|
assert (
|
|
received_down[-2].context.messages[-1]["content"]
|
|
== "Hello this is Pipecat speaking! How are you?"
|
|
)
|
|
|
|
|
|
class TestLLMFullResponseAggregator(unittest.IsolatedAsyncioTestCase):
|
|
# S T E -> T
|
|
async def test_s_t_e(self):
|
|
"""S T E case"""
|
|
response_aggregator = LLMFullResponseAggregator()
|
|
frames_to_send = [
|
|
LLMFullResponseStartFrame(),
|
|
TextFrame("Hello "),
|
|
TextFrame("this "),
|
|
TextFrame("is "),
|
|
TextFrame("Pipecat!"),
|
|
LLMFullResponseEndFrame(),
|
|
]
|
|
expected_returned_frames = [
|
|
LLMFullResponseStartFrame,
|
|
TextFrame,
|
|
LLMFullResponseEndFrame,
|
|
]
|
|
(received_down, _) = await run_test(
|
|
response_aggregator, frames_to_send, expected_returned_frames
|
|
)
|
|
assert received_down[-2].text == "Hello this is Pipecat!"
|