diff --git a/litellm/llms/prompt_templates/factory.py b/litellm/llms/prompt_templates/factory.py
index 06faaf55746..b895573b471 100644
--- a/litellm/llms/prompt_templates/factory.py
+++ b/litellm/llms/prompt_templates/factory.py
@@ -556,7 +556,7 @@ def convert_to_anthropic_image_obj(openai_image_url: str):
)
-def convert_to_anthropic_tool_result(message: dict) -> str:
+def convert_to_anthropic_tool_result(message: dict) -> dict:
"""
OpenAI message with a tool result looks like:
{
@@ -569,64 +569,79 @@ def convert_to_anthropic_tool_result(message: dict) -> str:
"""
Anthropic tool_results look like:
-
- [Successful results]
-
-
- get_current_weather
-
- function result goes here
-
-
-
-
- [Error results]
-
-
- error message goes here
-
-
+ {
+ "role": "user",
+ "content": [
+ {
+ "type": "tool_result",
+ "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
+ "content": "ConnectionError: the weather service API is not available (HTTP 500)",
+ # "is_error": true
+ }
+ ]
+ }
"""
- name = message.get("name")
+ tool_call_id = message.get("tool_call_id")
content = message.get("content")
# We can't determine from openai message format whether it's a successful or
# error call result so default to the successful result template
- anthropic_tool_result = (
- "\n"
- "\n"
- f"{name}\n"
- "\n"
- f"{content}\n"
- "\n"
- "\n"
- ""
- )
+ anthropic_tool_result = {
+ "type": "tool_result",
+ "tool_use_id": tool_call_id,
+ "content": content,
+ }
return anthropic_tool_result
-def convert_to_anthropic_tool_invoke(tool_calls: list) -> str:
- invokes = ""
- for tool in tool_calls:
- if tool["type"] != "function":
- continue
+def convert_to_anthropic_tool_invoke(tool_calls: list) -> list:
+ """
+ OpenAI tool invokes:
+ {
+ "role": "assistant",
+ "content": null,
+ "tool_calls": [
+ {
+ "id": "call_abc123",
+ "type": "function",
+ "function": {
+ "name": "get_current_weather",
+ "arguments": "{\n\"location\": \"Boston, MA\"\n}"
+ }
+ }
+ ]
+ },
+ """
- tool_name = tool["function"]["name"]
- parameters = "".join(
- f"<{param}>{val}{param}>\n"
- for param, val in json.loads(tool["function"]["arguments"]).items()
- )
- invokes += (
- "\n"
- f"{tool_name}\n"
- "\n"
- f"{parameters}"
- "\n"
- "\n"
- )
-
- anthropic_tool_invoke = f"\n{invokes}"
+ """
+ Anthropic tool invokes:
+ {
+ "role": "assistant",
+ "content": [
+ {
+ "type": "text",
+ "text": "To answer this question, I will: 1. Use the get_weather tool to get the current weather in San Francisco. 2. Use the get_time tool to get the current time in the America/Los_Angeles timezone, which covers San Francisco, CA."
+ },
+ {
+ "type": "tool_use",
+ "id": "toolu_01A09q90qw90lq917835lq9",
+ "name": "get_weather",
+ "input": {"location": "San Francisco, CA"}
+ }
+ ]
+ }
+ """
+ anthropic_tool_invoke = [
+ {
+ "type": "tool_use",
+ "id": tool["id"],
+ "name": tool["function"]["name"],
+ "input": json.loads(tool["function"]["arguments"]),
+ }
+ for tool in tool_calls
+ if tool["type"] == "function"
+ ]
return anthropic_tool_invoke
@@ -663,17 +678,12 @@ def anthropic_messages_pt(messages: list):
)
elif m.get("type", "") == "text":
user_content.append({"type": "text", "text": m["text"]})
+ elif messages[msg_i]["role"] == "tool":
+ # OpenAI's tool message content will always be a string
+ user_content.append(convert_to_anthropic_tool_result(messages[msg_i]))
else:
- # Tool message content will always be a string
user_content.append(
- {
- "type": "text",
- "text": (
- convert_to_anthropic_tool_result(messages[msg_i])
- if messages[msg_i]["role"] == "tool"
- else messages[msg_i]["content"]
- ),
- }
+ {"type": "text", "text": messages[msg_i]["content"]}
)
msg_i += 1
@@ -687,14 +697,16 @@ def anthropic_messages_pt(messages: list):
assistant_text = (
messages[msg_i].get("content") or ""
) # either string or none
+ if assistant_text:
+ assistant_content.append({"type": "text", "text": assistant_text})
+
if messages[msg_i].get(
"tool_calls", []
): # support assistant tool invoke convertion
- assistant_text += convert_to_anthropic_tool_invoke(
- messages[msg_i]["tool_calls"]
+ assistant_content.extend(
+ convert_to_anthropic_tool_invoke(messages[msg_i]["tool_calls"])
)
- assistant_content.append({"type": "text", "text": assistant_text})
msg_i += 1
if assistant_content: