diff --git a/examples/foundational/19a-tools-anthropic.py b/examples/foundational/19a-tools-anthropic.py index 8e0fc6bbc..e238de63c 100644 --- a/examples/foundational/19a-tools-anthropic.py +++ b/examples/foundational/19a-tools-anthropic.py @@ -62,7 +62,7 @@ async def main(): ) llm = AnthropicLLMService( - api_key=os.getenv("OPENAI_API_KEY"), + api_key=os.getenv("ANTHROPIC_API_KEY"), model="claude-3-5-sonnet-20240620" ) llm.register_function("get_weather", get_weather) @@ -86,10 +86,12 @@ async def main(): # todo: test with very short initial user message - messages = [{"role": "system", - "content": "You are a helpful assistant who can report the weather in any location in the universe. Respond concisely. Your response will be turned into speech so use only simple words and punctuation."}, - {"role": "user", - "content": " Start the conversation by introducing yourself."}] + # messages = [{"role": "system", + # "content": "You are a helpful assistant who can report the weather in any location in the universe. Respond concisely. Your response will be turned into speech so use only simple words and punctuation."}, + # {"role": "user", + # "content": " Start the conversation by introducing yourself."}] + + messages = [{"role": "user", "content": "Say 'hello' to start the conversation."}] context = OpenAILLMContext(messages, tools) context_aggregator = llm.create_context_aggregator(context) @@ -109,7 +111,7 @@ async def main(): async def on_first_participant_joined(transport, participant): transport.capture_participant_transcription(participant["id"]) # Kick off the conversation. - await task.queue_frames([LLMMessagesFrame(messages)]) + await task.queue_frames([context_aggregator.user().get_context_frame()]) runner = PipelineRunner() diff --git a/examples/foundational/19b-tools-video-anthropic.py b/examples/foundational/19b-tools-video-anthropic.py index 51a321bf9..4ba29ab37 100644 --- a/examples/foundational/19b-tools-video-anthropic.py +++ b/examples/foundational/19b-tools-video-anthropic.py @@ -137,7 +137,8 @@ If you need to use a tool, simply use the tool. Do not tell the user the tool yo """ messages = [{"role": "system", - "content": system_prompt, + "content": system_prompt}, + {"role": "user", "content": "Start the conversation by introducing yourself."}] context = OpenAILLMContext(messages, tools) @@ -161,7 +162,7 @@ If you need to use a tool, simply use the tool. Do not tell the user the tool yo transport.capture_participant_transcription(video_participant_id) transport.capture_participant_video(video_participant_id, framerate=0) # Kick off the conversation. - await task.queue_frames([LLMMessagesFrame(messages)]) + await task.queue_frames([context_aggregator.user().get_context_frame()]) runner = PipelineRunner() await runner.run(task) diff --git a/src/pipecat/services/anthropic.py b/src/pipecat/services/anthropic.py index 5c636b45f..506d71243 100644 --- a/src/pipecat/services/anthropic.py +++ b/src/pipecat/services/anthropic.py @@ -102,13 +102,15 @@ class AnthropicLLMService(LLMService): await self.push_frame(LLMFullResponseStartFrame()) await self.start_processing_metrics() - logger.debug(f"Generating chat: {context.get_messages_for_logging()}") + logger.debug( + f"Generating chat: {context.system} | {context.get_messages_for_logging()}") messages = context.messages await self.start_ttfb_metrics() response = await self._client.messages.create( + system=context.system or [], messages=messages, tools=context.tools or [], model=self._model, @@ -234,12 +236,12 @@ class AnthropicLLMContext(OpenAILLMContext): tools: list[dict] | None = None, tool_choice: dict | None = None, *, - system: str | None = None + system: List | None = None ): super().__init__(messages=messages, tools=tools, tool_choice=tool_choice) self._user_image_request_context = {} - self.system_message = system + self.system = system @classmethod def from_openai_context(cls, openai_context: OpenAILLMContext): @@ -248,23 +250,14 @@ class AnthropicLLMContext(OpenAILLMContext): tools=openai_context.tools, tool_choice=openai_context.tool_choice, ) - # See if we should pull the system message out of our context.messages list. (For - # compatibility with Open AI messages format.) - if self.messages and self.messages[0]["role"] == "system": - if len(self.messages) == 1: - # If we have only have a system message in the list, all we can really do - # without introducing too much magic is change the role to "user". - self.messages[0]["role"] = "user" - else: - # If we have more than one message, we'll pull the system message out of the - # list. - self.system_message = self.messages[0]["content"] - self.messages.pop(0) + self._restructure_from_openai_messages() return self @classmethod def from_messages(cls, messages: List[dict]) -> "AnthropicLLMContext": - return cls(messages=messages) + self = cls(messages=messages) + self._restructure_from_openai_messages() + return self @classmethod def from_image_frame(cls, frame: VisionImageRawFrame) -> "AnthropicLLMContext": @@ -276,6 +269,10 @@ class AnthropicLLMContext(OpenAILLMContext): text=frame.text) return context + def set_messages(self, messages: List): + self._messages[:] = messages + self._restructure_from_openai_messages() + def add_image_frame_message( self, *, format: str, size: tuple[int, int], image: bytes, text: str = None): buffer = io.BytesIO() @@ -316,6 +313,20 @@ class AnthropicLLMContext(OpenAILLMContext): except Exception as e: logger.error(f"Error adding message: {e}") + def _restructure_from_openai_messages(self): + # See if we should pull the system message out of our context.messages list. (For + # compatibility with Open AI messages format.) + if self.messages and self.messages[0]["role"] == "system": + if len(self.messages) == 1: + # If we have only have a system message in the list, all we can really do + # without introducing too much magic is change the role to "user". + self.messages[0]["role"] = "user" + else: + # If we have more than one message, we'll pull the system message out of the + # list. + self.system = self.messages[0]["content"] + self.messages.pop(0) + def get_messages_for_logging(self) -> str: msgs = [] for message in self.messages: