import unittest from models import AssistantConfig from pipecat.frames.frames import LLMContextFrame from pipecat.processors.aggregators.llm_context import LLMContext from pipecat.processors.frame_processor import FrameDirection from services.pipecat.pipeline import ( KNOWLEDGE_CONTEXT_MARKER, KnowledgeRetrievalProcessor, UserTurnRoutingProcessor, _knowledge_tool_description, ) class KnowledgeToolDescriptionTest(unittest.TestCase): def test_includes_bound_knowledge_scope(self): description = _knowledge_tool_description( AssistantConfig( knowledge_base_name="产品服务知识库", knowledge_base_description="产品价格、售后政策和退换货条件", ) ) self.assertIn("知识库名称:产品服务知识库", description) self.assertIn("资料适用范围:产品价格、售后政策和退换货条件", description) self.assertIn("与该范围无关的问题不要调用", description) def test_falls_back_when_metadata_is_empty(self): description = _knowledge_tool_description(AssistantConfig()) self.assertEqual( description, "在当前助手绑定的知识库中检索与问题最相关的资料片段。", ) def test_compacts_and_limits_description(self): description = _knowledge_tool_description( AssistantConfig(knowledge_base_description=("范围\n 内容 " * 200)) ) self.assertNotIn("\n ", description) self.assertLess(len(description), 1000) def test_workflow_knowledge_uses_system_role(self): processor = KnowledgeRetrievalProcessor(None) messages = [ {"role": "assistant", "content": "你好"}, { "role": "developer", "content": f"{KNOWLEDGE_CONTEXT_MARKER}\n旧检索结果", }, ] processor._set_context( messages, f"{KNOWLEDGE_CONTEXT_MARKER}\n新检索结果", ) self.assertEqual(messages[0]["role"], "system") self.assertIn("新检索结果", messages[0]["content"]) self.assertFalse(any(message["role"] == "developer" for message in messages)) class UserTurnRoutingProcessorTest(unittest.IsolatedAsyncioTestCase): async def test_routes_each_user_message_once_before_response_run(self): class FakeBrain: def __init__(self): self.turns = [] async def on_user_turn_end(self, content): self.turns.append(content) return True brain = FakeBrain() processor = UserTurnRoutingProcessor(brain) forwarded = [] async def push_frame(frame, direction): forwarded.append((frame, direction)) processor.push_frame = push_frame context = LLMContext(messages=[{"role": "user", "content": "我叫李白"}]) frame = LLMContextFrame(context) await processor.process_frame(frame, FrameDirection.DOWNSTREAM) self.assertEqual(brain.turns, ["我叫李白"]) self.assertEqual(forwarded, []) # A queued LLMRunFrame after the transition uses the same context. It # must reach the target Agent without invoking routing a second time. await processor.process_frame(frame, FrameDirection.DOWNSTREAM) self.assertEqual(brain.turns, ["我叫李白"]) self.assertEqual(forwarded, [(frame, FrameDirection.DOWNSTREAM)]) if __name__ == "__main__": unittest.main()