fix(config): correct Gemini official endpoint reasoning example (#6161)

* fix(config): correct Gemini official endpoint reasoning example

* docs: clarify official Gemini endpoint heading
This commit is contained in:
Insecshin 2026-10-02 22:32:21 +08:00 committed by GitHub
parent 23b366a101
commit 759136e074
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 72 additions and 40 deletions

View File

@ -121,6 +121,9 @@ Optional per-model [`request_admission`](backend/docs/CONFIGURATION.md#model-req
paces requests to help stay within provider request-per-minute limits.
It is disabled by default; see the linked guide to enable it.
For Google's official Gemini OpenAI-compatible endpoint, use the
[Gemini reasoning profile](backend/docs/CONFIGURATION.md#gemini-via-googles-openai-compatible-endpoint).
1. **Clone the DeerFlow repository**
```bash

View File

@ -269,7 +269,7 @@ models:
type: enabled
```
**Gemini with thinking via OpenAI-compatible gateway**:
#### Gemini via Google's OpenAI-compatible endpoint
When routing Gemini through an OpenAI-compatible proxy (Vertex AI OpenAI compat endpoint, AI Studio, or third-party gateways) with thinking enabled, the API attaches a `thought_signature` to each tool-call object returned in the response. Every subsequent request that replays those assistant messages **must** echo those signatures back on the tool-call entries or the API returns:
@ -282,22 +282,24 @@ Standard `langchain_openai:ChatOpenAI` silently drops `thought_signature` when s
```yaml
models:
- name: gemini-2.5-pro-thinking
display_name: Gemini 2.5 Pro (Thinking)
- name: gemini-3.1-pro-preview
display_name: Gemini 3.1 Pro (Thinking)
use: deerflow.models.patched_openai:PatchedChatOpenAI
model: google/gemini-2.5-pro-preview # model name as expected by your gateway
model: gemini-3.1-pro-preview
api_key: $GEMINI_API_KEY
base_url: https://<your-openai-compat-gateway>/v1
base_url: https://generativelanguage.googleapis.com/v1beta/openai/
max_tokens: 16384
supports_thinking: true
supports_vision: true
when_thinking_enabled:
extra_body:
thinking:
type: enabled
reasoning:
thinking: required
dialect: none
effort:
values: [minimal, low, medium, high]
```
For Gemini accessed **without** thinking (e.g. via OpenRouter where thinking is not activated), the plain `langchain_openai:ChatOpenAI` with `supports_thinking: false` is sufficient and no patch is needed.
This example targets Google's official endpoint. Its [OpenAI compatibility API](https://ai.google.dev/gemini-api/docs/openai#thinking) accepts `reasoning_effort`; `extra_body.thinking` becomes an unsupported top-level `thinking` field and causes HTTP 400. Gemini 3.1 Pro cannot disable thinking, so `thinking: required` keeps it enabled even when a caller requests otherwise, while `dialect: none` prevents a provider-specific thinking toggle. Omitting effort uses the model's default.
If you copied the previous example, replace its `supports_thinking`, `when_thinking_enabled`, and `when_thinking_disabled` settings with the `reasoning` block above. Third-party gateways may require different model IDs and reasoning parameters; follow that gateway's documentation instead of reusing Google's profile unchanged.
**MiMo with thinking via OpenAI-compatible API**:

View File

@ -39,21 +39,8 @@ class PatchedChatOpenAI(ChatOpenAI):
from ``AIMessage.additional_kwargs["tool_calls"]`` into the serialised
request payload before it is sent to the API.
Usage in ``config.yaml``::
- name: gemini-2.5-pro-thinking
display_name: Gemini 2.5 Pro (Thinking)
use: deerflow.models.patched_openai:PatchedChatOpenAI
model: google/gemini-2.5-pro-preview
api_key: $GEMINI_API_KEY
base_url: https://<your-openai-compat-gateway>/v1
max_tokens: 16384
supports_thinking: true
supports_vision: true
when_thinking_enabled:
extra_body:
thinking:
type: enabled
See the Gemini example in ``config.example.yaml`` for Google's official
OpenAI-compatible endpoint and its reasoning configuration.
"""
def _get_request_payload(

View File

@ -0,0 +1,41 @@
"""Exercise the shipped Gemini example through the model factory and OpenAI SDK."""
import json
from pathlib import Path
import httpx
import pytest
import yaml
from deerflow.config.app_config import AppConfig
from deerflow.config.model_config import ModelConfig
from deerflow.config.sandbox_config import SandboxConfig
from deerflow.models.factory import create_chat_model
@pytest.mark.parametrize("thinking_enabled,effort", [(True, None), (True, "medium"), (True, "high"), (False, "minimal")])
def test_gemini_example_request(thinking_enabled, effort):
example = (Path(__file__).resolve().parents[2] / "config.example.yaml").read_text(encoding="utf-8")
block = example.split(" # Example: Gemini model via ", 1)[1].split("\n\n", 1)[0]
lines = block[block.index(" # - name:") :].splitlines()
settings = yaml.safe_load("\n".join(line.removeprefix(" # ") for line in lines))[0]
settings["api_key"] = "test-key"
config = AppConfig(models=[ModelConfig(**settings)], sandbox=SandboxConfig(use="deerflow.sandbox.local:LocalSandboxProvider"))
requests = []
def respond(request):
requests.append(request)
return httpx.Response(200, json={"id": "test", "object": "chat.completion", "created": 0, "model": settings["model"], "choices": [{"index": 0, "message": {"role": "assistant", "content": "OK"}, "finish_reason": "stop"}]})
with httpx.Client(transport=httpx.MockTransport(respond)) as client:
model = create_chat_model(app_config=config, attach_tracing=False, thinking_enabled=thinking_enabled, reasoning_effort=effort, http_client=client)
assert model.invoke("Hello").content == "OK"
assert len(requests) == 1
payload = json.loads(requests[0].content)
assert "thinking" not in payload
assert payload.get("reasoning_effort") == effort
if effort is None:
assert "reasoning_effort" not in payload
assert payload["model"] == "gemini-3.1-pro-preview"
assert str(requests[0].url) == "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions"

View File

@ -430,31 +430,30 @@ models:
# context_window: 1048576
# supports_vision: true
# Example: Gemini model via OpenAI-compatible gateway (with thinking support)
# Example: Gemini model via Google's official OpenAI-compatible endpoint
# Use PatchedChatOpenAI so that tool-call thought_signature values on tool_calls
# are preserved across multi-turn tool-call conversations — required by the
# Gemini API when thinking is enabled. See:
# https://docs.cloud.google.com/vertex-ai/generative-ai/docs/thought-signatures
# - name: gemini-2.5-pro-thinking
# display_name: Gemini 2.5 Pro (Thinking)
# Google accepts reasoning_effort, not extra_body.thinking. Gemini 3.1 Pro
# cannot disable thinking; dialect: none avoids emitting a thinking toggle.
# https://ai.google.dev/gemini-api/docs/openai#thinking
# - name: gemini-3.1-pro-preview
# display_name: Gemini 3.1 Pro (Thinking)
# use: deerflow.models.patched_openai:PatchedChatOpenAI
# model: google/gemini-2.5-pro-preview # model name as expected by your gateway
# model: gemini-3.1-pro-preview
# api_key: $GEMINI_API_KEY
# base_url: https://<your-openai-compat-gateway>/v1
# base_url: https://generativelanguage.googleapis.com/v1beta/openai/
# request_timeout: 600.0
# max_retries: 2
# max_tokens: 16384
# context_window: 1048576
# supports_thinking: true
# supports_vision: true
# when_thinking_enabled:
# extra_body:
# thinking:
# type: enabled
# when_thinking_disabled:
# extra_body:
# thinking:
# type: disabled
# reasoning:
# thinking: required
# dialect: none
# effort:
# values: [minimal, low, medium, high]
# Example: Xiaomi MiMo model (with thinking support)
# MiMo thinking mode returns reasoning_content and requires that field to be