Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 191f595

Browse files
authoredMar 6, 2025
Python: Remove custom separator in Bedrock tool call fully qualified name (microsoft#10826)
### 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. --> Closes microsoft#10619 Bedrock updated its rules on tool names. Previously, Bedrock disallowed "-" in tool names, which is the default plugin name and function name separator in SK. The solution was to use "_" as the separator. However, this introduced a bug where the translation between the SK fully qualified function names and the Bedrock tool names would fail if the function name had an underscore. Bedrock now allows "-" in tool names, so we can remove the custom logic and just use the default. Gemini also has rules on how tools are named. It doesn't recommend using "-". The solution was to use "_" just like Bedrock. To address the bug mentioned above, the solution is to use double underscores. ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> 1. Remove Bedrock custom fully qualified function names. 2. Use double underscores for Gemini fully qualified function names. TODO: Add a guide for SK function/plugin naming conventions. ### 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 - [ ] I didn't break anyone 😄
1 parent bfc8b40 commit 191f595

File tree

5 files changed

+12
-32
lines changed

5 files changed

+12
-32
lines changed
 

‎python/samples/concepts/setup/chat_completion_services.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,14 @@ def get_bedrock_chat_completion_service_and_request_settings() -> tuple[
213213
"""
214214
from semantic_kernel.connectors.ai.bedrock import BedrockChatCompletion, BedrockChatPromptExecutionSettings
215215

216-
chat_service = BedrockChatCompletion(service_id=service_id, model_id="cohere.command-r-v1:0")
216+
chat_service = BedrockChatCompletion(service_id=service_id, model_id="anthropic.claude-3-sonnet-20240229-v1:0")
217217
request_settings = BedrockChatPromptExecutionSettings(
218218
# For model specific settings, specify them in the extension_data dictionary.
219219
# For example, for Cohere Command specific settings, refer to:
220-
# https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-cohere-command-r-plus.html
220+
# https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html
221221
service_id=service_id,
222222
extension_data={
223-
"presence_penalty": 0.5,
224-
"seed": 5,
223+
"temperature": 0.8,
225224
},
226225
)
227226

‎python/semantic_kernel/connectors/ai/bedrock/services/bedrock_chat_completion.py

+2-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from semantic_kernel.connectors.ai.bedrock.services.model_provider.utils import (
2222
MESSAGE_CONVERTERS,
2323
finish_reason_from_bedrock_to_semantic_kernel,
24-
format_bedrock_function_name_to_kernel_function_fully_qualified_name,
2524
remove_none_recursively,
2625
update_settings_from_function_choice_configuration,
2726
)
@@ -254,9 +253,7 @@ def _create_chat_message_content(self, response: dict[str, Any]) -> ChatMessageC
254253
items.append(
255254
FunctionCallContent(
256255
id=content["toolUse"]["toolUseId"],
257-
name=format_bedrock_function_name_to_kernel_function_fully_qualified_name(
258-
content["toolUse"]["name"]
259-
),
256+
name=content["toolUse"]["name"],
260257
arguments=content["toolUse"]["input"],
261258
)
262259
)
@@ -323,9 +320,7 @@ def _parse_content_block_start_event(self, event: dict[str, Any]) -> StreamingCh
323320
items.append(
324321
FunctionCallContent(
325322
id=event["contentBlockStart"]["start"]["toolUse"]["toolUseId"],
326-
name=format_bedrock_function_name_to_kernel_function_fully_qualified_name(
327-
event["contentBlockStart"]["start"]["toolUse"]["name"]
328-
),
323+
name=event["contentBlockStart"]["start"]["toolUse"]["name"],
329324
)
330325
)
331326

‎python/semantic_kernel/connectors/ai/bedrock/services/model_provider/utils.py

+3-19
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
from semantic_kernel.connectors.ai.bedrock.bedrock_prompt_execution_settings import BedrockChatPromptExecutionSettings
88
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceType
9-
from semantic_kernel.const import DEFAULT_FULLY_QUALIFIED_NAME_SEPARATOR
109
from semantic_kernel.contents.chat_message_content import ChatMessageContent
1110
from semantic_kernel.contents.function_call_content import FunctionCallContent
1211
from semantic_kernel.contents.function_result_content import FunctionResultContent
@@ -102,7 +101,7 @@ def _format_assistant_message(message: ChatMessageContent) -> dict[str, Any]:
102101
contents.append({
103102
"toolUse": {
104103
"toolUseId": item.id,
105-
"name": item.custom_fully_qualified_name(BEDROCK_FUNCTION_NAME_SEPARATOR),
104+
"name": item.name,
106105
"input": item.arguments
107106
if isinstance(item.arguments, Mapping)
108107
else json.loads(item.arguments or "{}"),
@@ -157,19 +156,6 @@ def _format_tool_message(message: ChatMessageContent) -> dict[str, Any]:
157156
AuthorRole.TOOL: _format_tool_message,
158157
}
159158

160-
# The separator used in the fully qualified name of the function instead of the default "-" separator.
161-
# This is required since Bedrock disallows "-" in the function name.
162-
# https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ToolSpecification.html#API_runtime_ToolSpecification_Contents
163-
BEDROCK_FUNCTION_NAME_SEPARATOR = "_"
164-
165-
166-
def format_bedrock_function_name_to_kernel_function_fully_qualified_name(bedrock_function_name: str) -> str:
167-
"""Format the Bedrock function name to the kernel function fully qualified name."""
168-
if BEDROCK_FUNCTION_NAME_SEPARATOR in bedrock_function_name:
169-
plugin_name, function_name = bedrock_function_name.split(BEDROCK_FUNCTION_NAME_SEPARATOR, 1)
170-
return f"{plugin_name}{DEFAULT_FULLY_QUALIFIED_NAME_SEPARATOR}{function_name}"
171-
return bedrock_function_name
172-
173159

174160
def update_settings_from_function_choice_configuration(
175161
function_choice_configuration: "FunctionCallChoiceConfiguration",
@@ -198,16 +184,14 @@ def update_settings_from_function_choice_configuration(
198184
else:
199185
settings.tool_choice = {
200186
"tool": {
201-
"name": function_choice_configuration.available_functions[0].custom_fully_qualified_name(
202-
BEDROCK_FUNCTION_NAME_SEPARATOR
203-
),
187+
"name": function_choice_configuration.available_functions[0].fully_qualified_name,
204188
}
205189
}
206190

207191
settings.tools = [
208192
{
209193
"toolSpec": {
210-
"name": function.custom_fully_qualified_name(BEDROCK_FUNCTION_NAME_SEPARATOR),
194+
"name": function.fully_qualified_name,
211195
"description": function.description or "",
212196
"inputSchema": {
213197
"json": {

‎python/semantic_kernel/connectors/ai/google/shared_utils.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ def filter_system_message(chat_history: ChatHistory) -> str | None:
3838
# The separator used in the fully qualified name of the function instead of the default "-" separator.
3939
# This is required since Gemini doesn't work well with "-" in the function name.
4040
# https://ai.google.dev/gemini-api/docs/function-calling#function_declarations
41-
GEMINI_FUNCTION_NAME_SEPARATOR = "_"
41+
# Using double underscore to avoid situations where the function name already contains a single underscore.
42+
# For example, we may incorrect split a function name with a single score when the function doesn't have a plugin name.
43+
GEMINI_FUNCTION_NAME_SEPARATOR = "__"
4244

4345

4446
def format_gemini_function_name_to_kernel_function_fully_qualified_name(gemini_function_name: str) -> str:

‎python/tests/integration/completions/chat_completion_test_base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def services(self) -> dict[str, tuple[ServiceType | None, type[PromptExecutionSe
160160
BedrockChatPromptExecutionSettings,
161161
),
162162
"bedrock_anthropic_claude": (
163-
self._try_create_bedrock_chat_completion_client("anthropic.claude-3-5-sonnet-20240620-v1:0"),
163+
self._try_create_bedrock_chat_completion_client("anthropic.claude-3-sonnet-20240229-v1:0"),
164164
BedrockChatPromptExecutionSettings,
165165
),
166166
"bedrock_cohere_command": (

0 commit comments

Comments
 (0)
Please sign in to comment.