Skip to content

Conversation

@xunxiing
Copy link
Contributor

@xunxiing xunxiing commented Jan 25, 2026


Modifications / 改动点

修复了 ProviderGoogleGenAI (Gemini) 适配器中导致工具调用无限循环的 Bug。

在构建 role == "tool" 的历史消息时,原代码错误地将 tool_call_id 当作了函数 name 传入,且没有显式绑定 idfunction_response 中。这导致 Gemini API 无法正确识别工具执行结果,从而让模型认为任务未完成并陷入死循环。

主要修改 (astrbot/core/provider/sources/gemini_source.py):

  1. 修正函数名映射:在 types.Part.from_function_response 中使用真实的函数名 (message.get("name")),而不是 ID。
  2. 显式绑定 ID:手动赋值 part.function_response.id = message["tool_call_id"],确保工具返回结果能正确匹配到对应的调用请求。
  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

Before Fix / 修复前:
(日志显示模型不断重复调用 chip_build,无法识别工具返回结果,陷入死循环。)
image

After Fix / 修复后:
image

(Gemini 正确识别了工具执行结果,并成功输出了最终总结文本,跳出了循环。)

Checklist / 检查清单

  • 😊 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。/ If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc. (Bug fix usually doesn't need this / 修复 Bug 通常不需要此项,可以不勾)
  • 👀 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。/ My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
  • 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.

@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jan 25, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `astrbot/core/provider/sources/gemini_source.py:385-387` </location>
<code_context>
-                ]
+                # 1. 尝试获取真实的函数名称 (AstrBot/OpenAI 格式的消息通常包含 name)
+                # 如果 message 中没有 name,说明上游数据丢失,这里可能需要 fallback 逻辑,但通常都会有
+                func_name = message.get("name", "unknown_tool")
+
+                # 2. 创建 Part,注意 name 参数必须是函数名
</code_context>

<issue_to_address>
**suggestion:** 建议将 `tool_call_id` 用作函数名的回退值,而不是使用泛化的字面量。

使用像 `"unknown_tool"` 这样的通用占位符,会让你在日志中更难将响应与其对应的工具调用关联起来。由于这里可以保证 `tool_call_id` 一定存在,并且之前也被用作函数名,因此使用 `message.get("name", message["tool_call_id"])` 可以在仍然优先使用显式 `name` 的同时,更好地保留可追踪性。

```suggestion
                # 1. 尝试获取真实的函数名称 (AstrBot/OpenAI 格式的消息通常包含 name)
                # 如果 message 中没有 name,则回退使用 tool_call_id,便于在日志中追踪来源
                func_name = message.get("name", message["tool_call_id"])
```
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的代码评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审质量。
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `astrbot/core/provider/sources/gemini_source.py:385-387` </location>
<code_context>
-                ]
+                # 1. 尝试获取真实的函数名称 (AstrBot/OpenAI 格式的消息通常包含 name)
+                # 如果 message 中没有 name,说明上游数据丢失,这里可能需要 fallback 逻辑,但通常都会有
+                func_name = message.get("name", "unknown_tool")
+
+                # 2. 创建 Part,注意 name 参数必须是函数名
</code_context>

<issue_to_address>
**suggestion:** Consider using `tool_call_id` as the fallback function name instead of a generic literal.

A generic placeholder like `"unknown_tool"` makes it harder to correlate responses with their originating tool calls, especially in logs. Since `tool_call_id` is guaranteed here and was previously used as the function name, using `message.get("name", message["tool_call_id"])` preserves traceability while still preferring an explicit `name` when present.

```suggestion
                # 1. 尝试获取真实的函数名称 (AstrBot/OpenAI 格式的消息通常包含 name)
                # 如果 message 中没有 name,则回退使用 tool_call_id,便于在日志中追踪来源
                func_name = message.get("name", message["tool_call_id"])
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot dosubot bot added the area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. label Jan 25, 2026
Soulter and others added 2 commits January 26, 2026 17:09
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Refactor function response handling for tool role to ensure proper ID injection.
@Soulter Soulter merged commit 3765dd4 into AstrBotDevs:master Jan 26, 2026
6 checks passed
@Soulter Soulter changed the title 修复gemini toolcall 的名称导致的循环调用 fix: repetition tool calls in gemini models Jan 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants