Studio: heal DiffusionGemma tool calls into structured tool_calls (#6851)

* Studio: heal DiffusionGemma tool calls into structured tool_calls

* Fall back to supports_tools for backends without the passthrough capability

* Route DiffusionGemma client tools through passthrough when enable_tools is on

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Drop orphaned strip_tool_call_markup import after syncing with main

* Tighten supports_tool_passthrough comment

* Re-run CI on current main

---------

Co-authored-by: danielhanchen <unslothai@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
This commit is contained in:
oobabooga 2026-07-08 06:30:37 -03:00 committed by GitHub
parent baacbd025d
commit a113f893ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 17 additions and 10 deletions

View file

@ -67,7 +67,6 @@ from core.tool_healing import (
_strip_bracket_tag_calls,
apply_tool_strip_patterns,
strip_outside_think,
strip_tool_call_markup,
)
from utils.native_path_leases import child_env_without_native_path_secret
from utils.hf_xet_fallback import hf_hub_download_with_xet_fallback
@ -1781,6 +1780,13 @@ class LlamaCppBackend:
return False
return self._supports_tools
@property
def supports_tool_passthrough(self) -> bool:
# supports_tools is forced off for DiffusionGemma (its agentic loop drops the
# per-step canvas frames), but client passthrough skips that loop, so it uses
# the real _supports_tools.
return self._supports_tools
@property
def cache_type_kv(self) -> Optional[str]:
return self._cache_type_kv

View file

@ -6053,14 +6053,13 @@ async def openai_chat_completions(
# free-form sampling. Guided decoding does not require ``supports_tools`` --
# the grammar machinery is independent of tool-call parsing.
_has_response_format = _extract_response_format(payload) is not None
_tools_passthrough = llama_backend.supports_tools and (
(payload.tools and len(payload.tools) > 0) or _has_tool_messages
)
if (
using_gguf
and not _effective_enable_tools(payload)
and (_tools_passthrough or _has_response_format)
):
_tools_passthrough = getattr(
llama_backend, "supports_tool_passthrough", llama_backend.supports_tools
) and ((payload.tools and len(payload.tools) > 0) or _has_tool_messages)
# DiffusionGemma keeps supports_tools off, so the server-side tool loop can't
# claim the request; fall through to client passthrough, matching /v1/messages.
_server_tool_loop = _effective_enable_tools(payload) and llama_backend.supports_tools
if using_gguf and not _server_tool_loop and (_tools_passthrough or _has_response_format):
if _wants_multiple_choices(payload):
raise _reject_unsupported_n("GGUF tool or response_format passthrough")
if payload.audio_base64:
@ -10222,7 +10221,9 @@ async def anthropic_messages(
and not _has_image
)
client_tools = (
not server_tools and len(openai_client_tools) > 0 and llama_backend.supports_tools
not server_tools
and len(openai_client_tools) > 0
and getattr(llama_backend, "supports_tool_passthrough", llama_backend.supports_tools)
)
# Anthropic tool_choice.disable_parallel_tool_use caps the response to a