mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-08-02 08:44:44 +00:00
Merge branch 'main' into rag-metadata-support
This commit is contained in:
commit
3faaeb0bba
2 changed files with 76 additions and 2 deletions
|
@ -7,7 +7,7 @@
|
||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
from collections.abc import AsyncIterator
|
from collections.abc import AsyncIterator
|
||||||
from typing import cast
|
from typing import Any, cast
|
||||||
|
|
||||||
from openai.types.chat import ChatCompletionToolParam
|
from openai.types.chat import ChatCompletionToolParam
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
@ -264,7 +264,11 @@ class OpenAIResponsesImpl:
|
||||||
if response_tool_call:
|
if response_tool_call:
|
||||||
response_tool_call.function.arguments += tool_call.function.arguments
|
response_tool_call.function.arguments += tool_call.function.arguments
|
||||||
else:
|
else:
|
||||||
response_tool_call = OpenAIChatCompletionToolCall(**tool_call.model_dump())
|
tool_call_dict: dict[str, Any] = tool_call.model_dump()
|
||||||
|
# Ensure we don't have any empty type field in the tool call dict.
|
||||||
|
# The OpenAI client used by providers often returns a type=None here.
|
||||||
|
tool_call_dict.pop("type", None)
|
||||||
|
response_tool_call = OpenAIChatCompletionToolCall(**tool_call_dict)
|
||||||
chat_response_tool_calls[tool_call.index] = response_tool_call
|
chat_response_tool_calls[tool_call.index] = response_tool_call
|
||||||
|
|
||||||
# Convert the dict of tool calls by index to a list of tool calls to pass back in our response
|
# Convert the dict of tool calls by index to a list of tool calls to pass back in our response
|
||||||
|
|
|
@ -7,10 +7,18 @@
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from openai.types.chat.chat_completion_chunk import (
|
||||||
|
ChatCompletionChunk,
|
||||||
|
Choice,
|
||||||
|
ChoiceDelta,
|
||||||
|
ChoiceDeltaToolCall,
|
||||||
|
ChoiceDeltaToolCallFunction,
|
||||||
|
)
|
||||||
|
|
||||||
from llama_stack.apis.agents.openai_responses import (
|
from llama_stack.apis.agents.openai_responses import (
|
||||||
OpenAIResponseInputItemList,
|
OpenAIResponseInputItemList,
|
||||||
OpenAIResponseInputMessageContentText,
|
OpenAIResponseInputMessageContentText,
|
||||||
|
OpenAIResponseInputToolFunction,
|
||||||
OpenAIResponseInputToolWebSearch,
|
OpenAIResponseInputToolWebSearch,
|
||||||
OpenAIResponseMessage,
|
OpenAIResponseMessage,
|
||||||
OpenAIResponseObject,
|
OpenAIResponseObject,
|
||||||
|
@ -167,6 +175,68 @@ async def test_create_openai_response_with_string_input_with_tools(openai_respon
|
||||||
assert result.output[1].content[0].text == "Dublin"
|
assert result.output[1].content[0].text == "Dublin"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_create_openai_response_with_tool_call_type_none(openai_responses_impl, mock_inference_api):
|
||||||
|
"""Test creating an OpenAI response with a tool call response that has a type of None."""
|
||||||
|
# Setup
|
||||||
|
input_text = "How hot it is in San Francisco today?"
|
||||||
|
model = "meta-llama/Llama-3.1-8B-Instruct"
|
||||||
|
|
||||||
|
async def fake_stream():
|
||||||
|
yield ChatCompletionChunk(
|
||||||
|
id="123",
|
||||||
|
choices=[
|
||||||
|
Choice(
|
||||||
|
index=0,
|
||||||
|
delta=ChoiceDelta(
|
||||||
|
tool_calls=[
|
||||||
|
ChoiceDeltaToolCall(
|
||||||
|
index=0,
|
||||||
|
id="tc_123",
|
||||||
|
function=ChoiceDeltaToolCallFunction(name="get_weather", arguments="{}"),
|
||||||
|
type=None,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
created=1,
|
||||||
|
model=model,
|
||||||
|
object="chat.completion.chunk",
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_inference_api.openai_chat_completion.return_value = fake_stream()
|
||||||
|
|
||||||
|
# Execute
|
||||||
|
result = await openai_responses_impl.create_openai_response(
|
||||||
|
input=input_text,
|
||||||
|
model=model,
|
||||||
|
stream=True,
|
||||||
|
temperature=0.1,
|
||||||
|
tools=[
|
||||||
|
OpenAIResponseInputToolFunction(
|
||||||
|
name="get_weather",
|
||||||
|
description="Get current temperature for a given location.",
|
||||||
|
parameters={
|
||||||
|
"location": "string",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
first_call = mock_inference_api.openai_chat_completion.call_args_list[0]
|
||||||
|
assert first_call.kwargs["messages"][0].content == input_text
|
||||||
|
assert first_call.kwargs["tools"] is not None
|
||||||
|
assert first_call.kwargs["temperature"] == 0.1
|
||||||
|
|
||||||
|
# Check that we got the content from our mocked tool execution result
|
||||||
|
chunks = [chunk async for chunk in result]
|
||||||
|
assert len(chunks) > 0
|
||||||
|
assert chunks[0].response.output[0].type == "function_call"
|
||||||
|
assert chunks[0].response.output[0].name == "get_weather"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_create_openai_response_with_multiple_messages(openai_responses_impl, mock_inference_api):
|
async def test_create_openai_response_with_multiple_messages(openai_responses_impl, mock_inference_api):
|
||||||
"""Test creating an OpenAI response with multiple messages."""
|
"""Test creating an OpenAI response with multiple messages."""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue