Fix OpenAIAgent function tool schema (#6936)

Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
This commit is contained in:
Alexey Pelykh
2025-08-19 06:59:18 +02:00
committed by GitHub
parent a666c65047
commit 898d83e783
2 changed files with 29 additions and 27 deletions

View File

@@ -37,6 +37,7 @@ from pydantic import BaseModel, Field
from typing_extensions import NotRequired, TypedDict
from openai import AsyncAzureOpenAI, AsyncOpenAI # type: ignore
from openai.types.responses import FunctionToolParam
# Number of characters to display when previewing image content in logs and UI
# Base64 encoded images can be very long, so we truncate for readability
@@ -47,6 +48,29 @@ IMAGE_CONTENT_PREVIEW_LENGTH = 50
event_logger = logging.getLogger(EVENT_LOGGER_NAME)
def _convert_tool_to_function_tool_param(tool: Tool) -> FunctionToolParam:
"""Convert an autogen Tool to an OpenAI Responses function tool parameter."""
schema = tool.schema
parameters: Dict[str, object] = {}
if "parameters" in schema:
parameters = {
"type": schema["parameters"]["type"],
"properties": schema["parameters"]["properties"],
}
if "required" in schema["parameters"]:
parameters["required"] = schema["parameters"]["required"]
function_tool_param = FunctionToolParam(
type="function",
name=schema["name"],
description=schema.get("description", ""),
parameters=parameters,
strict=schema.get("strict", None),
)
return function_tool_param
# TypedDict classes for built-in tool configurations
class FileSearchToolConfig(TypedDict):
"""Configuration for file_search tool."""
@@ -144,24 +168,6 @@ class ImageMessage(BaseChatMessage):
return f"[Image: {self.content}]"
def _convert_tool_to_function_schema(tool: Tool) -> Dict[str, Any]:
schema = tool.schema
parameters: Dict[str, object] = {}
if "parameters" in schema:
parameters = {
"type": schema["parameters"]["type"],
"properties": schema["parameters"]["properties"],
}
if "required" in schema["parameters"]:
parameters["required"] = schema["parameters"]["required"]
return {
"name": schema["name"],
"description": schema.get("description", ""),
"parameters": parameters,
}
class OpenAIMessageContent(TypedDict):
type: str
text: str
@@ -510,11 +516,7 @@ class OpenAIAgent(BaseChatAgent, Component[OpenAIAgentConfig]):
self._add_configured_tool(tool)
elif isinstance(tool, Tool):
# Handle custom function tools
function_schema: Dict[str, Any] = {
"type": "function",
"function": _convert_tool_to_function_schema(tool),
}
self._tools.append(function_schema)
self._tools.append(cast(dict[str, Any], _convert_tool_to_function_tool_param(tool)))
self._tool_map[tool.name] = tool
else:
raise ValueError(f"Unsupported tool type: {type(tool)}")

View File

@@ -314,14 +314,14 @@ async def test_convert_message_functions(agent: OpenAIAgent) -> None:
@pytest.mark.asyncio
async def test_tool_schema_conversion(agent: OpenAIAgent) -> None:
from autogen_ext.agents.openai._openai_agent import _convert_tool_to_function_schema # type: ignore
from autogen_ext.agents.openai._openai_agent import _convert_tool_to_function_tool_param # type: ignore
tool_schema = _convert_tool_to_function_schema(agent._tool_map["get_weather"]) # type: ignore
tool_schema = _convert_tool_to_function_tool_param(agent._tool_map["get_weather"]) # type: ignore
assert tool_schema["name"] == "get_weather"
assert "description" in tool_schema
assert "parameters" in tool_schema
assert tool_schema["parameters"]["type"] == "object"
assert "parameters" in tool_schema and isinstance(tool_schema["parameters"], dict)
assert tool_schema["parameters"].get("type") == "object"
assert "properties" in tool_schema["parameters"]