forked from phoenix/litellm-mirror
fix(anthropic.py): handle multiple system prompts
This commit is contained in:
parent
de1f348453
commit
691a83b7dc
3 changed files with 45 additions and 14 deletions
|
@ -131,18 +131,24 @@ def completion(
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Separate system prompt from rest of message
|
# Separate system prompt from rest of message
|
||||||
system_prompt_idx: Optional[int] = None
|
system_prompt_indices = []
|
||||||
|
system_prompt = ""
|
||||||
for idx, message in enumerate(messages):
|
for idx, message in enumerate(messages):
|
||||||
if message["role"] == "system":
|
if message["role"] == "system":
|
||||||
optional_params["system"] = message["content"]
|
system_prompt += message["content"]
|
||||||
system_prompt_idx = idx
|
system_prompt_indices.append(idx)
|
||||||
break
|
if len(system_prompt_indices) > 0:
|
||||||
if system_prompt_idx is not None:
|
for idx in reversed(system_prompt_indices):
|
||||||
messages.pop(system_prompt_idx)
|
messages.pop(idx)
|
||||||
|
if len(system_prompt) > 0:
|
||||||
|
optional_params["system"] = system_prompt
|
||||||
# Format rest of message according to anthropic guidelines
|
# Format rest of message according to anthropic guidelines
|
||||||
|
try:
|
||||||
messages = prompt_factory(
|
messages = prompt_factory(
|
||||||
model=model, messages=messages, custom_llm_provider="anthropic"
|
model=model, messages=messages, custom_llm_provider="anthropic"
|
||||||
)
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise AnthropicError(status_code=400, message=str(e))
|
||||||
|
|
||||||
## Load Config
|
## Load Config
|
||||||
config = litellm.AnthropicConfig.get_config()
|
config = litellm.AnthropicConfig.get_config()
|
||||||
|
|
|
@ -5,6 +5,7 @@ from jinja2 import Template, exceptions, Environment, meta
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any
|
||||||
import imghdr, base64
|
import imghdr, base64
|
||||||
from typing import List
|
from typing import List
|
||||||
|
import litellm
|
||||||
|
|
||||||
|
|
||||||
def default_pt(messages):
|
def default_pt(messages):
|
||||||
|
@ -642,11 +643,12 @@ def anthropic_messages_pt(messages: list):
|
||||||
"""
|
"""
|
||||||
# add role=tool support to allow function call result/error submission
|
# add role=tool support to allow function call result/error submission
|
||||||
user_message_types = {"user", "tool"}
|
user_message_types = {"user", "tool"}
|
||||||
# reformat messages to ensure user/assistant are alternating, if there's either 2 consecutive 'user' messages or 2 consecutive 'assistant' message, add a blank 'user' or 'assistant' message to ensure compatibility
|
# reformat messages to ensure user/assistant are alternating, if there's either 2 consecutive 'user' messages or 2 consecutive 'assistant' message, merge them.
|
||||||
new_messages = []
|
new_messages = []
|
||||||
msg_i = 0
|
msg_i = 0
|
||||||
while msg_i < len(messages):
|
while msg_i < len(messages):
|
||||||
user_content = []
|
user_content = []
|
||||||
|
## MERGE CONSECUTIVE USER CONTENT ##
|
||||||
while msg_i < len(messages) and messages[msg_i]["role"] in user_message_types:
|
while msg_i < len(messages) and messages[msg_i]["role"] in user_message_types:
|
||||||
if isinstance(messages[msg_i]["content"], list):
|
if isinstance(messages[msg_i]["content"], list):
|
||||||
for m in messages[msg_i]["content"]:
|
for m in messages[msg_i]["content"]:
|
||||||
|
@ -680,6 +682,7 @@ def anthropic_messages_pt(messages: list):
|
||||||
new_messages.append({"role": "user", "content": user_content})
|
new_messages.append({"role": "user", "content": user_content})
|
||||||
|
|
||||||
assistant_content = []
|
assistant_content = []
|
||||||
|
## MERGE CONSECUTIVE ASSISTANT CONTENT ##
|
||||||
while msg_i < len(messages) and messages[msg_i]["role"] == "assistant":
|
while msg_i < len(messages) and messages[msg_i]["role"] == "assistant":
|
||||||
assistant_text = (
|
assistant_text = (
|
||||||
messages[msg_i].get("content") or ""
|
messages[msg_i].get("content") or ""
|
||||||
|
@ -697,10 +700,22 @@ def anthropic_messages_pt(messages: list):
|
||||||
if assistant_content:
|
if assistant_content:
|
||||||
new_messages.append({"role": "assistant", "content": assistant_content})
|
new_messages.append({"role": "assistant", "content": assistant_content})
|
||||||
|
|
||||||
|
if (
|
||||||
|
msg_i < len(messages)
|
||||||
|
and messages[msg_i]["role"] != user_message_types
|
||||||
|
and messages[msg_i]["role"] != "assistant"
|
||||||
|
):
|
||||||
|
raise Exception(f"Invalid role passed in - {messages[msg_i]}")
|
||||||
|
|
||||||
if new_messages[0]["role"] != "user":
|
if new_messages[0]["role"] != "user":
|
||||||
|
if litellm.modify_params:
|
||||||
new_messages.insert(
|
new_messages.insert(
|
||||||
0, {"role": "user", "content": [{"type": "text", "text": "."}]}
|
0, {"role": "user", "content": [{"type": "text", "text": "."}]}
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
raise Exception(
|
||||||
|
"Invalid first message. Should always start with 'role'='user' for Anthropic. System prompt is sent separately for Anthropic. set 'litellm.modify_params = True' or 'litellm_settings:modify_params = True' on proxy, to insert a placeholder user message - '.' as the first message, "
|
||||||
|
)
|
||||||
|
|
||||||
if new_messages[-1]["role"] == "assistant":
|
if new_messages[-1]["role"] == "assistant":
|
||||||
for content in new_messages[-1]["content"]:
|
for content in new_messages[-1]["content"]:
|
||||||
|
|
|
@ -7223,7 +7223,17 @@ def exception_type(
|
||||||
message=f"AnthropicException - {original_exception.message}",
|
message=f"AnthropicException - {original_exception.message}",
|
||||||
llm_provider="anthropic",
|
llm_provider="anthropic",
|
||||||
model=model,
|
model=model,
|
||||||
response=original_exception.response,
|
response=(
|
||||||
|
original_exception.response
|
||||||
|
if hasattr(original_exception, "response")
|
||||||
|
else httpx.Response(
|
||||||
|
status_code=500,
|
||||||
|
request=httpx.Request(
|
||||||
|
method="POST",
|
||||||
|
url="https://docs.anthropic.com/claude/reference/messages_post",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
exception_mapping_worked = True
|
exception_mapping_worked = True
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue