test(test_completion.py): add testing for anthropic vision calling

This commit is contained in:
Krrish Dholakia 2024-03-04 13:34:49 -08:00
parent 33afa53353
commit edda2d9293
4 changed files with 81 additions and 5 deletions

View file

@ -499,7 +499,11 @@ def convert_to_anthropic_image_obj(openai_image_url: str):
# Infer image format from the URL # Infer image format from the URL
image_format = openai_image_url.split("data:image/")[1].split(";base64,")[0] image_format = openai_image_url.split("data:image/")[1].split(";base64,")[0]
return {"type": "base64", "media_type": image_format, "data": base64_data} return {
"type": "base64",
"media_type": f"image/{image_format}",
"data": base64_data,
}
def anthropic_messages_pt(messages: list): def anthropic_messages_pt(messages: list):
@ -515,10 +519,35 @@ def anthropic_messages_pt(messages: list):
last_assistant_message_idx: Optional[int] = None last_assistant_message_idx: Optional[int] = None
# 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, add a blank 'user' or 'assistant' message to ensure compatibility
new_messages = [] new_messages = []
if len(messages) == 1:
# check if the message is a user message
if messages[0]["role"] == "assistant":
new_messages.append({"role": "user", "content": ""})
# check if content is a list (vision)
if isinstance(messages[0]["content"], list): # vision input
new_content = []
for m in messages[0]["content"]:
if m.get("type", "") == "image_url":
new_content.append(
{
"type": "image",
"source": convert_to_anthropic_image_obj(
m["image_url"]["url"]
),
}
)
elif m.get("type", "") == "text":
new_content.append({"type": "text", "text": m["text"]})
new_messages.append({"role": messages[0]["role"], "content": new_content}) # type: ignore
else:
new_messages.append(messages[0])
return new_messages
for i in range(len(messages) - 1): # type: ignore for i in range(len(messages) - 1): # type: ignore
if i == 0 and messages[i]["role"] == "assistant": if i == 0 and messages[i]["role"] == "assistant":
new_messages.append({"role": "user", "content": ""}) new_messages.append({"role": "user", "content": ""})
if isinstance(messages[i]["content"], list): # vision input if isinstance(messages[i]["content"], list): # vision input
new_content = [] new_content = []
for m in messages[i]["content"]: for m in messages[i]["content"]:
@ -546,8 +575,6 @@ def anthropic_messages_pt(messages: list):
if messages[i]["role"] == "assistant": if messages[i]["role"] == "assistant":
last_assistant_message_idx = i last_assistant_message_idx = i
new_messages.append(messages[-1])
if last_assistant_message_idx is not None: if last_assistant_message_idx is not None:
new_messages[last_assistant_message_idx]["content"] = new_messages[ new_messages[last_assistant_message_idx]["content"] = new_messages[
last_assistant_message_idx last_assistant_message_idx

View file

@ -351,7 +351,7 @@ def test_gemini_pro_vision_base64():
load_vertex_ai_credentials() load_vertex_ai_credentials()
litellm.set_verbose = True litellm.set_verbose = True
litellm.num_retries = 3 litellm.num_retries = 3
image_path = "cached_logo.jpg" image_path = "../proxy/cached_logo.jpg"
# Getting the base64 string # Getting the base64 string
base64_image = encode_image(image_path) base64_image = encode_image(image_path)
resp = litellm.completion( resp = litellm.completion(

View file

@ -159,6 +159,51 @@ def test_completion_claude_3_stream():
pytest.fail(f"Error occurred: {e}") pytest.fail(f"Error occurred: {e}")
def encode_image(image_path):
import base64
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode("utf-8")
@pytest.mark.skip(
reason="we already test claude-3, this is just another way to pass images"
)
def test_completion_claude_3_base64():
try:
litellm.set_verbose = True
litellm.num_retries = 3
image_path = "../proxy/cached_logo.jpg"
# Getting the base64 string
base64_image = encode_image(image_path)
resp = litellm.completion(
model="anthropic/claude-3-opus-20240229",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Whats in this image?"},
{
"type": "image_url",
"image_url": {
"url": "data:image/jpeg;base64," + base64_image
},
},
],
}
],
)
print(f"\nResponse: {resp}")
prompt_tokens = resp.usage.prompt_tokens
raise Exception("it worked!")
except Exception as e:
if "500 Internal error encountered.'" in str(e):
pass
else:
pytest.fail(f"An exception occurred - {str(e)}")
def test_completion_mistral_api(): def test_completion_mistral_api():
try: try:
litellm.set_verbose = True litellm.set_verbose = True

View file

@ -200,6 +200,10 @@ def map_finish_reason(
return "content_filter" return "content_filter"
elif finish_reason == "STOP": # vertex ai elif finish_reason == "STOP": # vertex ai
return "stop" return "stop"
elif finish_reason == "end_turn" or finish_reason == "stop_sequence": # anthropic
return "stop"
elif finish_reason == "max_tokens": # anthropic
return "length"
return finish_reason return finish_reason