mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
fix: add the missing required tool parameters for Anthropic models
Fixes #1692 PiperOrigin-RevId: 795125801
This commit is contained in:
committed by
Copybara-Service
parent
9ba8eec220
commit
e63e2a7106
@@ -216,25 +216,31 @@ def _update_type_string(value_dict: dict[str, Any]):
|
|||||||
def function_declaration_to_tool_param(
|
def function_declaration_to_tool_param(
|
||||||
function_declaration: types.FunctionDeclaration,
|
function_declaration: types.FunctionDeclaration,
|
||||||
) -> anthropic_types.ToolParam:
|
) -> anthropic_types.ToolParam:
|
||||||
|
"""Converts a function declaration to an Anthropic tool param."""
|
||||||
assert function_declaration.name
|
assert function_declaration.name
|
||||||
|
|
||||||
properties = {}
|
properties = {}
|
||||||
if (
|
required_params = []
|
||||||
function_declaration.parameters
|
if function_declaration.parameters:
|
||||||
and function_declaration.parameters.properties
|
if function_declaration.parameters.properties:
|
||||||
):
|
for key, value in function_declaration.parameters.properties.items():
|
||||||
for key, value in function_declaration.parameters.properties.items():
|
value_dict = value.model_dump(exclude_none=True)
|
||||||
value_dict = value.model_dump(exclude_none=True)
|
_update_type_string(value_dict)
|
||||||
_update_type_string(value_dict)
|
properties[key] = value_dict
|
||||||
properties[key] = value_dict
|
if function_declaration.parameters.required:
|
||||||
|
required_params = function_declaration.parameters.required
|
||||||
|
|
||||||
|
input_schema = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": properties,
|
||||||
|
}
|
||||||
|
if required_params:
|
||||||
|
input_schema["required"] = required_params
|
||||||
|
|
||||||
return anthropic_types.ToolParam(
|
return anthropic_types.ToolParam(
|
||||||
name=function_declaration.name,
|
name=function_declaration.name,
|
||||||
description=function_declaration.description or "",
|
description=function_declaration.description or "",
|
||||||
input_schema={
|
input_schema=input_schema,
|
||||||
"type": "object",
|
|
||||||
"properties": properties,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from anthropic import types as anthropic_types
|
|||||||
from google.adk import version as adk_version
|
from google.adk import version as adk_version
|
||||||
from google.adk.models import anthropic_llm
|
from google.adk.models import anthropic_llm
|
||||||
from google.adk.models.anthropic_llm import Claude
|
from google.adk.models.anthropic_llm import Claude
|
||||||
|
from google.adk.models.anthropic_llm import function_declaration_to_tool_param
|
||||||
from google.adk.models.llm_request import LlmRequest
|
from google.adk.models.llm_request import LlmRequest
|
||||||
from google.adk.models.llm_response import LlmResponse
|
from google.adk.models.llm_response import LlmResponse
|
||||||
from google.genai import types
|
from google.genai import types
|
||||||
@@ -96,6 +97,200 @@ def test_supported_models():
|
|||||||
assert models[1] == r"claude-.*-4.*"
|
assert models[1] == r"claude-.*-4.*"
|
||||||
|
|
||||||
|
|
||||||
|
function_declaration_test_cases = [
|
||||||
|
(
|
||||||
|
"function_with_no_parameters",
|
||||||
|
types.FunctionDeclaration(
|
||||||
|
name="get_current_time",
|
||||||
|
description="Gets the current time.",
|
||||||
|
),
|
||||||
|
anthropic_types.ToolParam(
|
||||||
|
name="get_current_time",
|
||||||
|
description="Gets the current time.",
|
||||||
|
input_schema={"type": "object", "properties": {}},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"function_with_one_optional_parameter",
|
||||||
|
types.FunctionDeclaration(
|
||||||
|
name="get_weather",
|
||||||
|
description="Gets weather information for a given location.",
|
||||||
|
parameters=types.Schema(
|
||||||
|
type=types.Type.OBJECT,
|
||||||
|
properties={
|
||||||
|
"location": types.Schema(
|
||||||
|
type=types.Type.STRING,
|
||||||
|
description="City and state, e.g., San Francisco, CA",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
anthropic_types.ToolParam(
|
||||||
|
name="get_weather",
|
||||||
|
description="Gets weather information for a given location.",
|
||||||
|
input_schema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"description": (
|
||||||
|
"City and state, e.g., San Francisco, CA"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"function_with_one_required_parameter",
|
||||||
|
types.FunctionDeclaration(
|
||||||
|
name="get_stock_price",
|
||||||
|
description="Gets the current price for a stock ticker.",
|
||||||
|
parameters=types.Schema(
|
||||||
|
type=types.Type.OBJECT,
|
||||||
|
properties={
|
||||||
|
"ticker": types.Schema(
|
||||||
|
type=types.Type.STRING,
|
||||||
|
description="The stock ticker, e.g., AAPL",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
required=["ticker"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
anthropic_types.ToolParam(
|
||||||
|
name="get_stock_price",
|
||||||
|
description="Gets the current price for a stock ticker.",
|
||||||
|
input_schema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"ticker": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The stock ticker, e.g., AAPL",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["ticker"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"function_with_multiple_mixed_parameters",
|
||||||
|
types.FunctionDeclaration(
|
||||||
|
name="submit_order",
|
||||||
|
description="Submits a product order.",
|
||||||
|
parameters=types.Schema(
|
||||||
|
type=types.Type.OBJECT,
|
||||||
|
properties={
|
||||||
|
"product_id": types.Schema(
|
||||||
|
type=types.Type.STRING, description="The product ID"
|
||||||
|
),
|
||||||
|
"quantity": types.Schema(
|
||||||
|
type=types.Type.INTEGER,
|
||||||
|
description="The order quantity",
|
||||||
|
),
|
||||||
|
"notes": types.Schema(
|
||||||
|
type=types.Type.STRING,
|
||||||
|
description="Optional order notes",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
required=["product_id", "quantity"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
anthropic_types.ToolParam(
|
||||||
|
name="submit_order",
|
||||||
|
description="Submits a product order.",
|
||||||
|
input_schema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"product_id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The product ID",
|
||||||
|
},
|
||||||
|
"quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The order quantity",
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Optional order notes",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["product_id", "quantity"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"function_with_complex_nested_parameter",
|
||||||
|
types.FunctionDeclaration(
|
||||||
|
name="create_playlist",
|
||||||
|
description="Creates a playlist from a list of songs.",
|
||||||
|
parameters=types.Schema(
|
||||||
|
type=types.Type.OBJECT,
|
||||||
|
properties={
|
||||||
|
"playlist_name": types.Schema(
|
||||||
|
type=types.Type.STRING,
|
||||||
|
description="The name for the new playlist",
|
||||||
|
),
|
||||||
|
"songs": types.Schema(
|
||||||
|
type=types.Type.ARRAY,
|
||||||
|
description="A list of songs to add to the playlist",
|
||||||
|
items=types.Schema(
|
||||||
|
type=types.Type.OBJECT,
|
||||||
|
properties={
|
||||||
|
"title": types.Schema(type=types.Type.STRING),
|
||||||
|
"artist": types.Schema(type=types.Type.STRING),
|
||||||
|
},
|
||||||
|
required=["title", "artist"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
required=["playlist_name", "songs"],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
anthropic_types.ToolParam(
|
||||||
|
name="create_playlist",
|
||||||
|
description="Creates a playlist from a list of songs.",
|
||||||
|
input_schema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"playlist_name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name for the new playlist",
|
||||||
|
},
|
||||||
|
"songs": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "A list of songs to add to the playlist",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"title": {"type": "string"},
|
||||||
|
"artist": {"type": "string"},
|
||||||
|
},
|
||||||
|
"required": ["title", "artist"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["playlist_name", "songs"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"_, function_declaration, expected_tool_param",
|
||||||
|
function_declaration_test_cases,
|
||||||
|
ids=[case[0] for case in function_declaration_test_cases],
|
||||||
|
)
|
||||||
|
async def test_function_declaration_to_tool_param(
|
||||||
|
_, function_declaration, expected_tool_param
|
||||||
|
):
|
||||||
|
"""Test function_declaration_to_tool_param."""
|
||||||
|
assert (
|
||||||
|
function_declaration_to_tool_param(function_declaration)
|
||||||
|
== expected_tool_param
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_generate_content_async(
|
async def test_generate_content_async(
|
||||||
claude_llm, llm_request, generate_content_response, generate_llm_response
|
claude_llm, llm_request, generate_content_response, generate_llm_response
|
||||||
|
|||||||
Reference in New Issue
Block a user