-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Python: Anthropic function calling fixes (#9938)
### Motivation and Context <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> The current implementation of the Anthropic connector relies on the `inner_content`s in chat messages to prepare the chat history for the Anthropic client. This will only work when the chat history is created by the Anthropic connector. This won't work if the chat history has been processed by other connectors, or if it is hardcoded as in testing. ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> 1. Prepare the chat history for the Anthropic client by parsing the actual Semantic Kernel item types. 2. Fix tests for the Anthropic connector. ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone 😄
- Loading branch information
1 parent
b427208
commit 4a21254
Showing
4 changed files
with
154 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
python/semantic_kernel/connectors/ai/anthropic/services/utils.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# Copyright (c) Microsoft. All rights reserved. | ||
|
||
import json | ||
import logging | ||
from collections.abc import Callable, Mapping | ||
from typing import Any | ||
|
||
from semantic_kernel.contents.chat_message_content import ChatMessageContent | ||
from semantic_kernel.contents.function_call_content import FunctionCallContent | ||
from semantic_kernel.contents.function_result_content import FunctionResultContent | ||
from semantic_kernel.contents.text_content import TextContent | ||
from semantic_kernel.contents.utils.author_role import AuthorRole | ||
|
||
logger: logging.Logger = logging.getLogger(__name__) | ||
|
||
|
||
def _format_user_message(message: ChatMessageContent) -> dict[str, Any]: | ||
"""Format a user message to the expected object for the Anthropic client. | ||
Args: | ||
message: The user message. | ||
Returns: | ||
The formatted user message. | ||
""" | ||
return { | ||
"role": "user", | ||
"content": message.content, | ||
} | ||
|
||
|
||
def _format_assistant_message(message: ChatMessageContent) -> dict[str, Any]: | ||
"""Format an assistant message to the expected object for the Anthropic client. | ||
Args: | ||
message: The assistant message. | ||
Returns: | ||
The formatted assistant message. | ||
""" | ||
tool_calls: list[dict[str, Any]] = [] | ||
|
||
for item in message.items: | ||
if isinstance(item, TextContent): | ||
# Assuming the assistant message will have only one text content item | ||
# and we assign the content directly to the message content, which is a string. | ||
continue | ||
if isinstance(item, FunctionCallContent): | ||
tool_calls.append({ | ||
"type": "tool_use", | ||
"id": item.id or "", | ||
"name": item.name or "", | ||
"input": item.arguments if isinstance(item.arguments, Mapping) else json.loads(item.arguments or ""), | ||
}) | ||
else: | ||
logger.warning( | ||
f"Unsupported item type in Assistant message while formatting chat history for Anthropic: {type(item)}" | ||
) | ||
|
||
if tool_calls: | ||
return { | ||
"role": "assistant", | ||
"content": [ | ||
{ | ||
"type": "text", | ||
"text": message.content, | ||
}, | ||
*tool_calls, | ||
], | ||
} | ||
|
||
return { | ||
"role": "assistant", | ||
"content": message.content, | ||
} | ||
|
||
|
||
def _format_tool_message(message: ChatMessageContent) -> dict[str, Any]: | ||
"""Format a tool message to the expected object for the Anthropic client. | ||
Args: | ||
message: The tool message. | ||
Returns: | ||
The formatted tool message. | ||
""" | ||
function_result_contents: list[dict[str, Any]] = [] | ||
for item in message.items: | ||
if not isinstance(item, FunctionResultContent): | ||
logger.warning( | ||
f"Unsupported item type in Tool message while formatting chat history for Anthropic: {type(item)}" | ||
) | ||
continue | ||
function_result_contents.append({ | ||
"type": "tool_result", | ||
"tool_use_id": item.id, | ||
"content": str(item.result), | ||
}) | ||
|
||
return { | ||
"role": "user", | ||
"content": function_result_contents, | ||
} | ||
|
||
|
||
MESSAGE_CONVERTERS: dict[AuthorRole, Callable[[ChatMessageContent], dict[str, Any]]] = { | ||
AuthorRole.USER: _format_user_message, | ||
AuthorRole.ASSISTANT: _format_assistant_message, | ||
AuthorRole.TOOL: _format_tool_message, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters