Skip to content

FunctionGemmaToolCallingSupport: compact functional tokens on the llm-agent provider architecture (#35, #36) - #292

Merged
michalharakal merged 2 commits into
developfrom
feat/functiongemma-toolcalling-support
Aug 11, 2026
Merged

michalharakal merged 2 commits into
developfrom
feat/functiongemma-toolcalling-support

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

What

First concrete slice of #35/#36: the compact <tool_N>(k="v")<end> functional-token format (FunctionGemma v10, parsed by CompactCodec) is now wired into llm-agent's ToolCallingSupport / ToolCallParserStrategy / ChatTemplate architecture, following the SmolLM provider prior art from #272.

Placement: gemma-iree, not llm-agent

Gemma4ToolCallingSupport and friends live in :llm-agent, but llm-agent publishes js/wasm/android/ios targets that :llm-runtime:gemma-iree does not have — so llm-agent cannot depend on gemma-iree. The provider therefore lives in gemma-iree commonMain (which gains an api(":llm-agent") dependency) and is opted into at runtime:

ToolCallingSupportResolver.register(FunctionGemmaToolCallingSupport())

register prepends, so the provider outranks the generic GemmaToolCallingSupport that would otherwise claim FunctionGemma's plain gemma3 arch and hand out the JSON functionCall template the fine-tune was never trained on.

Changes

  • CompactToolCodecCompactCodec's TOKEN_TO_NAME is now a constructor parameter (stock v10 six-tool vocabulary as default): a 7th tool needs no library edit, e.g. CompactToolCodec(DEFAULT_TOKEN_TO_NAME + ("6" to "open_gripper")). The CompactCodec object stays, delegating, so existing call sites are source-compatible.
  • FunctionGemmaToolCallParserStrategy — bridges gemma-iree ToolCall(tool, args) to llm-agent ToolCall(id, name, JsonObject); formatName = "functiongemma"; <tool_none> stays an explicit no-op.
  • FunctionGemmaChatTemplate — reproduces byte-for-byte the prompt FunctionGemma.call() used to hardcode (<start_of_turn>user\n…<end_of_turn>\n<start_of_turn>model\n; note: no newline before <end_of_turn>, unlike GemmaChatTemplate). tools are deliberately ignored — the vocabulary is baked into the checkpoint as special tokens.
  • FunctionGemmaToolCallingSupportfamily = "functiongemma", detection via family or <tool_*> tokenizer hints (arch is NOT a discriminator), ToolCallingMode.NATIVE.
  • FunctionGemma.call() refactored onto the template (behavior unchanged).
  • Hygiene (separate commit)llm-inference/gemma/README.md coordinates 0.35.0 → 0.39.0; new env-first FunctionGemmaFixture in llm-inference/gemma replaces seven hardcoded absolute GGUF paths (GEMMA_GGUF override, documented dev-box fallback).

Tests

  • New commonTest suite mirrors CompactCodecTest through the strategy (jvm + linuxX64 both green), plus custom-tool-map, unique-call-id, exact-prompt, multi-turn, and supports() discrimination tests. CompactCodecTest untouched — proves object-API compat.
  • FunctionGemmaEagerTest against the real Q5_K_M checkpoint: passed, not skipped (tests=1 skipped=0 failures=0), emitting <tool_0>(state="on")<end>set_lights/state=on through the new template.
  • RealGemmaLoadTest (-PincludeIntegration) green through the new fixture.
  • ./gradlew apiCheck green (no public-API dump changes in validated modules; kgemma's surface unchanged).

🤖 Generated with Claude Code

michalharakal and others added 2 commits August 11, 2026 09:06
…l tokens on the llm-agent provider architecture (#35, #36)

The compact <tool_N>(k="v")<end> format had no bridge into llm-agent's
ToolCallingSupport / ToolCallParserStrategy / ChatTemplate stack. Add one,
living in gemma-iree because the dependency direction demands it: llm-agent
publishes js/wasm/android/ios targets gemma-iree does not have, so the
provider is registered at runtime via ToolCallingSupportResolver.register()
(prepended, so it outranks the generic Gemma provider that would otherwise
claim FunctionGemma's plain gemma3 arch).

- CompactToolCodec: CompactCodec's TOKEN_TO_NAME is now a constructor param
  (stock v10 six-tool map as default) — a 7th tool needs no library edit.
  The CompactCodec object stays, delegating, for source compat.
- FunctionGemmaToolCallParserStrategy: gemma-iree ToolCall -> llm-agent
  ToolCall (flat string args as JsonPrimitives), formatName "functiongemma".
- FunctionGemmaChatTemplate: reproduces byte-for-byte the prompt
  FunctionGemma.call() used to hardcode (no newline before <end_of_turn>;
  tools deliberately ignored — the vocabulary is baked into the checkpoint).
- FunctionGemma.call() now applies the template; FunctionGemmaEagerTest
  verified green against the real Q5_K_M checkpoint (set_lights/state=on).
- commonTest mirrors CompactCodecTest through the strategy + custom-map and
  exact-prompt tests. Prior art: feature/smoll's SmolLM provider (#272).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…real-model tests

- llm-inference/gemma/README.md: stale 0.35.0 coordinates -> 0.39.0.
- New sk.ainet.models.gemma.FunctionGemmaFixture (env-first GEMMA_GGUF with
  the documented dev-box path as fallback), mirroring kgemma's fixture; the
  seven real-GGUF tests now share it instead of seven hardcoded absolute
  paths. RealGemmaLoadTest verified green through the fixture.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant