# @pytest.mark.skip(reason="AWS Suspended Account") import sys, os import traceback from dotenv import load_dotenv load_dotenv() import os, io sys.path.insert( 0, os.path.abspath("../..") ) # Adds the parent directory to the system path import pytest import litellm from litellm import embedding, completion, completion_cost, Timeout, ModelResponse from litellm import RateLimitError from litellm.llms.custom_httpx.http_handler import HTTPHandler from unittest.mock import patch, AsyncMock, Mock # litellm.num_retries = 3 litellm.cache = None litellm.success_callback = [] user_message = "Write a short poem about the sky" messages = [{"content": user_message, "role": "user"}] @pytest.fixture(autouse=True) def reset_callbacks(): print("\npytest fixture - resetting callbacks") litellm.success_callback = [] litellm._async_success_callback = [] litellm.failure_callback = [] litellm.callbacks = [] def test_completion_bedrock_claude_completion_auth(): print("calling bedrock claude completion params auth") import os aws_access_key_id = os.environ["AWS_ACCESS_KEY_ID"] aws_secret_access_key = os.environ["AWS_SECRET_ACCESS_KEY"] aws_region_name = os.environ["AWS_REGION_NAME"] os.environ.pop("AWS_ACCESS_KEY_ID", None) os.environ.pop("AWS_SECRET_ACCESS_KEY", None) os.environ.pop("AWS_REGION_NAME", None) try: response = completion( model="bedrock/anthropic.claude-instant-v1", messages=messages, max_tokens=10, temperature=0.1, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, aws_region_name=aws_region_name, ) # Add any assertions here to check the response print(response) os.environ["AWS_ACCESS_KEY_ID"] = aws_access_key_id os.environ["AWS_SECRET_ACCESS_KEY"] = aws_secret_access_key os.environ["AWS_REGION_NAME"] = aws_region_name except RateLimitError: pass except Exception as e: pytest.fail(f"Error occurred: {e}") # test_completion_bedrock_claude_completion_auth() def test_completion_bedrock_claude_2_1_completion_auth(): print("calling bedrock claude 2.1 completion params auth") import os aws_access_key_id = os.environ["AWS_ACCESS_KEY_ID"] aws_secret_access_key = os.environ["AWS_SECRET_ACCESS_KEY"] aws_region_name = os.environ["AWS_REGION_NAME"] os.environ.pop("AWS_ACCESS_KEY_ID", None) os.environ.pop("AWS_SECRET_ACCESS_KEY", None) os.environ.pop("AWS_REGION_NAME", None) try: response = completion( model="bedrock/anthropic.claude-v2:1", messages=messages, max_tokens=10, temperature=0.1, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, aws_region_name=aws_region_name, ) # Add any assertions here to check the response print(response) os.environ["AWS_ACCESS_KEY_ID"] = aws_access_key_id os.environ["AWS_SECRET_ACCESS_KEY"] = aws_secret_access_key os.environ["AWS_REGION_NAME"] = aws_region_name except RateLimitError: pass except Exception as e: pytest.fail(f"Error occurred: {e}") # test_completion_bedrock_claude_2_1_completion_auth() def test_completion_bedrock_claude_external_client_auth(): print("\ncalling bedrock claude external client auth") import os aws_access_key_id = os.environ["AWS_ACCESS_KEY_ID"] aws_secret_access_key = os.environ["AWS_SECRET_ACCESS_KEY"] aws_region_name = os.environ["AWS_REGION_NAME"] os.environ.pop("AWS_ACCESS_KEY_ID", None) os.environ.pop("AWS_SECRET_ACCESS_KEY", None) os.environ.pop("AWS_REGION_NAME", None) try: import boto3 litellm.set_verbose = True bedrock = boto3.client( service_name="bedrock-runtime", region_name=aws_region_name, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, endpoint_url=f"https://bedrock-runtime.{aws_region_name}.amazonaws.com", ) response = completion( model="bedrock/anthropic.claude-instant-v1", messages=messages, max_tokens=10, temperature=0.1, aws_bedrock_client=bedrock, ) # Add any assertions here to check the response print(response) os.environ["AWS_ACCESS_KEY_ID"] = aws_access_key_id os.environ["AWS_SECRET_ACCESS_KEY"] = aws_secret_access_key os.environ["AWS_REGION_NAME"] = aws_region_name except RateLimitError: pass except Exception as e: pytest.fail(f"Error occurred: {e}") # test_completion_bedrock_claude_external_client_auth() @pytest.mark.skip(reason="Expired token, need to renew") def test_completion_bedrock_claude_sts_client_auth(): print("\ncalling bedrock claude external client auth") import os aws_access_key_id = os.environ["AWS_TEMP_ACCESS_KEY_ID"] aws_secret_access_key = os.environ["AWS_TEMP_SECRET_ACCESS_KEY"] aws_region_name = os.environ["AWS_REGION_NAME"] aws_role_name = os.environ["AWS_TEMP_ROLE_NAME"] try: import boto3 litellm.set_verbose = True response = completion( model="bedrock/anthropic.claude-instant-v1", messages=messages, max_tokens=10, temperature=0.1, aws_region_name=aws_region_name, aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, aws_role_name=aws_role_name, aws_session_name="my-test-session", ) response = embedding( model="cohere.embed-multilingual-v3", input=["hello world"], aws_region_name="us-east-1", aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, aws_role_name=aws_role_name, aws_session_name="my-test-session", ) response = completion( model="gpt-3.5-turbo", messages=messages, aws_region_name="us-east-1", aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, aws_role_name=aws_role_name, aws_session_name="my-test-session", ) # Add any assertions here to check the response print(response) except RateLimitError: pass except Exception as e: pytest.fail(f"Error occurred: {e}") # test_completion_bedrock_claude_sts_client_auth() @pytest.mark.skip(reason="We don't have Circle CI OIDC credentials as yet") def test_completion_bedrock_claude_sts_oidc_auth(): print("\ncalling bedrock claude with oidc auth") import os aws_web_identity_token = "oidc/circleci_v2/" aws_region_name = os.environ["AWS_REGION_NAME"] aws_role_name = os.environ["AWS_TEMP_ROLE_NAME"] try: litellm.set_verbose = True response = completion( model="bedrock/anthropic.claude-instant-v1", messages=messages, max_tokens=10, temperature=0.1, aws_region_name=aws_region_name, aws_web_identity_token=aws_web_identity_token, aws_role_name=aws_role_name, aws_session_name="my-test-session", ) # Add any assertions here to check the response print(response) except RateLimitError: pass except Exception as e: pytest.fail(f"Error occurred: {e}") def test_bedrock_claude_3(): try: litellm.set_verbose = True data = { "max_tokens": 100, "stream": False, "temperature": 0.3, "messages": [ {"role": "user", "content": "Hi"}, {"role": "assistant", "content": "Hi"}, { "role": "user", "content": [ {"text": "describe this image", "type": "text"}, { "image_url": { "detail": "high", "url": "data:image/png;base64,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", }, "type": "image_url", }, ], }, ], } response: ModelResponse = completion( model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", num_retries=3, # messages=messages, # max_tokens=10, # temperature=0.78, **data, ) # Add any assertions here to check the response assert len(response.choices) > 0 assert len(response.choices[0].message.content) > 0 except RateLimitError: pass except Exception as e: pytest.fail(f"Error occurred: {e}") def test_bedrock_claude_3_tool_calling(): try: litellm.set_verbose = True tools = [ { "type": "function", "function": { "name": "get_current_weather", "description": "Get the current weather in a given location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city and state, e.g. San Francisco, CA", }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], }, }, "required": ["location"], }, }, } ] messages = [ { "role": "user", "content": "What's the weather like in Boston today in fahrenheit?", } ] response: ModelResponse = completion( model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", messages=messages, tools=tools, tool_choice="auto", ) print(f"response: {response}") # Add any assertions here to check the response assert isinstance(response.choices[0].message.tool_calls[0].function.name, str) assert isinstance( response.choices[0].message.tool_calls[0].function.arguments, str ) messages.append( response.choices[0].message.model_dump() ) # Add assistant tool invokes tool_result = ( '{"location": "Boston", "temperature": "72", "unit": "fahrenheit"}' ) # Add user submitted tool results in the OpenAI format messages.append( { "tool_call_id": response.choices[0].message.tool_calls[0].id, "role": "tool", "name": response.choices[0].message.tool_calls[0].function.name, "content": tool_result, } ) # In the second response, Claude should deduce answer from tool results second_response = completion( model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", messages=messages, tools=tools, tool_choice="auto", ) print(f"second response: {second_response}") assert isinstance(second_response.choices[0].message.content, str) except RateLimitError: pass except Exception as 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="bedrock/anthropic.claude-3-sonnet-20240229-v1:0", messages=[ { "role": "user", "content": [ {"type": "text", "text": "Whats in this image?"}, { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64," + base64_image }, }, ], } ], ) 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_provisioned_throughput(): try: litellm.set_verbose = True import botocore, json, io import botocore.session from botocore.stub import Stubber bedrock_client = botocore.session.get_session().create_client( "bedrock-runtime", region_name="us-east-1" ) expected_params = { "accept": "application/json", "body": '{"prompt": "\\n\\nHuman: Hello, how are you?\\n\\nAssistant: ", ' '"max_tokens_to_sample": 256}', "contentType": "application/json", "modelId": "provisioned-model-arn", } response_from_bedrock = { "body": io.StringIO( json.dumps( { "completion": " Here is a short poem about the sky:", "stop_reason": "max_tokens", "stop": None, } ) ), "contentType": "contentType", "ResponseMetadata": {"HTTPStatusCode": 200}, } with Stubber(bedrock_client) as stubber: stubber.add_response( "invoke_model", service_response=response_from_bedrock, expected_params=expected_params, ) response = litellm.completion( model="bedrock/anthropic.claude-instant-v1", model_id="provisioned-model-arn", messages=[{"content": "Hello, how are you?", "role": "user"}], aws_bedrock_client=bedrock_client, ) print("response stubbed", response) except Exception as e: pytest.fail(f"Error occurred: {e}") # test_provisioned_throughput() def test_completion_bedrock_mistral_completion_auth(): print("calling bedrock mistral completion params auth") import os # aws_access_key_id = os.environ["AWS_ACCESS_KEY_ID"] # aws_secret_access_key = os.environ["AWS_SECRET_ACCESS_KEY"] # aws_region_name = os.environ["AWS_REGION_NAME"] # os.environ.pop("AWS_ACCESS_KEY_ID", None) # os.environ.pop("AWS_SECRET_ACCESS_KEY", None) # os.environ.pop("AWS_REGION_NAME", None) try: response: ModelResponse = completion( model="bedrock/mistral.mistral-7b-instruct-v0:2", messages=messages, max_tokens=10, temperature=0.1, ) # type: ignore # Add any assertions here to check the response assert len(response.choices) > 0 assert len(response.choices[0].message.content) > 0 # os.environ["AWS_ACCESS_KEY_ID"] = aws_access_key_id # os.environ["AWS_SECRET_ACCESS_KEY"] = aws_secret_access_key # os.environ["AWS_REGION_NAME"] = aws_region_name except RateLimitError: pass except Exception as e: pytest.fail(f"Error occurred: {e}") # test_completion_bedrock_mistral_completion_auth() def test_bedrock_ptu(): """ Check if a url with 'modelId' passed in, is created correctly Reference: https://github.com/BerriAI/litellm/issues/3805 """ client = HTTPHandler() with patch.object(client, "post", new=Mock()) as mock_client_post: litellm.set_verbose = True from openai.types.chat import ChatCompletion model_id = ( "arn:aws:bedrock:us-west-2:888602223428:provisioned-model/8fxff74qyhs3" ) try: response = litellm.completion( model="bedrock/anthropic.claude-instant-v1", messages=[{"role": "user", "content": "What's AWS?"}], model_id=model_id, client=client, ) except Exception as e: pass assert "url" in mock_client_post.call_args.kwargs assert ( mock_client_post.call_args.kwargs["url"] == "https://bedrock-runtime.us-west-2.amazonaws.com/model/arn%3Aaws%3Abedrock%3Aus-west-2%3A888602223428%3Aprovisioned-model%2F8fxff74qyhs3/invoke" ) mock_client_post.assert_called_once() def test_bedrock_extra_headers(): """ Check if a url with 'modelId' passed in, is created correctly Reference: https://github.com/BerriAI/litellm/issues/3805 """ client = HTTPHandler() with patch.object(client, "post", new=Mock()) as mock_client_post: litellm.set_verbose = True from openai.types.chat import ChatCompletion try: response = litellm.completion( model="anthropic.claude-3-sonnet-20240229-v1:0", messages=[{"role": "user", "content": "What's AWS?"}], client=client, extra_headers={"test": "hello world"}, ) except Exception as e: pass print(f"mock_client_post.call_args: {mock_client_post.call_args}") assert "test" in mock_client_post.call_args.kwargs["headers"] assert mock_client_post.call_args.kwargs["headers"]["test"] == "hello world" mock_client_post.assert_called_once()