mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Introducing the Anthropic Client (#1819)
* initial version of anthropic connector * updated implementation and added tests * fix type and readme * mypy fix and int tests enabled * add integration test setup * updated based on comments * improved function result handling * added extra unordered test * updated from review * fix tool choice handling * same fix for chat client
This commit is contained in:
committed by
GitHub
Unverified
parent
a766a81243
commit
12d17acdc0
@@ -690,12 +690,12 @@ class BaseChatClient(SerializationMixin, ABC):
|
||||
chat_tool_mode = chat_options.tool_choice
|
||||
if chat_tool_mode is None or chat_tool_mode == ToolMode.NONE or chat_tool_mode == "none":
|
||||
chat_options.tools = None
|
||||
chat_options.tool_choice = ToolMode.NONE.mode
|
||||
chat_options.tool_choice = ToolMode.NONE
|
||||
return
|
||||
if not chat_options.tools:
|
||||
chat_options.tool_choice = ToolMode.NONE.mode
|
||||
chat_options.tool_choice = ToolMode.NONE
|
||||
else:
|
||||
chat_options.tool_choice = chat_tool_mode.mode if isinstance(chat_tool_mode, ToolMode) else chat_tool_mode
|
||||
chat_options.tool_choice = chat_tool_mode
|
||||
|
||||
def service_url(self) -> str:
|
||||
"""Get the URL of the service.
|
||||
|
||||
@@ -561,7 +561,7 @@ class BaseContent(SerializationMixin):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -651,7 +651,7 @@ class TextContent(BaseContent):
|
||||
*,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
"""Initializes a TextContent instance.
|
||||
@@ -793,7 +793,7 @@ class TextReasoningContent(BaseContent):
|
||||
*,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
"""Initializes a TextReasoningContent instance.
|
||||
@@ -936,7 +936,7 @@ class DataContent(BaseContent):
|
||||
self,
|
||||
*,
|
||||
uri: str,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -962,7 +962,7 @@ class DataContent(BaseContent):
|
||||
*,
|
||||
data: bytes,
|
||||
media_type: str,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -989,7 +989,7 @@ class DataContent(BaseContent):
|
||||
uri: str | None = None,
|
||||
data: bytes | None = None,
|
||||
media_type: str | None = None,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1093,7 +1093,7 @@ class UriContent(BaseContent):
|
||||
uri: str,
|
||||
media_type: str,
|
||||
*,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1187,7 +1187,7 @@ class ErrorContent(BaseContent):
|
||||
message: str | None = None,
|
||||
error_code: str | None = None,
|
||||
details: str | None = None,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1271,7 +1271,7 @@ class FunctionCallContent(BaseContent):
|
||||
name: str,
|
||||
arguments: str | dict[str, Any | None] | None = None,
|
||||
exception: Exception | None = None,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1380,7 +1380,7 @@ class FunctionResultContent(BaseContent):
|
||||
call_id: str,
|
||||
result: Any | None = None,
|
||||
exception: Exception | None = None,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1438,7 +1438,7 @@ class UsageContent(BaseContent):
|
||||
self,
|
||||
details: UsageDetails | MutableMapping[str, Any],
|
||||
*,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1556,7 +1556,7 @@ class BaseUserInputRequest(BaseContent):
|
||||
self,
|
||||
*,
|
||||
id: str,
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1610,7 +1610,7 @@ class FunctionApprovalResponseContent(BaseContent):
|
||||
*,
|
||||
id: str,
|
||||
function_call: FunctionCallContent | MutableMapping[str, Any],
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -1674,7 +1674,7 @@ class FunctionApprovalRequestContent(BaseContent):
|
||||
*,
|
||||
id: str,
|
||||
function_call: FunctionCallContent | MutableMapping[str, Any],
|
||||
annotations: list[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
annotations: Sequence[Annotations | MutableMapping[str, Any]] | None = None,
|
||||
additional_properties: dict[str, Any] | None = None,
|
||||
raw_representation: Any | None = None,
|
||||
**kwargs: Any,
|
||||
@@ -3146,7 +3146,7 @@ class ChatOptions(SerializationMixin):
|
||||
@classmethod
|
||||
def _validate_tool_mode(
|
||||
cls, tool_choice: ToolMode | Literal["auto", "required", "none"] | Mapping[str, Any] | None
|
||||
) -> ToolMode | str | None:
|
||||
) -> ToolMode | None:
|
||||
"""Validates the tool_choice field to ensure it is a valid ToolMode."""
|
||||
if not tool_choice:
|
||||
return None
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import importlib
|
||||
from typing import Any
|
||||
|
||||
PACKAGE_NAME = "agent_framework_anthropic"
|
||||
PACKAGE_EXTRA = "anthropic"
|
||||
_IMPORTS = ["__version__", "AnthropicClient"]
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
if name in _IMPORTS:
|
||||
try:
|
||||
return getattr(importlib.import_module(PACKAGE_NAME), name)
|
||||
except ModuleNotFoundError as exc:
|
||||
raise ModuleNotFoundError(
|
||||
f"The '{PACKAGE_EXTRA}' extra is not installed, please do `pip install agent-framework-{PACKAGE_EXTRA}`"
|
||||
) from exc
|
||||
raise AttributeError(f"Module {PACKAGE_NAME} has no attribute {name}.")
|
||||
|
||||
|
||||
def __dir__() -> list[str]:
|
||||
return _IMPORTS
|
||||
@@ -0,0 +1,5 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from agent_framework_anthropic import AnthropicClient, __version__
|
||||
|
||||
__all__ = ["AnthropicClient", "__version__"]
|
||||
@@ -408,7 +408,7 @@ class OpenAIAssistantsClient(OpenAIConfigMixin, BaseChatClient):
|
||||
run_options["tools"] = tool_definitions
|
||||
|
||||
if chat_options.tool_choice == "none" or chat_options.tool_choice == "auto":
|
||||
run_options["tool_choice"] = chat_options.tool_choice
|
||||
run_options["tool_choice"] = chat_options.tool_choice.mode
|
||||
elif (
|
||||
isinstance(chat_options.tool_choice, ToolMode)
|
||||
and chat_options.tool_choice == "required"
|
||||
|
||||
@@ -191,6 +191,8 @@ class OpenAIBaseChatClient(OpenAIBase, BaseChatClient):
|
||||
for key, value in additional_properties.items():
|
||||
if value is not None:
|
||||
options_dict[key] = value
|
||||
if (tool_choice := options_dict.get("tool_choice")) and len(tool_choice.keys()) == 1:
|
||||
options_dict["tool_choice"] = tool_choice["mode"]
|
||||
return options_dict
|
||||
|
||||
def _create_chat_response(self, response: ChatCompletion, chat_options: ChatOptions) -> "ChatResponse":
|
||||
|
||||
@@ -345,6 +345,8 @@ class OpenAIBaseResponsesClient(OpenAIBase, BaseChatClient):
|
||||
options_dict[key] = value
|
||||
if "store" not in options_dict:
|
||||
options_dict["store"] = False
|
||||
if (tool_choice := options_dict.get("tool_choice")) and len(tool_choice.keys()) == 1:
|
||||
options_dict["tool_choice"] = tool_choice["mode"]
|
||||
return options_dict
|
||||
|
||||
def _prepare_chat_messages_for_request(self, chat_messages: Sequence[ChatMessage]) -> list[dict[str, Any]]:
|
||||
|
||||
@@ -45,6 +45,8 @@ all = [
|
||||
"agent-framework-mem0",
|
||||
"agent-framework-redis",
|
||||
"agent-framework-devui",
|
||||
"agent-framework-purview",
|
||||
"agent-framework-anthropic",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
|
||||
Reference in New Issue
Block a user