Skip to content

Add Tool Calling and Reasoning Token Metadata to genai_config.json with Fallback Map#2215

Open
sayanshaw24 wants to merge 4 commits into
mainfrom
sayanshaw/tool-tags
Open

Add Tool Calling and Reasoning Token Metadata to genai_config.json with Fallback Map#2215
sayanshaw24 wants to merge 4 commits into
mainfrom
sayanshaw/tool-tags

Conversation

@sayanshaw24

@sayanshaw24 sayanshaw24 commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Add tool calling and reasoning generation tags to genai_config.json

Summary

Adds support for reading tool call start/end tokens and reasoning start/end tokens from genai_config.json, with a fallback map by model.type for backward compatibility with older model files.

This enables downstream consumers (Foundry Local C++ SDK) to get these tokens from GenAI's model API instead of relying on catalog metadata — required for the Catalog v2 migration where toolCallStart/toolCallEnd/reasoningStart/reasoningEnd tags will no longer be available.

Changes

Config parsing (config.h / config.cpp)

  • New Config::ToolCalling struct with tool_call_start_token and tool_call_end_token
  • New Config::Reasoning struct with reasoning_start_token and reasoning_end_token
  • SAX parser elements (ToolCalling_Element, Reasoning_Element) wired into Root_Element

Model API (models/model.h / models/model.cpp)

  • Model::GetGenerationTag(tag_name) — single generic method that returns the value for a given tag key
  • Static fallback map keyed by model.type for models without the new config sections:
    • qwen2/qwen3/phi3<tool_call> / </tool_call>
    • gptoss<|start|> / <|call|>
    • qwen3<think> / </think> (reasoning)

Public C API (ort_genai_c.h / ort_genai_c.cpp)

  • OgaModelGetGenerationTag(model, tag_name, &out) — single generic API accepting tag name as string key

Supported tag names:

  • "tool_call_start", "tool_call_end"
  • "reasoning_start", "reasoning_end"
  • Extensible for future tags (e.g. Harmony channel/message tokens)

C++ wrapper (ort_genai.h)

  • OgaModel::GetGenerationTag(tag_name) method

Tests (test/c_api_tests.cpp)

  • GenerationTags_Fallback — verifies gpt2 model (not in fallback map) returns empty strings
  • GenerationTags_FromConfig — creates a temp model dir with tool_calling/reasoning sections in genai_config.json and verifies correct parsing

genai_config.json format

{
  "model": { "type": "qwen2", ... },
  "tool_calling": {
    "tool_call_start_token": "<tool_call>",
    "tool_call_end_token": "</tool_call>"
  },
  "reasoning": {
    "reasoning_start_token": "<think>",
    "reasoning_end_token": "</think>"
  }
}

Both sections are optional. If absent, the fallback map is used. If the model type isn't in the fallback map either, empty strings are returned (meaning the model doesn't support tool calling / reasoning).

Motivation

The Foundry Local C++ SDK (sdk_v2) currently reads tool call and reasoning tokens from Azure catalog metadata (ModelInfo.string_properties). With Catalog v2, these fields are being removed. This PR makes the tokens available directly from GenAI's model object, sourced from the model-shipped genai_config.json.

Priority order in FL SDK will be:

  1. GenAI model API (this PR)
  2. Catalog metadata (existing, backward compat — to be deprecated)

API Design Note

The API uses a single generic OgaModelGetGenerationTag(model, tag_name, &out) rather than separate functions per token. Rationale:

  • Extensibility: Models like GPT-OSS/Harmony require additional tags beyond start/end (e.g. <|channel|>, <|message|>, <|constrain|>). A generic API avoids adding new functions for each.
  • Consistency: Follows the pattern of key-value attribute access rather than an ever-growing function surface.
  • Future-proofing: New model families can define arbitrary generation tags without requiring GenAI API changes.

Related PRs

  • Foundry-Local: Will update BuildToolCallContext() in chat_session.cc to read from GenAI API

@sayanshaw24 sayanshaw24 marked this pull request as ready for review June 26, 2026 22:23
@sayanshaw24 sayanshaw24 requested a review from a team as a code owner June 26, 2026 22:23
Copilot AI review requested due to automatic review settings June 26, 2026 22:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for exposing model “generation tags” (tool-calling and reasoning start/end tokens) via genai_config.json, with a model-type-based fallback for older model artifacts. It extends the internal config/model layers and surfaces a generic tag getter through the public C API and C++ wrapper, plus adds C API tests to validate both fallback and explicit config parsing.

Changes:

  • Extend config schema/parsing with optional tool_calling and reasoning sections (Config::ToolCalling, Config::Reasoning).
  • Add Model::GetTag(tag_name) with a static fallback map keyed by model.type.
  • Expose tag lookup via OgaModelGetTag (C API) and OgaModel::GetTag (C++ wrapper), and add tests covering fallback and config-driven values.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/c_api_tests.cpp Adds tests for tag fallback behavior and tag parsing from a temp genai_config.json.
src/ort_genai.h Adds C++ wrapper OgaModel::GetTag(...) calling the new C API.
src/ort_genai_c.h Adds public C API declaration/docs for OgaModelGetTag(...).
src/ort_genai_c.cpp Implements OgaModelGetTag(...) by allocating a returned string from Model::GetTag.
src/models/model.h Declares internal Model::GetTag(...) accessor (config + fallback).
src/models/model.cpp Implements fallback map + config accessors for tag lookup.
src/config.h Adds Config::ToolCalling and Config::Reasoning structs to the config model.
src/config.cpp Wires new SAX elements (ToolCalling_Element, Reasoning_Element) into root parsing.

Comment thread test/c_api_tests.cpp
Comment on lines +1838 to +1839
auto temp_dir = std::filesystem::temp_directory_path() / "oga_test_tool_tags";
std::filesystem::create_directories(temp_dir);
Comment thread src/ort_genai_c.h
Comment on lines +410 to +414
* \brief Returns a tag value for this model by name.
*
* Known tag names: "tool_call_start", "tool_call_end", "reasoning_start", "reasoning_end".
* Returns an empty string if the model doesn't define the requested tag.
*
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.

2 participants