mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Replace Hosted*Tool classes with tool methods (#3634)
* Replace Hosted*Tool classes with client static factory methods * fixed failing test * mypy fix * mypy fix 2 * declarative mypy fix * addressed comments * ToolProtocol removal * fixed test * agents mypy fix * fix failing tests * mypy fix * addressed comments * fixed tests * addressed comments + added factory method overrides for azureai v2 client * mypy fix * added kwargs to azureai tool methods * fixed in test * _sessions fix * test fix
This commit is contained in:
@@ -8,9 +8,9 @@ import pytest
|
||||
from openai.types.beta.assistant import Assistant
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from agent_framework import Agent, HostedCodeInterpreterTool, HostedFileSearchTool, normalize_tools, tool
|
||||
from agent_framework import Agent, normalize_tools, tool
|
||||
from agent_framework.exceptions import ServiceInitializationError
|
||||
from agent_framework.openai import OpenAIAssistantProvider
|
||||
from agent_framework.openai import OpenAIAssistantProvider, OpenAIAssistantsClient
|
||||
from agent_framework.openai._shared import from_assistant_tools, to_assistant_tools
|
||||
|
||||
# region Test Helpers
|
||||
@@ -269,7 +269,7 @@ class TestOpenAIAssistantProviderCreateAgent:
|
||||
await provider.create_agent(
|
||||
name="CodeAgent",
|
||||
model="gpt-4",
|
||||
tools=[HostedCodeInterpreterTool()],
|
||||
tools=[OpenAIAssistantsClient.get_code_interpreter_tool()],
|
||||
)
|
||||
|
||||
call_kwargs = mock_async_openai.beta.assistants.create.call_args.kwargs
|
||||
@@ -282,7 +282,7 @@ class TestOpenAIAssistantProviderCreateAgent:
|
||||
await provider.create_agent(
|
||||
name="SearchAgent",
|
||||
model="gpt-4",
|
||||
tools=[HostedFileSearchTool()],
|
||||
tools=[OpenAIAssistantsClient.get_file_search_tool()],
|
||||
)
|
||||
|
||||
call_kwargs = mock_async_openai.beta.assistants.create.call_args.kwargs
|
||||
@@ -295,7 +295,7 @@ class TestOpenAIAssistantProviderCreateAgent:
|
||||
await provider.create_agent(
|
||||
name="SearchAgent",
|
||||
model="gpt-4",
|
||||
tools=[HostedFileSearchTool(max_results=10)],
|
||||
tools=[OpenAIAssistantsClient.get_file_search_tool(max_num_results=10)],
|
||||
)
|
||||
|
||||
call_kwargs = mock_async_openai.beta.assistants.create.call_args.kwargs
|
||||
@@ -309,7 +309,11 @@ class TestOpenAIAssistantProviderCreateAgent:
|
||||
await provider.create_agent(
|
||||
name="MultiToolAgent",
|
||||
model="gpt-4",
|
||||
tools=[get_weather, HostedCodeInterpreterTool(), HostedFileSearchTool()],
|
||||
tools=[
|
||||
get_weather,
|
||||
OpenAIAssistantsClient.get_code_interpreter_tool(),
|
||||
OpenAIAssistantsClient.get_file_search_tool(),
|
||||
],
|
||||
)
|
||||
|
||||
call_kwargs = mock_async_openai.beta.assistants.create.call_args.kwargs
|
||||
@@ -564,22 +568,22 @@ class TestToolConversion:
|
||||
assert api_tools[0]["function"]["name"] == "get_weather"
|
||||
|
||||
def test_to_assistant_tools_code_interpreter(self) -> None:
|
||||
"""Test HostedCodeInterpreterTool conversion."""
|
||||
api_tools = to_assistant_tools([HostedCodeInterpreterTool()])
|
||||
"""Test code_interpreter tool dict conversion."""
|
||||
api_tools = to_assistant_tools([OpenAIAssistantsClient.get_code_interpreter_tool()])
|
||||
|
||||
assert len(api_tools) == 1
|
||||
assert api_tools[0] == {"type": "code_interpreter"}
|
||||
|
||||
def test_to_assistant_tools_file_search(self) -> None:
|
||||
"""Test HostedFileSearchTool conversion."""
|
||||
api_tools = to_assistant_tools([HostedFileSearchTool()])
|
||||
"""Test file_search tool dict conversion."""
|
||||
api_tools = to_assistant_tools([OpenAIAssistantsClient.get_file_search_tool()])
|
||||
|
||||
assert len(api_tools) == 1
|
||||
assert api_tools[0]["type"] == "file_search"
|
||||
|
||||
def test_to_assistant_tools_file_search_with_max_results(self) -> None:
|
||||
"""Test HostedFileSearchTool with max_results conversion."""
|
||||
api_tools = to_assistant_tools([HostedFileSearchTool(max_results=5)])
|
||||
"""Test file_search tool with max_results conversion."""
|
||||
api_tools = to_assistant_tools([OpenAIAssistantsClient.get_file_search_tool(max_num_results=5)])
|
||||
|
||||
assert api_tools[0]["file_search"]["max_num_results"] == 5
|
||||
|
||||
@@ -605,7 +609,7 @@ class TestToolConversion:
|
||||
tools = from_assistant_tools(assistant_tools)
|
||||
|
||||
assert len(tools) == 1
|
||||
assert isinstance(tools[0], HostedCodeInterpreterTool)
|
||||
assert tools[0] == {"type": "code_interpreter"}
|
||||
|
||||
def test_from_assistant_tools_file_search(self) -> None:
|
||||
"""Test converting file_search tool from OpenAI format."""
|
||||
@@ -614,7 +618,7 @@ class TestToolConversion:
|
||||
tools = from_assistant_tools(assistant_tools)
|
||||
|
||||
assert len(tools) == 1
|
||||
assert isinstance(tools[0], HostedFileSearchTool)
|
||||
assert tools[0] == {"type": "file_search"}
|
||||
|
||||
def test_from_assistant_tools_function_skipped(self) -> None:
|
||||
"""Test that function tools are skipped (no implementations)."""
|
||||
@@ -707,7 +711,7 @@ class TestToolMerging:
|
||||
merged = provider._merge_tools(assistant_tools, None) # type: ignore[reportPrivateUsage]
|
||||
|
||||
assert len(merged) == 1
|
||||
assert isinstance(merged[0], HostedCodeInterpreterTool)
|
||||
assert merged[0] == {"type": "code_interpreter"}
|
||||
|
||||
def test_merge_file_search(self, mock_async_openai: MagicMock) -> None:
|
||||
"""Test merging file search tool."""
|
||||
@@ -717,7 +721,7 @@ class TestToolMerging:
|
||||
merged = provider._merge_tools(assistant_tools, None) # type: ignore[reportPrivateUsage]
|
||||
|
||||
assert len(merged) == 1
|
||||
assert isinstance(merged[0], HostedFileSearchTool)
|
||||
assert merged[0] == {"type": "file_search"}
|
||||
|
||||
def test_merge_with_user_tools(self, mock_async_openai: MagicMock) -> None:
|
||||
"""Test merging hosted and user tools."""
|
||||
@@ -727,7 +731,7 @@ class TestToolMerging:
|
||||
merged = provider._merge_tools(assistant_tools, [get_weather]) # type: ignore[reportPrivateUsage]
|
||||
|
||||
assert len(merged) == 2
|
||||
assert isinstance(merged[0], HostedCodeInterpreterTool)
|
||||
assert merged[0] == {"type": "code_interpreter"}
|
||||
|
||||
def test_merge_multiple_hosted_tools(self, mock_async_openai: MagicMock) -> None:
|
||||
"""Test merging multiple hosted tools."""
|
||||
|
||||
@@ -18,8 +18,6 @@ from agent_framework import (
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
HostedCodeInterpreterTool,
|
||||
HostedFileSearchTool,
|
||||
Message,
|
||||
SupportsChatGetResponse,
|
||||
tool,
|
||||
@@ -736,11 +734,11 @@ def test_prepare_options_with_tool_tool(mock_async_openai: MagicMock) -> None:
|
||||
|
||||
|
||||
def test_prepare_options_with_code_interpreter(mock_async_openai: MagicMock) -> None:
|
||||
"""Test _prepare_options with HostedCodeInterpreterTool."""
|
||||
"""Test _prepare_options with code interpreter tool."""
|
||||
client = create_test_openai_assistants_client(mock_async_openai)
|
||||
|
||||
# Create a real HostedCodeInterpreterTool
|
||||
code_tool = HostedCodeInterpreterTool()
|
||||
# Create a code interpreter tool dict
|
||||
code_tool = OpenAIAssistantsClient.get_code_interpreter_tool()
|
||||
|
||||
options = {
|
||||
"tools": [code_tool],
|
||||
@@ -831,12 +829,12 @@ def test_prepare_options_required_function(mock_async_openai: MagicMock) -> None
|
||||
|
||||
|
||||
def test_prepare_options_with_file_search_tool(mock_async_openai: MagicMock) -> None:
|
||||
"""Test _prepare_options with HostedFileSearchTool."""
|
||||
"""Test _prepare_options with file_search tool."""
|
||||
|
||||
client = create_test_openai_assistants_client(mock_async_openai)
|
||||
|
||||
# Create a HostedFileSearchTool with max_results
|
||||
file_search_tool = HostedFileSearchTool(max_results=10)
|
||||
# Create a file_search tool with max_results
|
||||
file_search_tool = OpenAIAssistantsClient.get_file_search_tool(max_num_results=10)
|
||||
|
||||
options = {
|
||||
"tools": [file_search_tool],
|
||||
@@ -851,7 +849,7 @@ def test_prepare_options_with_file_search_tool(mock_async_openai: MagicMock) ->
|
||||
# Check file search tool was set correctly
|
||||
assert "tools" in run_options
|
||||
assert len(run_options["tools"]) == 1
|
||||
expected_tool = {"type": "file_search", "max_num_results": 10}
|
||||
expected_tool = {"type": "file_search", "file_search": {"max_num_results": 10}}
|
||||
assert run_options["tools"][0] == expected_tool
|
||||
assert run_options["tool_choice"] == "auto"
|
||||
|
||||
@@ -1182,7 +1180,7 @@ async def test_file_search() -> None:
|
||||
response = await openai_assistants_client.get_response(
|
||||
messages=messages,
|
||||
options={
|
||||
"tools": [HostedFileSearchTool()],
|
||||
"tools": [OpenAIAssistantsClient.get_file_search_tool()],
|
||||
"tool_resources": {"file_search": {"vector_store_ids": [vector_store.vector_store_id]}},
|
||||
},
|
||||
)
|
||||
@@ -1209,7 +1207,7 @@ async def test_file_search_streaming() -> None:
|
||||
stream=True,
|
||||
messages=messages,
|
||||
options={
|
||||
"tools": [HostedFileSearchTool()],
|
||||
"tools": [OpenAIAssistantsClient.get_file_search_tool()],
|
||||
"tool_resources": {"file_search": {"vector_store_ids": [vector_store.vector_store_id]}},
|
||||
},
|
||||
)
|
||||
@@ -1346,7 +1344,7 @@ async def test_openai_assistants_agent_code_interpreter():
|
||||
async with Agent(
|
||||
client=OpenAIAssistantsClient(model_id=INTEGRATION_TEST_MODEL),
|
||||
instructions="You are a helpful assistant that can write and execute Python code.",
|
||||
tools=[HostedCodeInterpreterTool()],
|
||||
tools=[OpenAIAssistantsClient.get_code_interpreter_tool()],
|
||||
) as agent:
|
||||
# Request code execution
|
||||
response = await agent.run("Write Python code to calculate the factorial of 5 and show the result.")
|
||||
|
||||
@@ -15,10 +15,8 @@ from pytest import param
|
||||
from agent_framework import (
|
||||
ChatResponse,
|
||||
Content,
|
||||
HostedWebSearchTool,
|
||||
Message,
|
||||
SupportsChatGetResponse,
|
||||
ToolProtocol,
|
||||
prepare_function_call_results,
|
||||
tool,
|
||||
)
|
||||
@@ -172,18 +170,22 @@ async def test_content_filter_exception_handling(openai_unit_test_env: dict[str,
|
||||
|
||||
|
||||
def test_unsupported_tool_handling(openai_unit_test_env: dict[str, str]) -> None:
|
||||
"""Test that unsupported tool types are handled correctly."""
|
||||
"""Test that unsupported tool types are passed through unchanged."""
|
||||
client = OpenAIChatClient()
|
||||
|
||||
# Create a mock ToolProtocol that's not a FunctionTool
|
||||
unsupported_tool = MagicMock(spec=ToolProtocol)
|
||||
unsupported_tool.__class__.__name__ = "UnsupportedAITool"
|
||||
# Create a random object that's not a FunctionTool, dict, or callable
|
||||
# This simulates an unsupported tool type that gets passed through
|
||||
class UnsupportedTool:
|
||||
pass
|
||||
|
||||
# This should ignore the unsupported ToolProtocol and return empty list
|
||||
unsupported_tool = UnsupportedTool()
|
||||
|
||||
# Unsupported tools are passed through for the API to handle/reject
|
||||
result = client._prepare_tools_for_openai([unsupported_tool]) # type: ignore
|
||||
assert result == {}
|
||||
assert "tools" in result
|
||||
assert len(result["tools"]) == 1
|
||||
|
||||
# Also test with a non-ToolProtocol that should be converted to dict
|
||||
# Also test with a dict-based tool that should be passed through
|
||||
dict_tool = {"type": "function", "name": "test"}
|
||||
result = client._prepare_tools_for_openai([dict_tool]) # type: ignore
|
||||
assert result["tools"] == [dict_tool]
|
||||
@@ -770,8 +772,8 @@ def test_prepare_tools_with_web_search_no_location(openai_unit_test_env: dict[st
|
||||
"""Test preparing web search tool without user location."""
|
||||
client = OpenAIChatClient()
|
||||
|
||||
# Web search tool without additional_properties
|
||||
web_search_tool = HostedWebSearchTool()
|
||||
# Web search tool using static method
|
||||
web_search_tool = OpenAIChatClient.get_web_search_tool()
|
||||
|
||||
result = client._prepare_tools_for_openai([web_search_tool])
|
||||
|
||||
@@ -1071,11 +1073,13 @@ async def test_integration_web_search() -> None:
|
||||
client = OpenAIChatClient(model_id="gpt-4o-search-preview")
|
||||
|
||||
for streaming in [False, True]:
|
||||
# Use static method for web search tool
|
||||
web_search_tool = OpenAIChatClient.get_web_search_tool()
|
||||
content = {
|
||||
"messages": "Who are the main characters of Kpop Demon Hunters? Do a web search to find the answer.",
|
||||
"options": {
|
||||
"tool_choice": "auto",
|
||||
"tools": [HostedWebSearchTool()],
|
||||
"tools": [web_search_tool],
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
@@ -1090,17 +1094,19 @@ async def test_integration_web_search() -> None:
|
||||
assert "Zoey" in response.text
|
||||
|
||||
# Test that the client will use the web search tool with location
|
||||
additional_properties = {
|
||||
"user_location": {
|
||||
"country": "US",
|
||||
"city": "Seattle",
|
||||
web_search_tool_with_location = OpenAIChatClient.get_web_search_tool(
|
||||
web_search_options={
|
||||
"user_location": {
|
||||
"type": "approximate",
|
||||
"approximate": {"country": "US", "city": "Seattle"},
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
content = {
|
||||
"messages": "What is the current weather? Do not ask for my current location.",
|
||||
"options": {
|
||||
"tool_choice": "auto",
|
||||
"tools": [HostedWebSearchTool(additional_properties=additional_properties)],
|
||||
"tools": [web_search_tool_with_location],
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
|
||||
@@ -31,11 +31,6 @@ from agent_framework import (
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
HostedCodeInterpreterTool,
|
||||
HostedFileSearchTool,
|
||||
HostedImageGenerationTool,
|
||||
HostedMCPTool,
|
||||
HostedWebSearchTool,
|
||||
Message,
|
||||
SupportsChatGetResponse,
|
||||
tool,
|
||||
@@ -236,19 +231,18 @@ async def test_get_response_with_all_parameters() -> None:
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_web_search_tool_with_location() -> None:
|
||||
"""Test HostedWebSearchTool with location parameters."""
|
||||
"""Test web search tool with location parameters."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
|
||||
# Test web search tool with location
|
||||
web_search_tool = HostedWebSearchTool(
|
||||
additional_properties={
|
||||
"user_location": {
|
||||
"country": "US",
|
||||
"city": "Seattle",
|
||||
"region": "WA",
|
||||
"timezone": "America/Los_Angeles",
|
||||
}
|
||||
# Test web search tool with location using static method
|
||||
web_search_tool = OpenAIResponsesClient.get_web_search_tool(
|
||||
user_location={
|
||||
"city": "Seattle",
|
||||
"country": "US",
|
||||
"region": "WA",
|
||||
"timezone": "America/Los_Angeles",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -260,38 +254,21 @@ async def test_web_search_tool_with_location() -> None:
|
||||
)
|
||||
|
||||
|
||||
async def test_file_search_tool_with_invalid_inputs() -> None:
|
||||
"""Test HostedFileSearchTool with invalid vector store inputs."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
|
||||
# Test with invalid inputs type (should trigger ValueError)
|
||||
file_search_tool = HostedFileSearchTool(inputs=[Content.from_hosted_file(file_id="invalid")])
|
||||
|
||||
# Should raise an error due to invalid inputs
|
||||
with pytest.raises(ValueError, match="HostedFileSearchTool requires inputs to be of type"):
|
||||
await client.get_response(
|
||||
messages=[Message(role="user", text="Search files")],
|
||||
options={"tools": [file_search_tool]},
|
||||
)
|
||||
|
||||
|
||||
async def test_code_interpreter_tool_variations() -> None:
|
||||
"""Test HostedCodeInterpreterTool with and without file inputs."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
|
||||
# Test code interpreter without files
|
||||
code_tool_empty = HostedCodeInterpreterTool()
|
||||
# Test code interpreter using static method
|
||||
code_tool = OpenAIResponsesClient.get_code_interpreter_tool()
|
||||
|
||||
with pytest.raises(ServiceResponseException):
|
||||
await client.get_response(
|
||||
messages=[Message(role="user", text="Run some code")],
|
||||
options={"tools": [code_tool_empty]},
|
||||
messages=[Message("user", ["Run some code"])],
|
||||
options={"tools": [code_tool]},
|
||||
)
|
||||
|
||||
# Test code interpreter with files
|
||||
code_tool_with_files = HostedCodeInterpreterTool(
|
||||
inputs=[Content.from_hosted_file(file_id="file1"), Content.from_hosted_file(file_id="file2")]
|
||||
)
|
||||
# Test code interpreter with files using static method
|
||||
code_tool_with_files = OpenAIResponsesClient.get_code_interpreter_tool(file_ids=["file1", "file2"])
|
||||
|
||||
with pytest.raises(ServiceResponseException):
|
||||
await client.get_response(
|
||||
@@ -319,18 +296,20 @@ async def test_content_filter_exception() -> None:
|
||||
assert "content error" in str(exc_info.value)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_hosted_file_search_tool_validation() -> None:
|
||||
"""Test get_response HostedFileSearchTool validation."""
|
||||
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
|
||||
# Test HostedFileSearchTool without inputs (should raise ValueError)
|
||||
empty_file_search_tool = HostedFileSearchTool()
|
||||
# Test file search tool with vector store IDs
|
||||
file_search_tool = OpenAIResponsesClient.get_file_search_tool(vector_store_ids=["vs_123"])
|
||||
|
||||
with pytest.raises((ValueError, ServiceInvalidRequestError)):
|
||||
# Test using file search tool - may raise various exceptions depending on API response
|
||||
with pytest.raises((ValueError, ServiceInvalidRequestError, ServiceResponseException)):
|
||||
await client.get_response(
|
||||
messages=[Message(role="user", text="Test")],
|
||||
options={"tools": [empty_file_search_tool]},
|
||||
messages=[Message("user", ["Test"])],
|
||||
options={"tools": [file_search_tool]},
|
||||
)
|
||||
|
||||
|
||||
@@ -1074,18 +1053,17 @@ def test_streaming_chunk_with_usage_only() -> None:
|
||||
assert update.contents[0].usage_details["total_token_count"] == 75
|
||||
|
||||
|
||||
def test_prepare_tools_for_openai_with_hosted_mcp() -> None:
|
||||
"""Test that HostedMCPTool is converted to the correct response tool dict."""
|
||||
def test_prepare_tools_for_openai_with_mcp() -> None:
|
||||
"""Test that MCP tool dict is converted to the correct response tool dict."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
|
||||
tool = HostedMCPTool(
|
||||
name="My MCP",
|
||||
# Use static method to create MCP tool
|
||||
tool = OpenAIResponsesClient.get_mcp_tool(
|
||||
name="My_MCP",
|
||||
url="https://mcp.example",
|
||||
description="An MCP server",
|
||||
approval_mode={"always_require_approval": ["tool_a", "tool_b"]},
|
||||
allowed_tools={"tool_a", "tool_b"},
|
||||
allowed_tools=["tool_a", "tool_b"],
|
||||
headers={"X-Test": "yes"},
|
||||
additional_properties={"custom": "value"},
|
||||
approval_mode={"always_require_approval": ["tool_a", "tool_b"]},
|
||||
)
|
||||
|
||||
resp_tools = client._prepare_tools_for_openai([tool])
|
||||
@@ -1097,7 +1075,6 @@ def test_prepare_tools_for_openai_with_hosted_mcp() -> None:
|
||||
assert mcp["server_label"] == "My_MCP"
|
||||
# server_url may be normalized to include a trailing slash by the client
|
||||
assert str(mcp["server_url"]).rstrip("/") == "https://mcp.example"
|
||||
assert mcp["server_description"] == "An MCP server"
|
||||
assert mcp["headers"]["X-Test"] == "yes"
|
||||
assert set(mcp["allowed_tools"]) == {"tool_a", "tool_b"}
|
||||
# approval mapping created from approval_mode dict
|
||||
@@ -1258,13 +1235,15 @@ def test_prepare_tools_for_openai_with_raw_image_generation_minimal() -> None:
|
||||
assert len(image_tool) == 1
|
||||
|
||||
|
||||
def test_prepare_tools_for_openai_with_hosted_image_generation() -> None:
|
||||
"""Test HostedImageGenerationTool conversion."""
|
||||
def test_prepare_tools_for_openai_with_image_generation_options() -> None:
|
||||
"""Test image generation tool conversion with options."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
tool = HostedImageGenerationTool(
|
||||
description="Generate images",
|
||||
options={"output_format": "png", "size": "512x512"},
|
||||
additional_properties={"quality": "high"},
|
||||
|
||||
# Use static method to create image generation tool
|
||||
tool = OpenAIResponsesClient.get_image_generation_tool(
|
||||
output_format="png",
|
||||
size="512x512",
|
||||
quality="high",
|
||||
)
|
||||
|
||||
resp_tools = client._prepare_tools_for_openai([tool])
|
||||
@@ -2324,11 +2303,13 @@ async def test_integration_web_search() -> None:
|
||||
client = OpenAIResponsesClient(model_id="gpt-5")
|
||||
|
||||
for streaming in [False, True]:
|
||||
# Use static method for web search tool
|
||||
web_search_tool = OpenAIResponsesClient.get_web_search_tool()
|
||||
content = {
|
||||
"messages": "Who are the main characters of Kpop Demon Hunters? Do a web search to find the answer.",
|
||||
"options": {
|
||||
"tool_choice": "auto",
|
||||
"tools": [HostedWebSearchTool()],
|
||||
"tools": [web_search_tool],
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
@@ -2343,17 +2324,14 @@ async def test_integration_web_search() -> None:
|
||||
assert "Zoey" in response.text
|
||||
|
||||
# Test that the client will use the web search tool with location
|
||||
additional_properties = {
|
||||
"user_location": {
|
||||
"country": "US",
|
||||
"city": "Seattle",
|
||||
}
|
||||
}
|
||||
web_search_tool_with_location = OpenAIResponsesClient.get_web_search_tool(
|
||||
user_location={"country": "US", "city": "Seattle"},
|
||||
)
|
||||
content = {
|
||||
"messages": "What is the current weather? Do not ask for my current location.",
|
||||
"options": {
|
||||
"tool_choice": "auto",
|
||||
"tools": [HostedWebSearchTool(additional_properties=additional_properties)],
|
||||
"tools": [web_search_tool_with_location],
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
@@ -2375,7 +2353,9 @@ async def test_integration_file_search() -> None:
|
||||
assert isinstance(openai_responses_client, SupportsChatGetResponse)
|
||||
|
||||
file_id, vector_store = await create_vector_store(openai_responses_client)
|
||||
# Test that the client will use the web search tool
|
||||
# Use static method for file search tool
|
||||
file_search_tool = OpenAIResponsesClient.get_file_search_tool(vector_store_ids=[vector_store.vector_store_id])
|
||||
# Test that the client will use the file search tool
|
||||
response = await openai_responses_client.get_response(
|
||||
messages=[
|
||||
Message(
|
||||
@@ -2385,7 +2365,7 @@ async def test_integration_file_search() -> None:
|
||||
],
|
||||
options={
|
||||
"tool_choice": "auto",
|
||||
"tools": [HostedFileSearchTool(inputs=vector_store)],
|
||||
"tools": [file_search_tool],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2406,9 +2386,10 @@ async def test_integration_streaming_file_search() -> None:
|
||||
assert isinstance(openai_responses_client, SupportsChatGetResponse)
|
||||
|
||||
file_id, vector_store = await create_vector_store(openai_responses_client)
|
||||
# Use static method for file search tool
|
||||
file_search_tool = OpenAIResponsesClient.get_file_search_tool(vector_store_ids=[vector_store.vector_store_id])
|
||||
# Test that the client will use the web search tool
|
||||
response = openai_responses_client.get_response(
|
||||
stream=True,
|
||||
response = openai_responses_client.get_streaming_response(
|
||||
messages=[
|
||||
Message(
|
||||
role="user",
|
||||
@@ -2417,7 +2398,7 @@ async def test_integration_streaming_file_search() -> None:
|
||||
],
|
||||
options={
|
||||
"tool_choice": "auto",
|
||||
"tools": [HostedFileSearchTool(inputs=vector_store)],
|
||||
"tools": [file_search_tool],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user