mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: fix anthropic code interpreter tool repr (#2244)
* fix anthropic code interpreter tool repr * fixes * added skills and sample * test fix * add new sample to readme * fixes tests
This commit is contained in:
committed by
GitHub
Unverified
parent
45dba6b825
commit
fcc3f1b6c0
@@ -18,6 +18,7 @@ from agent_framework import (
|
||||
FunctionCallContent,
|
||||
FunctionResultContent,
|
||||
HostedCodeInterpreterTool,
|
||||
HostedFileContent,
|
||||
HostedMCPTool,
|
||||
HostedWebSearchTool,
|
||||
Role,
|
||||
@@ -122,6 +123,7 @@ class AnthropicClient(BaseChatClient):
|
||||
api_key: str | None = None,
|
||||
model_id: str | None = None,
|
||||
anthropic_client: AsyncAnthropic | None = None,
|
||||
additional_beta_flags: list[str] | None = None,
|
||||
env_file_path: str | None = None,
|
||||
env_file_encoding: str | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -134,6 +136,8 @@ class AnthropicClient(BaseChatClient):
|
||||
anthropic_client: An existing Anthropic client to use. If not provided, one will be created.
|
||||
This can be used to further configure the client before passing it in.
|
||||
For instance if you need to set a different base_url for testing or private deployments.
|
||||
additional_beta_flags: Additional beta flags to enable on the client.
|
||||
Default flags are: "mcp-client-2025-04-04", "code-execution-2025-08-25".
|
||||
env_file_path: Path to environment file for loading settings.
|
||||
env_file_encoding: Encoding of the environment file.
|
||||
kwargs: Additional keyword arguments passed to the parent class.
|
||||
@@ -196,6 +200,7 @@ class AnthropicClient(BaseChatClient):
|
||||
|
||||
# Initialize instance variables
|
||||
self.anthropic_client = anthropic_client
|
||||
self.additional_beta_flags = additional_beta_flags or []
|
||||
self.model_id = anthropic_settings.chat_model_id
|
||||
# streaming requires tracking the last function call ID and name
|
||||
self._last_call_id_name: tuple[str, str] | None = None
|
||||
@@ -246,12 +251,16 @@ class AnthropicClient(BaseChatClient):
|
||||
Returns:
|
||||
A dictionary of run options for the Anthropic client.
|
||||
"""
|
||||
if chat_options.additional_properties and "additional_beta_flags" in chat_options.additional_properties:
|
||||
betas = chat_options.additional_properties.pop("additional_beta_flags")
|
||||
else:
|
||||
betas = []
|
||||
run_options: dict[str, Any] = {
|
||||
"model": chat_options.model_id or self.model_id,
|
||||
"messages": self._convert_messages_to_anthropic_format(messages),
|
||||
"max_tokens": chat_options.max_tokens or ANTHROPIC_DEFAULT_MAX_TOKENS,
|
||||
"extra_headers": {"User-Agent": AGENT_FRAMEWORK_USER_AGENT},
|
||||
"betas": BETA_FLAGS,
|
||||
"betas": {*BETA_FLAGS, *self.additional_beta_flags, *betas},
|
||||
}
|
||||
|
||||
# Add any additional options from chat_options or kwargs
|
||||
@@ -396,7 +405,7 @@ class AnthropicClient(BaseChatClient):
|
||||
case HostedCodeInterpreterTool():
|
||||
code_tool: dict[str, Any] = {
|
||||
"type": "code_execution_20250825",
|
||||
"name": "code_interpreter",
|
||||
"name": "code_execution",
|
||||
}
|
||||
tool_list.append(code_tool)
|
||||
case HostedMCPTool():
|
||||
@@ -524,17 +533,7 @@ class AnthropicClient(BaseChatClient):
|
||||
annotations=self._parse_citations(content_block),
|
||||
)
|
||||
)
|
||||
case "tool_use":
|
||||
self._last_call_id_name = (content_block.id, content_block.name)
|
||||
contents.append(
|
||||
FunctionCallContent(
|
||||
call_id=content_block.id,
|
||||
name=content_block.name,
|
||||
arguments=content_block.input,
|
||||
raw_representation=content_block,
|
||||
)
|
||||
)
|
||||
case "mcp_tool_use" | "server_tool_use":
|
||||
case "tool_use" | "mcp_tool_use" | "server_tool_use":
|
||||
self._last_call_id_name = (content_block.id, content_block.name)
|
||||
contents.append(
|
||||
FunctionCallContent(
|
||||
@@ -572,6 +571,19 @@ class AnthropicClient(BaseChatClient):
|
||||
| "text_editor_code_execution_tool_result"
|
||||
):
|
||||
call_id, name = self._last_call_id_name or (None, None)
|
||||
if (
|
||||
content_block.content
|
||||
and (
|
||||
content_block.content.type == "bash_code_execution_result"
|
||||
or content_block.content.type == "code_execution_result"
|
||||
)
|
||||
and content_block.content.content
|
||||
):
|
||||
for result_content in content_block.content.content:
|
||||
if hasattr(result_content, "file_id"):
|
||||
contents.append(
|
||||
HostedFileContent(file_id=result_content.file_id, raw_representation=result_content)
|
||||
)
|
||||
contents.append(
|
||||
FunctionResultContent(
|
||||
call_id=content_block.tool_use_id,
|
||||
|
||||
@@ -50,7 +50,9 @@ def create_test_anthropic_client(
|
||||
) -> AnthropicClient:
|
||||
"""Helper function to create AnthropicClient instances for testing, bypassing normal validation."""
|
||||
if anthropic_settings is None:
|
||||
anthropic_settings = AnthropicSettings(api_key="test-api-key-12345", chat_model_id="claude-3-5-sonnet-20241022")
|
||||
anthropic_settings = AnthropicSettings(
|
||||
api_key="test-api-key-12345", chat_model_id="claude-3-5-sonnet-20241022", env_file_path="test.env"
|
||||
)
|
||||
|
||||
# Create client instance directly
|
||||
client = object.__new__(AnthropicClient)
|
||||
@@ -61,6 +63,7 @@ def create_test_anthropic_client(
|
||||
client._last_call_id_name = None
|
||||
client.additional_properties = {}
|
||||
client.middleware = None
|
||||
client.additional_beta_flags = []
|
||||
|
||||
return client
|
||||
|
||||
@@ -70,7 +73,7 @@ def create_test_anthropic_client(
|
||||
|
||||
def test_anthropic_settings_init(anthropic_unit_test_env: dict[str, str]) -> None:
|
||||
"""Test AnthropicSettings initialization."""
|
||||
settings = AnthropicSettings()
|
||||
settings = AnthropicSettings(env_file_path="test.env")
|
||||
|
||||
assert settings.api_key is not None
|
||||
assert settings.api_key.get_secret_value() == anthropic_unit_test_env["ANTHROPIC_API_KEY"]
|
||||
@@ -80,8 +83,7 @@ def test_anthropic_settings_init(anthropic_unit_test_env: dict[str, str]) -> Non
|
||||
def test_anthropic_settings_init_with_explicit_values() -> None:
|
||||
"""Test AnthropicSettings initialization with explicit values."""
|
||||
settings = AnthropicSettings(
|
||||
api_key="custom-api-key",
|
||||
chat_model_id="claude-3-opus-20240229",
|
||||
api_key="custom-api-key", chat_model_id="claude-3-opus-20240229", env_file_path="test.env"
|
||||
)
|
||||
|
||||
assert settings.api_key is not None
|
||||
@@ -114,6 +116,7 @@ def test_anthropic_client_init_auto_create_client(anthropic_unit_test_env: dict[
|
||||
client = AnthropicClient(
|
||||
api_key=anthropic_unit_test_env["ANTHROPIC_API_KEY"],
|
||||
model_id=anthropic_unit_test_env["ANTHROPIC_CHAT_MODEL_ID"],
|
||||
env_file_path="test.env",
|
||||
)
|
||||
|
||||
assert client.anthropic_client is not None
|
||||
@@ -307,7 +310,7 @@ def test_convert_tools_to_anthropic_format_code_interpreter(mock_anthropic_clien
|
||||
assert "tools" in result
|
||||
assert len(result["tools"]) == 1
|
||||
assert result["tools"][0]["type"] == "code_execution_20250825"
|
||||
assert result["tools"][0]["name"] == "code_interpreter"
|
||||
assert result["tools"][0]["name"] == "code_execution"
|
||||
|
||||
|
||||
def test_convert_tools_to_anthropic_format_mcp_tool(mock_anthropic_client: MagicMock) -> None:
|
||||
@@ -725,6 +728,32 @@ async def test_anthropic_client_integration_function_calling() -> None:
|
||||
assert has_function_call
|
||||
|
||||
|
||||
@pytest.mark.flaky
|
||||
@skip_if_anthropic_integration_tests_disabled
|
||||
async def test_anthropic_client_integration_hosted_tools() -> None:
|
||||
"""Integration test for hosted tools."""
|
||||
client = AnthropicClient()
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="What tools do you have available?")]
|
||||
tools = [
|
||||
HostedWebSearchTool(),
|
||||
HostedCodeInterpreterTool(),
|
||||
HostedMCPTool(
|
||||
name="example-mcp",
|
||||
url="https://learn.microsoft.com/api/mcp",
|
||||
approval_mode="never_require",
|
||||
),
|
||||
]
|
||||
|
||||
response = await client.get_response(
|
||||
messages=messages,
|
||||
chat_options=ChatOptions(tools=tools, max_tokens=100),
|
||||
)
|
||||
|
||||
assert response is not None
|
||||
assert response.text is not None
|
||||
|
||||
|
||||
@pytest.mark.flaky
|
||||
@skip_if_anthropic_integration_tests_disabled
|
||||
async def test_anthropic_client_integration_with_system_message() -> None:
|
||||
|
||||
Reference in New Issue
Block a user