~/blog/swe-bench-local-models-framework-matters

DGX Spark · part 15

[AI Agent] Gemma 4 從 40 次失敗到 9 步修好 Bug — 只換了一個東西

cat --toc

TL;DR

可行性測試,不是完整 benchmark。 Gemma 4 26B 在 OpenHands 上 40+ 次 tool calling 錯誤,換到 SWE-agent 後 9 步修好測試 bug。同一個模型、同一台 GX10。整條路通了,完整 SWE-Bench Lite(300 題)是下一步。

白話版:桌上型 AI 電腦能修真正的 bug 嗎?

SWE-Bench 是測試 AI 能不能修真實軟體 bug 的標準測驗 — 它從知名開源專案拿真實的 GitHub issue,看 AI 能不能產出能用的修復 patch。排行榜上幾乎全是 Claude 和 GPT 透過雲端 API 跑的。

我想知道能不能完全跳過 API 帳單 — 在自己的硬體上用開源模型跑。所以在 DGX Spark 上測了 Gemma 4 26B 和 Qwen 3.5 35B,先試 OpenHands,再試 SWE-agent。花了四個小時以為 Gemma 4 壞了,最後才發現問題出在 OpenHands 不在模型。


環境

  • 硬體: NVIDIA DGX Spark(GB10,128 GB unified memory,SM121)
  • 模型: Gemma 4 26B-A4B NVFP4、Qwen 3.5 35B-A3B FP8 — 都透過 vLLM 服務
  • 框架: OpenHands v0.59.0、SWE-agent v1.1.0
  • Agent 主機: Mac mini M4(16 GB,OrbStack Docker)— 跑 agent + sandbox,透過 Tailscale 連 GX10 vLLM

測試一:OpenHands — Function Calling 地獄

OpenHands 用 OpenAI 格式的 function calling — 模型收到 JSON 格式的 tool schema,必須回傳結構化的 tool_calls 物件。它對外暴露 11 個 tools:execute_bashstr_replace_editorthinkfinishbrowserexecute_ipython_celltask_trackerfetchcreate_prcreate_mrcreate_bitbucket_pr

任務:「寫一個檢查質數的 Python 函式,包含測試。」

Gemma 4 26B on OpenHands:40+ 次 error

每種 parser 設定都失敗:

--tool-call-parser成功前的 error 次數結果
pythonic5只出了 task_tracker:plan
hermes4同上
7同上
gemma4 + 官方 chat template40+從未完成任務

Error 都是同一個 pattern:

Missing required parameters for function 'execute_bash': {'command', 'security_risk'}
Missing required parameters for function 'str_replace_editor': {'path', 'command', 'security_risk'}

Gemma 4 呼叫了正確的 function 但參數通通漏掉。每一次都是。

但 API 明明是通的?

這是讓我 debug 了好幾個小時的原因。同樣 11 tools + 完整 OpenHands system prompt(8,892 字)用 curl 打?完美:

curl http://<gx10-ip>:8000/v1/chat/completions -d '{
  "model": "gemma-4-26b",
  "messages": [{"role": "system", "content": "<8892 字的 OpenHands prompt>"},
               {"role": "user", "content": "Create hello.py"}],
  "tools": [<全部 11 個 tools>]
}'

回應:正確的 str_replace_editor 呼叫,所有參數都帶了。API 層面沒問題。框架的多輪對話不知為何把它搞壞了。

Qwen 3.5 35B on OpenHands:成功(有條件)

Qwen 3.5 用 1 個 error 就完成了同樣的任務 — 漏了一次 security_risk 參數,然後自己修正了:

✅ 建了 prime_check.py,裡面有 is_prime() 函式
✅ 跑了 python3 prime_check.py — 所有測試通過
✅ 任務完成

關鍵設定: Qwen 3.5 的 --reasoning-parser qwen3 必須拿掉。開著的話所有 output 都被當 thinking token 消化掉,回傳內容是空的。用 --tool-call-parser qwen3_xml,不要加 reasoning parser。


測試二:SWE-agent — 換個 action 格式,換個世界

SWE-agent 根本不用 function calling。模型就寫純文字,框架自己解析:

💭 THOUGHT
我需要看一下有語法錯誤的那個檔案。

🎬 ACTION
str_replace_editor view /repo/tests/missing_colon.py

框架負責解析文字。完全不涉及 OpenAI function calling。

任務: 修復 SWE-agent/test-repo#1 的 bug — Python function 定義少了一個冒號,造成 SyntaxError。這是 SWE-agent 自己的測試 repo,不是真正的 SWE-Bench 題目 — 刻意簡單,用來驗證整條路通不通。

Gemma 4 26B on SWE-agent:9 步完成,patch 已提交

Step 1: find . -maxdepth 2 -not -path '*/.*'     → 看 repo 結構
Step 2: cat tests/missing_colon.py                → 讀了有 bug 的檔案
Step 3: python3 tests/missing_colon.py            → 重現了 error
Step 4: cat tests/missing_colon.py                → 確認問題位置
Step 5: str_replace_editor(路徑錯)              → 自己修正路徑
Step 6: str_replace_editor str_replace             → 修好 bug ✅
Step 7: python3 tests/missing_colon.py            → 驗證修復 ✅
Step 8-9: submit                                   → 提交 patch ✅

Patch 內容:

-def division(a: float, b: float) -> float
+def division(a: float, b: float) -> float:
     return a/b

就是那個在 OpenHands 上連 hello world 都寫不出來、40 次 error 的同一個模型。

Qwen 3.5 35B on SWE-agent:修好了但無法結束

Qwen 3.5 也找到並修好了 bug — 它正確地執行了同樣的 str_replace 修改。但它跑了 96 步,花大量時間做 git 歷史分析,始終沒有呼叫 submit。修復是正確的,模型只是不知道怎麼結束任務。


所以到底怎麼回事

OpenHands(function calling)SWE-agent(文字指令)
Gemma 4 26B❌ 40+ errors,從未完成✅ 9 步完成,產出正確 patch
Qwen 3.5 35B✅ 1 error,完成任務⚠️ 修好了但跑 96 步,沒呼叫 submit

差別在 action 格式。OpenHands 要求結構化 JSON function call,參數名稱和型別都要對。Gemma 4 在 11 個 tools 同時擠的時候就會漏參數。SWE-agent 只需要純文字 — 而 Gemma 4 寫純文字沒問題。

Gemma 4 會寫 code。它只是不會穩定地填 JSON 表格。


重要的 vLLM 設定

這幾個設定花掉了我大半個下午:

1. Chat template(最容易漏)

# 從 vLLM GitHub 下載
curl -sL https://raw.githubusercontent.com/vllm-project/vllm/main/examples/tool_chat_template_gemma4.jinja \
  -o tool_chat_template_gemma4.jinja

# Mount 進 container
-v /path/to/tool_chat_template_gemma4.jinja:/app/tool_chat_template_gemma4.jinja
--chat-template /app/tool_chat_template_gemma4.jinja

沒設的話 Gemma 4 的 tool call 會丟失參數,即使模型有正確生成。vLLM 官方 recipe 有寫但很容易忽略。

2. Qwen 3.5 的 thinking mode 必須關掉

# 錯 — 所有 output 被當 thinking token 消化
--reasoning-parser qwen3 --tool-call-parser qwen3_xml

# 對 — tool calling 正常
--tool-call-parser qwen3_xml
# (不要加 --reasoning-parser)

3. Gemma 4 在 Ollama 上壞的

Gemma 4 E2B、E4B、26B 在 Ollama 上的 tool call 全部回傳空的(已知 bug)。用 vLLM + --tool-call-parser gemma4


收穫

花最多時間的地方

在 OpenHands 上 debug Gemma 4 的 tool calling。測了四種 --tool-call-parser、加了官方 chat template、確認 parser 程式碼包含 PR #38847 的修復、在每個層級跑 curl 測試。curl 測試全部通過 — 11 tools、8,892 字 system prompt、參數完整。問題只在 OpenHands 的多輪對話裡出現。

早知道一開始就用 SWE-agent。

可轉移的診斷方法

當模型「不會 tool calling」的時候,在下結論之前先在三個層級測試:

  1. 單一 API call(curl + 2 tools)— 測基本格式
  2. 完整 schema(curl + 全部 tools + system prompt)— 測規模
  3. 框架整合(實際 agent loop)— 測多輪互動

如果 1-2 通過但 3 失敗,問題在框架不在模型。換框架比 debug function calling 相容性快。

以後會記得的事

下次本地模型在某個 agent 框架上看起來壞掉,我會先換框架再 debug 模型。這次能省四個小時。


怎麼重現

  1. vLLM 跑 Gemma 4:vllm/vllm-openai:gemma4-cu130 image(不要用 latest — 缺 Gemma 4 的 transformers 支援)
  2. 下載 chat template: curl -sL https://raw.githubusercontent.com/vllm-project/vllm/main/examples/tool_chat_template_gemma4.jinja
  3. 安裝 SWE-agent: uv python install 3.12 && git clone SWE-agent && uv pip install -e .
  4. 執行: sweagent run --agent.model.name openai/gemma-4-26b --agent.model.api_base http://<your-gx10-ip>:8000/v1 --agent.model.api_key dummy --agent.model.per_instance_cost_limit 0
  5. Qwen 3.5 的話: 拿掉 --reasoning-parser qwen3,用 --tool-call-parser qwen3_xml

這是「DGX Spark」系列的第十五篇。

常見問題

可以用本地開源模型跑 SWE-Bench 嗎?不用 Claude 或 GPT?
整條路是通的。我們用 SWE-agent + Gemma 4 26B 在 DGX Spark 上 9 步修好了一個測試 bug,不花 API 費。但這是可行性測試(簡單的少冒號 bug),還沒跑完整的 SWE-Bench Lite 300 題。完整的 resolve rate 數字還在規劃中。
SWE-Bench 該用 Gemma 4 還是 Qwen 3.5?
看框架。在 SWE-agent(文字指令格式)上,Gemma 4 26B 用 9 步解完並提交 patch。Qwen 3.5 35B 也修好了 bug 但跑了 96 步而且沒 submit。在 OpenHands(function calling 格式)上,Qwen 3.5 能用(1 個 error)但 Gemma 4 產生 40+ 個 error。選跟你框架 action 格式合的模型。
為什麼 Gemma 4 在 OpenHands 上失敗但在 SWE-agent 上成功?
OpenHands 用 OpenAI 格式的 function calling(結構化 JSON tool calls)。Gemma 4 在 11 個同時的 tools 下 function calling 不穩定 — 會漏掉必要參數。SWE-agent 用文字格式的 action(純文字指令由框架解析),Gemma 4 處理得很好。模型的 coding 能力沒問題,壞掉的是 function calling 格式。
vLLM 跑 Gemma 4 tool calling 需要什麼設定?
三個關鍵設定:--enable-auto-tool-choice、--tool-call-parser gemma4、以及 --chat-template tool_chat_template_gemma4.jinja(從 vLLM GitHub 下載)。Chat template 最容易漏 — 沒設的話 Gemma 4 的 tool call 會丟失參數,即使模型有正確生成。