Skip to content

fix(antigravity): 让“返回思维链到前端”开关按配置生效 - #441

Closed
wan0ge wants to merge 1 commit into
su-kaka:masterfrom
wan0ge:fix/return-thoughts-toggle
Closed

wan0ge wants to merge 1 commit into
su-kaka:masterfrom
wan0ge:fix/return-thoughts-toggle

Conversation

@wan0ge

@wan0ge wan0ge commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

问题

如果只是重构还没做到这一块那么可以视情况不合()

控制面板与环境变量 RETURN_THOUGHTS_TO_FRONTEND 提供了“是否向客户端回传思维链”的开关,
config.py 的 get_return_thoughts_to_frontend() 已实现读取(默认 True)。
但 src/converter/antigravity_fix.py 的 normalize_antigravity_request 将 return_thoughts
固定为 True,该开关设置不生效:面板关闭后,思考内容仍随响应返回。

此外,_apply_thinking 对 none 类型模型(如 gemini-2.5-flash-lite)直接跳过,导致这类模型
即使携带 thinkingConfig 也不会写入 includeThoughts,开关对其同样无效。

修复

  • normalize_antigravity_request 以 await get_return_thoughts_to_frontend() 的结果作为 return_thoughts。
  • 请求侧:_apply_thinking 在模型带有 thinkingConfig 时写入 includeThoughts = return_thoughts
    (none 类型仅保留客户端思考深度参数,不额外施加预算);无 thinkingConfig 的模型不注入,
    避免影响不支持思考的模型。
  • 响应侧:在 stream_request / non_stream_request(Gemini / OpenAI / Anthropic 三个路由共用的出站出口)
    统一过滤——开关关闭时从 candidates[].content.parts[] 剔除 thought:true 的片段。
    实测后端会忽略 includeThoughts(出站确为 includeThoughts:false 仍回传思考),故响应侧过滤是必要补充;
    过滤只移除思考片段,保留答案、finishReason、usageMetadata。

行为范围

  • route(gemini-3 / gemini-4 / claude-5.5)与 budget(模型名含 think):includeThoughts 随开关。
  • none(如 gemini-2.5 系列含 flash-lite):若请求带有 thinkingConfig,保留其思考深度参数并按开关写入 includeThoughts。
  • 响应侧过滤对所有接口格式生效(Gemini / OpenAI / Anthropic,流式与非流式)。

测试

本地验证(未随仓库提交):

  • _apply_thinking 的 route/budget/none × 开/关(含 none 带客户端 thinkingConfig);
  • normalize_antigravity_request:route 开/关、budget 关闭保留预算、flash-lite 关闭/开启、none 无配置不注入;
  • 环境变量取值解析;
  • thought_filter:strip_thought_parts、filter_sse_chunk(str/bytes、{"response":...} 包装、[DONE]、非 data 行、
    非法 JSON、无改动原样返回)、filter_response_bytes(包装、非法内容)全部通过。

面板与环境变量 RETURN_THOUGHTS_TO_FRONTEND 提供“是否向客户端回传思维链”的开关,
但 normalize_antigravity_request 将 return_thoughts 固定为 True,开关设置不生效。

分支以 get_return_thoughts_to_frontend() 的结果作为 return_thoughts:
- 请求侧 _apply_thinking 在模型带有 thinkingConfig 时写入 includeThoughts(含 none 类型,
  保留客户端 thinkingBudget;无 thinkingConfig 的模型不注入)。
- 响应侧在 stream_request / non_stream_request 统一剔除 thought:true 片段(三格式共用出口),
  不依赖后端是否遵守 includeThoughts。

该开关只影响是否回传思考内容,不改变模型的思考预算/深度,也不对模型做白名单限制。
@su-kaka

su-kaka commented Oct 27, 2026

Copy link
Copy Markdown
Owner

参数加了 专门过滤就不用了

@su-kaka su-kaka closed this Oct 27, 2026
@wan0ge

wan0ge commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

参数加了 专门过滤就不用了

只加参数在我这边测试Gemini接口不知道为什么没用,所以才加的专门过滤hhhh

@su-kaka

su-kaka commented Oct 27, 2026

Copy link
Copy Markdown
Owner

可能客户端传了返回思维链参数过去?

@wan0ge

wan0ge commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

可能客户端传了返回思维链参数过去?

看了下客户端请求没有带includeThoughts参数所以很怪,佬你那边测试正常吗
我使用的客户端请求时只有下列参数

"generationConfig": {
  "temperature": 0.7,
  "thinkingConfig": {
    "thinkingBudget": -1 或 0
  }
}

@su-kaka

su-kaka commented Oct 27, 2026

Copy link
Copy Markdown
Owner

你可以打开详细日志 看看
我这边测试正常 开了就返回 关了就不返回

@wan0ge

wan0ge commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

还是没排查出原因()让ai测了下貌似我的Gemini模型思维链不受控制,claude正常

{
  "created_at": 1793093034.8973846,
  "request_id": "6d0bcafafdad4a7b",
  "model_name": "gemini-2.5-flash-lite",
  "upstream_model_name": "gemini-2.5-flash-lite",
  "credential_email": "0",
  "is_stream": false,
  "status_code": 200,
  "url": "https://0/GoogleAntigravity//v1internal:generateContent",
  "request_headers": {
    "User-Agent": "antigravity/cli/1.4.8 windows/amd64",
    "Authorization": "(已脱敏)",
    "Content-Type": "application/json",
    "Accept": "*/*",
    "Accept-Encoding": "gzip",
    "Connection": "close",
    "requestId": "req-ea402f00-9e34-4257-9d63-23ef2b1bfd6b",
    "requestType": "agent"
  },
  "request_body": {
    "project": "aicode-consumers",
    "requestId": "agent/e22c1fd3-3c1b-4615-941d-76ee2a3e7fa9/1793093031702/9d4e9092-3e27-4b6c-8638-9ef142b6ea6f/1",
    "request": {
      "contents": [
        {
          "role": "user",
          "parts": [
            {
              "text": "You are a professional translation engine, please translate the text into a colloquial, professional, elegant and fluent content, without the style of machine translation. You must only translate the text content, never interpret it."
            }
          ]
        },
        {
          "role": "model",
          "parts": [
            {
              "text": "Ok, I will only translate the text content, never interpret it"
            }
          ]
        },
        {
          "role": "user",
          "parts": [
            {
              "text": "Translate the following text from en to zh: hello world"
            }
          ]
        },
        {
          "role": "model",
          "parts": [
            {
              "text": "你好,世界"
            }
          ]
        },
        {
          "role": "user",
          "parts": [
            {
              "text": "Translate the following text from English to Simplified Chinese: install"
            }
          ]
        }
      ],
      "generationConfig": {
        "temperature": 0.7,
        "thinkingConfig": {
          "thinkingBudget": -1
        },
        "maxOutputTokens": 64000,
        "topK": 64
      },
      "sessionId": "-6060038299408623030",
      "labels": {
        "last_step_index": "1",
        "model_enum": "gemini-2.5-flash-lite",
        "trajectory_id": "-6060038299408623030",
        "used_claude": "false",
        "used_claude_conservative": "false"
      },
      "toolConfig": {
        "functionCallingConfig": {
          "mode": "VALIDATED"
        }
      }
    },
    "model": "gemini-2.5-flash-lite",
    "requestType": "agent"
  },
  "response_body": "",
  "error_message": ""
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants