[LiteLLM] role='tool_responses' for Gemma 4 breaks tool calling on Vertex AI Model Garden MaaS (400 INVALID_ARGUMENT)
維護者通常 4 天內回覆
評估
研究方向
問題出在 google/adk/models/lite_llm.py 中的 _is_gemma4_model 以及 _STANDARD_TOOL_ROLE_PROVIDERS 集合,它決定工具結果要使用 role="tool" 還是 role="tool_responses"。請先閱讀 vertex_ai/ 模型字串如何推導出實際生效的提供者,然後檢查涵蓋 openai、azure 和 lm_studio 排除項的現有測試。完成標準是:vertex_ai 上的 Gemma 4 發送 role="tool",ollama 和 hosted_vllm 保持 tool_responses,並且有一個測試涵蓋 vertex_ai 的情況。
由索引模型根據 Issue 內容生成。
描述
🔴 Required Information
Describe the Bug:
_is_gemma4_model in google/adk/models/lite_llm.py causes ADK to emit tool results with role="tool_responses" whenever the model string matches gemma-?4, except when the effective provider is in _STANDARD_TOOL_ROLE_PROVIDERS ({"openai", "azure", "lm_studio"}, added in 7d190e6e for #6482).
When calling Gemma 4 on Vertex AI Model Garden MaaS via LiteLLM (model="vertex_ai/google/gemma-4-26b-a4b-it-maas"), LiteLLM routes the request to Vertex AI's OpenAI-compatible chat-completions endpoint (.../endpoints/openapi/chat/completions), which strictly validates OpenAI message roles. Because "vertex_ai" is not in _STANDARD_TOOL_ROLE_PROVIDERS, ADK sends role="tool_responses" and Vertex AI rejects every tool-result turn with HTTP 400 INVALID_ARGUMENT:
Unrecognized 'role' field for a message; found: 'tool_responses'.
Steps to Reproduce:
- Configure ADC with a GCP project that has Vertex AI API enabled.
- Instantiate
LiteLlm(model="vertex_ai/google/gemma-4-26b-a4b-it-maas", vertex_project="<gcp-project>", vertex_location="global"). - Send a tool-calling round trip (
userprompt ->modelFunctionCall->userFunctionResponse). - Observe
litellm.BadRequestError(400 INVALID_ARGUMENT).
Expected Behavior:
ADK sends tool results with role="tool" for vertex_ai Gemma 4 models, and Vertex AI returns a 200 OK completion grounded in the tool result.
Observed Behavior:
ADK sends role="tool_responses" and Vertex AI returns:
{
"error": {
"code": 400,
"message": "Unrecognized 'role' field for a message; found: 'tool_responses'.",
"status": "INVALID_ARGUMENT"
}
}
Environment Details:
- ADK Library Version (
pip show google-adk):2.13.0andmain(76627586) - Desktop OS: Linux
- Python Version (
python -V): Python 3.12
Model Information:
- Are you using LiteLLM: Yes
- Which model is being used:
vertex_ai/google/gemma-4-26b-a4b-it-maas
🟡 Optional Information
Regression:
Introduced when gemma-?4 matching was broadened in 49301558 (#6334 / #6340); 7d190e6e (#6482 / #7042) excluded openai, azure, and lm_studio, but did not include vertex_ai.
Logs:
roles sent: ['user', 'assistant', 'tool_responses']
EXCEPTION: BadRequestError litellm.BadRequestError: Vertex_aiException BadRequestError - [{
"error": {
"code": 400,
"message": "Unrecognized 'role' field for a message; found: 'tool_responses'.",
"status": "INVALID_ARGUMENT"
}
}]
Additional Context:
We also verified a self-deployed Vertex AI Model Garden Gemma 4 vLLM endpoint (google/gemma4@gemma-4-e2b-it via vertex_ai/gemma/... :predict with @requestFormat="chatCompletions" and dedicated /chat/completions): it accepts role="tool" with 200 OK and produces the expected final answer without re-calling the tool. Adding "vertex_ai" to _STANDARD_TOOL_ROLE_PROVIDERS therefore fixes Vertex MaaS without regressing self-deployed Vertex Model Garden endpoints, while preserving role="tool_responses" for ollama/... and hosted_vllm/....
Minimal Reproduction Code:
import asyncio
from google.adk.models.lite_llm import LiteLlm
from google.adk.models.llm_request import LlmRequest
from google.genai import types
async def main() -> None:
model = "vertex_ai/google/gemma-4-26b-a4b-it-maas"
llm = LiteLlm(
model=model,
vertex_project="<gcp-project>",
vertex_location="global",
)
weather = types.FunctionDeclaration(
name="get_weather",
description="Returns the weather for a city.",
parameters=types.Schema(
type=types.Type.OBJECT,
properties={"city": types.Schema(type=types.Type.STRING)},
required=["city"],
),
)
req = LlmRequest(
model=model,
contents=[
types.Content(
role="user",
parts=[types.Part(text="What is the weather in Paris?")],
),
types.Content(
role="model",
parts=[
types.Part(
function_call=types.FunctionCall(
id="call_1",
name="get_weather",
args={"city": "Paris"},
)
)
],
),
types.Content(
role="user",
parts=[
types.Part(
function_response=types.FunctionResponse(
id="call_1",
name="get_weather",
response={"result": "sunny, 21 C"},
)
)
],
),
],
config=types.GenerateContentConfig(
tools=[types.Tool(function_declarations=[weather])],
max_output_tokens=64,
),
)
async for r in llm.generate_content_async(req):
print(r.finish_reason, r.content)
asyncio.run(main())
How often has this issue occurred?:
- Always (100%)
- 主要語言
- Python
- 星號
- 22.1k
- 分支
- 4.3k
- 平均合併
- 1 天 10 小時
- 30 天內合併 PR
- 5
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
google/adk-python 的其他 Issue
-
FileArtifactService changes CRLF and CR line endings in text artifacts可能已有人在做 @sanketpatil06 於 3 天前認領。 未關閉request clarification services
難度 2/5 1-3 小時 新手友好度 85/100
google/adk-python#7914 · 1 則留言 · 已指派 1 人 ·
維護者通常 4 天內回覆
-
ContainerCodeExecutor drops output files that are hard links可能已有人在做 @llalitkumarrr 於 3 天前認領。 未關閉
難度 2/5 1-3 小時 新手友好度 76/100
google/adk-python#7906 · 2 則留言 · 已指派 1 人 ·
維護者通常 4 天內回覆
-
GCS skill loaders ignore a skill.md manifest that the local and zip loaders accept可能已有人在做 @surajksharma07 於 6 天前認領。 未關閉tools
難度 2/5 1-3 小時 新手友好度 84/100
google/adk-python#7842 · 2 則留言 · 已指派 1 人 ·
維護者通常 4 天內回覆
-
RestApiTool crashes on a request body media type that has no schema可能已有人在做 @llalitkumarrr 於 6 天前認領。 未關閉
難度 2/5 1-3 小時 新手友好度 78/100
google/adk-python#7838 · 1 則留言 · 已指派 1 人 ·
維護者通常 4 天內回覆
-
LiteLlm with SSE streaming records the answer twice in gen_ai.output.messages可能已有人在做 @surajksharma07 於 14 天前認領。 未關閉models
難度 2/5 1-3 小時 新手友好度 78/100
google/adk-python#7630 · 11 則留言 · 已指派 1 人 ·
維護者通常 4 天內回覆
查看 google/adk-python 的全部 Issue
相似的 Issue
-
fuzz fuzz-unconfirmed
難度 2/5 1-3 小時 新手友好度 70/100
維護者通常 1 天內回覆
-
ready-for-agent
難度 2/5 1-3 小時 新手友好度 86/100
neilsh/stunt-reel#220 ·
維護者通常 1 天內回覆
-
[Issue]: use_fp4_cache is accepted but ignored; the launcher always writes FP8 records可能已有人在做 @0z5a 今天認領。 未關閉
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆
-
area: cli priority: p3 size: S type: bug
難度 2/5 1-3 小時 新手友好度 83/100
finos/open-resource-broker#757 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 65/100
維護者通常 6 天內回覆