mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-09-05 23:56:37 +08:00
Merge pull request #286 from 4Crusaders:fix/gemini-structured-output-tools-conflict
fix: 修复Gemini模型不支持同时使用tools和结构化输出的问题
This commit is contained in:
@@ -119,6 +119,14 @@ def _build_tools(model: str, payload: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|||||||
record[k] = v
|
record[k] = v
|
||||||
return record
|
return record
|
||||||
|
|
||||||
|
def _is_structured_output_request(payload: Dict[str, Any]) -> bool:
|
||||||
|
"""检查请求是否要求结构化JSON输出"""
|
||||||
|
try:
|
||||||
|
generation_config = payload.get("generationConfig", {})
|
||||||
|
return generation_config.get("responseMimeType") == "application/json"
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
return False
|
||||||
|
|
||||||
tool = dict()
|
tool = dict()
|
||||||
if payload and isinstance(payload, dict) and "tools" in payload:
|
if payload and isinstance(payload, dict) and "tools" in payload:
|
||||||
if payload.get("tools") and isinstance(payload.get("tools"), dict):
|
if payload.get("tools") and isinstance(payload.get("tools"), dict):
|
||||||
@@ -127,19 +135,25 @@ def _build_tools(model: str, payload: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|||||||
if items and isinstance(items, list):
|
if items and isinstance(items, list):
|
||||||
tool.update(_merge_tools(items))
|
tool.update(_merge_tools(items))
|
||||||
|
|
||||||
if (
|
# "Tool use with a response mime type: 'application/json' is unsupported"
|
||||||
settings.TOOLS_CODE_EXECUTION_ENABLED
|
# Gemini API限制:不支持同时使用tools和结构化输出(response_mime_type='application/json')
|
||||||
and not (model.endswith("-search") or "-thinking" in model)
|
# 当请求指定了JSON响应格式时,跳过所有工具的添加以避免API错误
|
||||||
and not _has_image_parts(payload.get("contents", []))
|
has_structured_output = _is_structured_output_request(payload)
|
||||||
):
|
if not has_structured_output:
|
||||||
tool["codeExecution"] = {}
|
if (
|
||||||
if model.endswith("-search"):
|
settings.TOOLS_CODE_EXECUTION_ENABLED
|
||||||
tool["googleSearch"] = {}
|
and not (model.endswith("-search") or "-thinking" in model)
|
||||||
|
and not _has_image_parts(payload.get("contents", []))
|
||||||
real_model = _get_real_model(model)
|
):
|
||||||
if real_model in settings.URL_CONTEXT_MODELS and settings.URL_CONTEXT_ENABLED:
|
tool["codeExecution"] = {}
|
||||||
tool["urlContext"] = {}
|
|
||||||
|
if model.endswith("-search"):
|
||||||
|
tool["googleSearch"] = {}
|
||||||
|
|
||||||
|
real_model = _get_real_model(model)
|
||||||
|
if real_model in settings.URL_CONTEXT_MODELS and settings.URL_CONTEXT_ENABLED:
|
||||||
|
tool["urlContext"] = {}
|
||||||
|
|
||||||
# 解决 "Tool use with function calling is unsupported" 问题
|
# 解决 "Tool use with function calling is unsupported" 问题
|
||||||
if tool.get("functionDeclarations") or _has_function_call(payload.get("contents", [])):
|
if tool.get("functionDeclarations") or _has_function_call(payload.get("contents", [])):
|
||||||
tool.pop("googleSearch", None)
|
tool.pop("googleSearch", None)
|
||||||
|
|||||||
@@ -97,6 +97,14 @@ def _build_tools(model: str, payload: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|||||||
record[k] = v
|
record[k] = v
|
||||||
return record
|
return record
|
||||||
|
|
||||||
|
def _is_structured_output_request(payload: Dict[str, Any]) -> bool:
|
||||||
|
"""检查请求是否要求结构化JSON输出"""
|
||||||
|
try:
|
||||||
|
generation_config = payload.get("generationConfig", {})
|
||||||
|
return generation_config.get("responseMimeType") == "application/json"
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
return False
|
||||||
|
|
||||||
tool = dict()
|
tool = dict()
|
||||||
if payload and isinstance(payload, dict) and "tools" in payload:
|
if payload and isinstance(payload, dict) and "tools" in payload:
|
||||||
if payload.get("tools") and isinstance(payload.get("tools"), dict):
|
if payload.get("tools") and isinstance(payload.get("tools"), dict):
|
||||||
@@ -105,18 +113,24 @@ def _build_tools(model: str, payload: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|||||||
if items and isinstance(items, list):
|
if items and isinstance(items, list):
|
||||||
tool.update(_merge_tools(items))
|
tool.update(_merge_tools(items))
|
||||||
|
|
||||||
if (
|
# "Tool use with a response mime type: 'application/json' is unsupported"
|
||||||
settings.TOOLS_CODE_EXECUTION_ENABLED
|
# Gemini API限制:不支持同时使用tools和结构化输出(response_mime_type='application/json')
|
||||||
and not (model.endswith("-search") or "-thinking" in model)
|
# 当请求指定了JSON响应格式时,跳过所有工具的添加以避免API错误
|
||||||
and not _has_image_parts(payload.get("contents", []))
|
has_structured_output = _is_structured_output_request(payload)
|
||||||
):
|
if not has_structured_output:
|
||||||
tool["codeExecution"] = {}
|
if (
|
||||||
if model.endswith("-search"):
|
settings.TOOLS_CODE_EXECUTION_ENABLED
|
||||||
tool["googleSearch"] = {}
|
and not (model.endswith("-search") or "-thinking" in model)
|
||||||
|
and not _has_image_parts(payload.get("contents", []))
|
||||||
real_model = _get_real_model(model)
|
):
|
||||||
if real_model in settings.URL_CONTEXT_MODELS and settings.URL_CONTEXT_ENABLED:
|
tool["codeExecution"] = {}
|
||||||
tool["urlContext"] = {}
|
|
||||||
|
if model.endswith("-search"):
|
||||||
|
tool["googleSearch"] = {}
|
||||||
|
|
||||||
|
real_model = _get_real_model(model)
|
||||||
|
if real_model in settings.URL_CONTEXT_MODELS and settings.URL_CONTEXT_ENABLED:
|
||||||
|
tool["urlContext"] = {}
|
||||||
|
|
||||||
# 解决 "Tool use with function calling is unsupported" 问题
|
# 解决 "Tool use with function calling is unsupported" 问题
|
||||||
if tool.get("functionDeclarations") or _has_function_call(payload.get("contents", [])):
|
if tool.get("functionDeclarations") or _has_function_call(payload.get("contents", [])):
|
||||||
|
|||||||
Reference in New Issue
Block a user