Skip to content

W2b: HF-side chat-template auto-detection (#38) + registerable parser strategies (#40) - #297

Merged
michalharakal merged 3 commits into
feat/tool-calling-w2afrom
feat/tool-calling-w2b
Aug 11, 2026
Merged

michalharakal merged 3 commits into
feat/tool-calling-w2afrom
feat/tool-calling-w2b

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Summary

W2b — second of three stacked PRs for the tool-calling epic (#35). Stacked on #296 (W2a) — review only the last commit here until #296 merges.

#38 — best-effort auto-detection from HF-side configs

The resolver-side auto-detection (metadata → provider, explicit override wins) already shipped; what was missing was the tokenizer/config-side inspection called out in the issue. Now:

  • ModelMetadataExtraction.fromHuggingFaceConfig(tokenizerConfigJson, chatTemplateJson, modelConfigJson) parses:
    • tokenizer_config.jsonchat_template as a plain string or HF's list-of-named-templates form ("default" entry wins, else first), plus additional_special_tokens (strings or {"content": ...} objects) for tool-hint scanning
    • chat_template.json — used when tokenizer_config has no template
    • config.jsonmodel_type → architecture → family
  • kllama Main.kt now peeks these sidecar files for safetensors checkpoints (peekHfMetadata) and feeds the result into the exact resolver path GGUF metadata already used. --template=... still wins (resolver contract, unchanged).
  • All parsing is best-effort: malformed/missing JSON degrades to partial metadata, never throws.

#40 — registerable parser strategies

ToolCallParserStrategy + parseWith existed; clean registration into the default chain did not. Now:

  • ToolCallParser.registerStrategy(strategy) — prepended (outranks built-ins), replace-by-formatName, mirroring ToolCallingSupportResolver.register() semantics exactly
  • ToolCallParser.unregisterStrategy(formatName) — removes runtime registrations only; built-ins (hermes, llama3-function-tag, llama3-json) are permanent
  • ToolCallParser.registeredFormats() — chain snapshot in resolution order

#39 — no code needed

GenericToolCallingSupport + resolveOrFallback + GENERIC-mode diagnostics already exist (32b3b9e); verified, will be close-commented on the issue.

Verification

  • :llm-agent:jvmTest: 206 tests (17 new), 0 failures — HF extraction (string/list templates, precedence, malformed JSON, end-to-end resolver checks for qwen2/llama3 sidecars) + parser registration (ordering, replacement, unregistration, built-in immutability)
  • :llm-agent:apiCheck green, apiDump refreshed
  • :llm-runtime:kllama:compileKotlinJvm green

Refs #38 #39 #40 #35

🤖 Generated with Claude Code

michalharakal and others added 2 commits August 11, 2026 17:35
…rser strategies

Completes the two genuinely-missing pieces of the detection/parsing layer
(the resolver-side auto-detection with explicit-override-wins already
shipped; see the #35 reconciliation):

- #38: ModelMetadataExtraction.fromHuggingFaceConfig() parses
  tokenizer_config.json (chat_template as string or HF's named-template
  list, additional_special_tokens for hints), chat_template.json, and
  config.json (model_type -> family). kllama Main.kt now peeks these
  sidecar files for safetensors checkpoints and feeds the result into
  the same resolver path GGUF already used — auto-detection now works
  on the HF path too, and --template still wins. Malformed/missing JSON
  degrades to partial metadata, never throws.
- #40: ToolCallParser.registerStrategy()/unregisterStrategy()/
  registeredFormats() — family-specific parser strategies can be
  registered into the default chain at runtime, prepended so they
  outrank the built-ins, replace-by-formatName semantics mirroring
  ToolCallingSupportResolver.register(). Built-ins are not removable.
- #39 needed no code: GenericToolCallingSupport + resolveOrFallback +
  GENERIC-mode logging already exist.

17 new unit tests (HF extraction incl. resolver end-to-end for qwen2/
llama3 safetensors sidecars; parser registration ordering/replacement/
unregistration). apiDump refreshed; apiCheck green.

Part of #35; W2b, stacked on #296.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tests, Qwen real-GGUF validation, native-vs-generic docs

Final PR of the W2 stack (#35 epic):

- #41: AgentCli (chat/agent modes) now prints the same provider/mode/
  reason resolution diagnostics ToolCallingDemo already printed, so
  native-vs-generic selection is visible in every CLI mode.
- #42: ResolutionDiagnosticsTest pins resolveWithDiagnostics — explicit
  override reason, auto-detect reason, GENERIC fallback mode/reason, and
  extraction→diagnostics carry-through. (GGUF/HF extraction tests landed
  in the earlier PRs of this stack.)
- #43: QwenToolCallSmokeTest, env-gated on QWEN_MODEL_PATH. Two stages:
  (1) metadata extraction + auto-resolution against the real file —
  header-only, runs in seconds; verified PASSING against
  Qwen2.5-0.5B-Instruct-F16.gguf (family=qwen, arch=qwen2, hints
  [<tool_call>, <tool_response>, <|im_start|>] → provider qwen, NATIVE,
  no explicit family). (2) full agent-loop round-trip over the real
  checkpoint via the same DSL path the CLI uses — currently fails for a
  reason outside this architecture: the DSL Qwen runtime emits
  degenerate text on real checkpoints (tracked as #118); documented in
  the test so it becomes the round-trip pin once #118 lands.
- #44: README gains a "Tool calling: native vs. generic support"
  section with resolution-order docs and a family/provider/mode/format/
  detection compatibility matrix; CHANGELOG entry for the W2 stack.

Verification: llm-agent jvmTest 210 green; kllama jvmTest green
(gated tests skip cleanly without env vars); apiCheck green on
llm-core/llm-agent/kllama (no public API changes in this PR);
gemma-iree jvmTest green (functiongemma provider registration).

Note: :llm-apps:kllama-cli / :llm-apps:skainet-cli fail dependency
resolution on develop (empty engine version on app classpaths),
pre-existing and unrelated — demo validation therefore ran through the
env-gated smoke tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
W2c: AgentCli diagnostics (#41), detection tests (#42), Qwen real-GGUF validation (#43), native-vs-generic docs (#44)
@michalharakal
michalharakal merged commit a48ccd3 into feat/tool-calling-w2a Aug 11, 2026
2 checks passed
@michalharakal
michalharakal deleted the feat/tool-calling-w2b branch August 11, 2026 20:33
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