Added LiteLLM to the stack
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
# Ensure the project root is on the import path so `litellm` can be imported when
|
||||
# tests are executed from any working directory.
|
||||
sys.path.insert(0, os.path.abspath("../../../../../.."))
|
||||
|
||||
from litellm.llms.bedrock.chat.invoke_transformations.anthropic_claude3_transformation import (
|
||||
AmazonAnthropicClaudeConfig,
|
||||
)
|
||||
|
||||
|
||||
def test_get_supported_params_thinking():
|
||||
config = AmazonAnthropicClaudeConfig()
|
||||
params = config.get_supported_openai_params(
|
||||
model="anthropic.claude-sonnet-4-20250514-v1:0"
|
||||
)
|
||||
assert "thinking" in params
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,169 @@
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
sys.path.insert(
|
||||
0, os.path.abspath("../../../../..")
|
||||
) # Adds the parent directory to the system path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from litellm.llms.bedrock.chat.invoke_handler import AWSEventStreamDecoder
|
||||
|
||||
|
||||
def test_transform_thinking_blocks_with_redacted_content():
|
||||
thinking_block = {"redactedContent": "This is a redacted content"}
|
||||
decoder = AWSEventStreamDecoder(model="test")
|
||||
transformed_thinking_blocks = decoder.translate_thinking_blocks(thinking_block)
|
||||
assert len(transformed_thinking_blocks) == 1
|
||||
assert transformed_thinking_blocks[0]["type"] == "redacted_thinking"
|
||||
assert transformed_thinking_blocks[0]["data"] == "This is a redacted content"
|
||||
|
||||
|
||||
def test_transform_tool_calls_index():
|
||||
chunks = [
|
||||
{
|
||||
"delta": {"text": "Certainly! I can help you with the"},
|
||||
"contentBlockIndex": 0,
|
||||
},
|
||||
{
|
||||
"delta": {"text": " current weather and time in Tokyo."},
|
||||
"contentBlockIndex": 0,
|
||||
},
|
||||
{"delta": {"text": " To get this information, I'll"}, "contentBlockIndex": 0},
|
||||
{"delta": {"text": " need to use two"}, "contentBlockIndex": 0},
|
||||
{"delta": {"text": " different tools: one"}, "contentBlockIndex": 0},
|
||||
{"delta": {"text": " for the weather and one for"}, "contentBlockIndex": 0},
|
||||
{"delta": {"text": " the time. Let me fetch"}, "contentBlockIndex": 0},
|
||||
{"delta": {"text": " that data for you."}, "contentBlockIndex": 0},
|
||||
{
|
||||
"start": {
|
||||
"toolUse": {
|
||||
"toolUseId": "tooluse_JX1wqyUvRjyTcVSg_6-JwA",
|
||||
"name": "Weather_Tool",
|
||||
}
|
||||
},
|
||||
"contentBlockIndex": 1,
|
||||
},
|
||||
{"delta": {"toolUse": {"input": ""}}, "contentBlockIndex": 1},
|
||||
{"delta": {"toolUse": {"input": '{"locatio'}}, "contentBlockIndex": 1},
|
||||
{"delta": {"toolUse": {"input": 'n": "Toky'}}, "contentBlockIndex": 1},
|
||||
{"delta": {"toolUse": {"input": 'o"}'}}, "contentBlockIndex": 1},
|
||||
{
|
||||
"start": {
|
||||
"toolUse": {
|
||||
"toolUseId": "tooluse_rxDBNjDMQ-mqA-YOp9_3cQ",
|
||||
"name": "Query_Time_Tool",
|
||||
}
|
||||
},
|
||||
"contentBlockIndex": 2,
|
||||
},
|
||||
{"delta": {"toolUse": {"input": ""}}, "contentBlockIndex": 2},
|
||||
{"delta": {"toolUse": {"input": '{"locati'}}, "contentBlockIndex": 2},
|
||||
{"delta": {"toolUse": {"input": 'on"'}}, "contentBlockIndex": 2},
|
||||
{"delta": {"toolUse": {"input": ': "Tokyo"}'}}, "contentBlockIndex": 2},
|
||||
{"stopReason": "tool_use"},
|
||||
]
|
||||
decoder = AWSEventStreamDecoder(model="test")
|
||||
parsed_chunks = []
|
||||
for chunk in chunks:
|
||||
parsed_chunk = decoder._chunk_parser(chunk)
|
||||
parsed_chunks.append(parsed_chunk)
|
||||
tool_call_chunks1 = parsed_chunks[8:12]
|
||||
tool_call_chunks2 = parsed_chunks[13:17]
|
||||
for tool_call_hunk in tool_call_chunks1:
|
||||
tool_call_hunk_dict = tool_call_hunk.model_dump()
|
||||
for tool_call in tool_call_hunk_dict["choices"][0]["delta"]["tool_calls"]:
|
||||
assert tool_call["index"] == 0
|
||||
for tool_call_hunk in tool_call_chunks2:
|
||||
tool_call_hunk_dict = tool_call_hunk.model_dump()
|
||||
for tool_call in tool_call_hunk_dict["choices"][0]["delta"]["tool_calls"]:
|
||||
assert tool_call["index"] == 1
|
||||
|
||||
|
||||
def test_transform_tool_calls_index_with_optional_arg_func():
|
||||
chunks = [
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": "To"},
|
||||
"p": "abcdefghijklmnopqrstuv",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": " get the current time, I"},
|
||||
"p": "abcdefghijklmnopqrstuvwxyzABCD",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": ' can use the "get_time"'},
|
||||
"p": "abcdefghijkl",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": " function. Since the user"},
|
||||
"p": "abcdefghijkl",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": " didn't specify whether"},
|
||||
"p": "abcdefghijklmnopqrstuvw",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": " they want UTC time or local time,"},
|
||||
"p": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": " I'll assume they"},
|
||||
"p": "abcdefghijkl",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": " want the local time. Here's"},
|
||||
"p": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": " how I"},
|
||||
"p": "abcdefghijklmnopqrstuvw",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"delta": {"text": "'ll make the function call:"},
|
||||
"p": "abcdefghijklmnopqrstuvwxyzAB",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 0,
|
||||
"p": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 1,
|
||||
"p": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO",
|
||||
"start": {
|
||||
"toolUse": {
|
||||
"name": "get_time",
|
||||
"toolUseId": "tooluse_htgmgeJATsKTl4s_LW77sQ",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"contentBlockIndex": 1,
|
||||
"delta": {"toolUse": {"input": ""}},
|
||||
"p": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV",
|
||||
},
|
||||
{"contentBlockIndex": 1, "p": "abcdefghijklmnopqrstuvw"},
|
||||
{"p": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK", "stopReason": "tool_use"},
|
||||
]
|
||||
decoder = AWSEventStreamDecoder(model="test")
|
||||
parsed_chunks = []
|
||||
for chunk in chunks:
|
||||
parsed_chunk = decoder._chunk_parser(chunk)
|
||||
parsed_chunks.append(parsed_chunk)
|
||||
tool_call_chunks = parsed_chunks[11:14]
|
||||
for tool_call_hunk in tool_call_chunks:
|
||||
tool_call_hunk_dict = tool_call_hunk.model_dump()
|
||||
for tool_call in tool_call_hunk_dict["choices"][0]["delta"]["tool_calls"]:
|
||||
assert tool_call["index"] == 0
|
@@ -0,0 +1,32 @@
|
||||
from litellm.llms.bedrock.chat.invoke_transformations.amazon_mistral_transformation import (
|
||||
AmazonMistralConfig,
|
||||
)
|
||||
from litellm.types.utils import ModelResponse
|
||||
|
||||
|
||||
def test_mistral_get_outputText():
|
||||
# Set initial model response with arbitrary finish reason
|
||||
model_response = ModelResponse()
|
||||
model_response.choices[0].finish_reason = "None"
|
||||
|
||||
# Models like pixtral will return a completion with the openai format.
|
||||
mock_json_with_choices = {
|
||||
"choices": [{"message": {"content": "Hello!"}, "finish_reason": "stop"}]
|
||||
}
|
||||
|
||||
outputText = AmazonMistralConfig.get_outputText(
|
||||
completion_response=mock_json_with_choices, model_response=model_response
|
||||
)
|
||||
|
||||
assert outputText == "Hello!"
|
||||
assert model_response.choices[0].finish_reason == "stop"
|
||||
|
||||
# Other models might return a completion behind "outputs"
|
||||
mock_json_with_output = {"outputs": [{"text": "Hi!", "stop_reason": "finish"}]}
|
||||
|
||||
outputText = AmazonMistralConfig.get_outputText(
|
||||
completion_response=mock_json_with_output, model_response=model_response
|
||||
)
|
||||
|
||||
assert outputText == "Hi!"
|
||||
assert model_response.choices[0].finish_reason == "finish"
|
Reference in New Issue
Block a user