Skip to content

fix(gemini): automatically disable thinking config when tools are present#8742

Open
Rat0323 wants to merge 3 commits into
AstrBotDevs:masterfrom
Rat0323:fix/gemini-thinking-conflict
Open

fix(gemini): automatically disable thinking config when tools are present#8742
Rat0323 wants to merge 3 commits into
AstrBotDevs:masterfrom
Rat0323:fix/gemini-thinking-conflict

Conversation

@Rat0323

@Rat0323 Rat0323 commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Pull Request: fix(gemini): automatically disable thinking config when tools are present to prevent API conflict

🚀 变更类型 | Type of Change

  • Bug 修复 (Bug fix which fixes an issue)
  • 代码优化 (Code refinement without breaking changes)

📝 问题背景与核心痛点 | Background and Problem

1. Gemini 官方 API 的硬性限制

根据 Google Gemini API (Google GenAI) 的官方规范,思考模式 (Reasoning/Thinking) 与工具调用 (Function Calling / Tool Use) 在同一次请求中是互斥原生互斥的
如果向接口传递了 thinking_config,同时又在 tools 中声明了函数或启用了原生工具(如搜索落地、代码执行等),Gemini API 将会直接报错拒绝服务,或者模型会在回复中以文本脑补、输出模拟代码的形式来逃避工具执行。

2. AstrBot 原有代码的问题

在原版的 ProviderGoogleGenAI(位于 astrbot/core/provider/sources/gemini_source.py)中,思考配置的装配逻辑是强绑定的:

  • Gemini 2.5 即使设置 budget=0,也会向 API 传递装配好的 ThinkingConfig 对象。
  • Gemini 3 分支中对 thinking_level 进行了枚举强校验。当需要使用工具时,即使在配置中关闭,代码也会因为校验不通过而自动将其重置并回推到默认的 "HIGH",导致 API 始终带有思考配置,进而彻底瘫痪了工具调用能力。

这导致所有使用 Gemini 模型的用户在开启思考深度(默认模板通常开启)时,无法使用任何需要注册工具的插件(例如 Tavily 搜索、各种长期记忆/RAG插件、GitHub 卡片等)。


🛠️ 解决方案与代码审计 | Proposed Changes & Code Audit

我们采用的是一种自适应覆写 (Auto-Adaptive Override) 的最简 Diff 方案。在 _prepare_query_config 函数的最后、组装配置并返回(return types.GenerateContentConfig(...))的紧前位置,当检测到有工具并且思考模式是开启状态时,输出警告日志并关闭思考选项:

        # If any tools (native or custom function declarations) are active for this request,
        # we must disable thinking because Gemini API does not support them simultaneously.
        if tool_list and thinking_config:
            if getattr(thinking_config, "thinking_budget", None) != 0:
                logger.warning("[Gemini] Thinking config is automatically disabled because tools are active for this request.")
            thinking_config = None

🔍 逻辑审计与可行性论证(为什么这是最优解):

  1. 精确拦截
    tool_list 是当前请求已经收集完毕的工具列表(包括原生工具和第三方自定义函数)。在 Python 中,空列表 []None 会被评估为 False,只有在确实有工具要执行时,if tool_list: 才会被触发为 True
  2. 高可观测性且无噪音 (Zero Log Noise)
    仅在思考功能被配置启用时,自动关闭才会输出 logger.warning 警告日志。如果用户已经显式将 thinking_budget 设为了 0(代表预期关闭思考),则通过 getattr 判断静默切断,避免产生多余的“噪音”日志。
  3. 安全覆写
    在检测到 tool_list 有效时,强行将 thinking_config 置为 None。根据 google-genai SDK 规范,不传递或传递 None 即代表不启用思考模式。这完美避开了 API 冲突。
  4. 零副作用
    由于采用后置覆盖,我们不需要修改原先 Gemini 2.5/3 任何复杂的参数装配和缩进结构,保留了配置项原有的纯净性。当日常对话不需要工具时,代码依然会尊重用户在 UI 界面上设置的思考深度(如 HIGHMEDIUM)。

🧪 调试与测试结果 | Testing & Validation

我们对该补丁在生产环境中进行了多轮高强度测试,测试结果完全符合预期:

测试场景 A:第三方工具调用测试(如 GitHub PR 插件)

  • 测试输入:发送一条包含 GitHub PR 链接的消息,触发 get_pull_request 工具。
  • 控制台日志与表现
    1. 系统检测到有工具需要调用,将 tool_list 装配为 [Tool(get_pull_request)]
    2. 触发拦截逻辑,由于 thinking_budget > 0 或者是 Gemini 3 模型在开启思考,会在控制台和日志文件中输出日志:[Gemini] Thinking config is automatically disabled because tools are active for this request.
    3. thinking_config 自动降级为 None
    4. API 成功响应并正常发起函数调用(FunctionCall),没有抛出任何 API 冲突异常,也没有在文字中“脑补”Python代码。
    5. 插件成功获取 PR 信息并渲染回复给用户。

测试场景 B:日常逻辑推理测试(无工具调用)

  • 测试输入:发送一个纯文字的逻辑推理问题(例如“证明庞加莱猜想”或日常闲聊)。
  • 控制台日志与表现
    1. 本次请求未关联任何工具,tool_list 保持为 None
    2. 自适应拦截未触发,思考配置保留为用户配置的级别(如 MEDIUMHIGH)。
    3. 模型回复前成功输出了 <think> 思维链内容,展现了完整的深度推理过程,且日志中无警告打印。

📊 审计结论

该修复方案仅用 4 行逻辑代码就完全消除了 Gemini 接口级的功能物理冲突,完美实现了“工具调用时防崩溃自适应,日常闲聊时高商思考”的最佳效果。代码无多余副作用,建议合并。

@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. labels Jun 12, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates the Gemini provider source to automatically disable the thinking configuration when tools are active, preventing API errors since Gemini does not support both simultaneously. The reviewer suggested adding a warning log when this automatic disabling occurs to improve observability and prevent confusion, which is a valuable improvement.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +297 to +298
if tool_list:
thinking_config = None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

When thinking_config is automatically disabled due to the presence of tools, it is highly recommended to log a warning message. This provides crucial observability for users and developers, preventing confusion as to why the model's thinking/reasoning mode is not active when plugins or tools are triggered.

Suggested change
if tool_list:
thinking_config = None
if tool_list and thinking_config:
logger.warning("[Gemini] Thinking config is automatically disabled because tools are active for this request.")
thinking_config = None

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Given that tool_list may be None or different iterable types over time, consider making the condition more explicit (e.g., if tool_list is not None and len(tool_list) > 0) to avoid surprising behavior if tool_list changes shape in future refactors.
  • Since this override changes user-visible behavior when tools are present, it might be safer to route this through a small helper (e.g., disable_thinking_if_tools) so the intent is centralized and future changes to tool handling don’t accidentally bypass this constraint.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Given that `tool_list` may be `None` or different iterable types over time, consider making the condition more explicit (e.g., `if tool_list is not None and len(tool_list) > 0`) to avoid surprising behavior if `tool_list` changes shape in future refactors.
- Since this override changes user-visible behavior when tools are present, it might be safer to route this through a small helper (e.g., `disable_thinking_if_tools`) so the intent is centralized and future changes to tool handling don’t accidentally bypass this constraint.

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.

@Rat0323 Rat0323 force-pushed the fix/gemini-thinking-conflict branch from 54c1a72 to 851b526 Compare June 12, 2026 13:58
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:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant