Add chat template kwargs to C API - #1102
Conversation
Preserve the existing API while allowing typed JSON context values for model-specific chat templates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Run the repository C API build and C++ tests on Jenny's fork while upstream Azure Pipelines await maintainer authorization. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400
There was a problem hiding this comment.
Pull request overview
This PR extends the tokenizer C API to accept additional, typed JSON context values (“template kwargs”) when applying chat templates, while preserving the legacy OrtxApplyChatTemplate entry point.
Changes:
- Adds a new C API function
OrtxApplyChatTemplateWithOptionsthat acceptstemplate_kwargsas a JSON object string. - Updates chat template rendering to merge
template_kwargsinto the Minja context while preventing overrides of core context keys (messages,tools,add_generation_prompt). - Adds new unit tests covering typed kwargs, core-context override prevention, and invalid kwargs handling.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/pp_api_test/test_tokenizer_chat.cc | Adds tests for typed template kwargs behavior, override-prevention, and invalid JSON errors. |
| shared/api/tokenizer_impl.h | Extends TokenizerImpl::ApplyChatTemplate signature to accept template_kwargs. |
| shared/api/chat_template.cc | Implements parsing/merging of template_kwargs into the template context with core-key precedence rules. |
| shared/api/c_api_tokenizer.cc | Introduces OrtxApplyChatTemplateWithOptions and routes legacy API through it. |
| include/ortx_tokenizer.h | Exposes the new API in the public header with documentation. |
Suppressed comments (1)
shared/api/c_api_tokenizer.cc:486
- OrtxApplyChatTemplateWithOptions can dereference a null tokenizer when tokenizer == nullptr but template_str != nullptr. The current guard only rejects the case where both tokenizer and template_str are null, but token_ptr is always derived from tokenizer, so this can crash instead of returning kOrtxErrorInvalidArgument.
if (tokenizer == nullptr && template_str == nullptr) {
ReturnableStatus::last_error_message_ = "both tokenizer and template_str are null, no template to apply";
return kOrtxErrorInvalidArgument;
}
if (input == nullptr || output == nullptr) {
ReturnableStatus::last_error_message_ = "Invalid argument";
return kOrtxErrorInvalidArgument;
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Exercise the same typed false value without relying on the unsupported is false predicate in an explicit template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400
The repository C API build and full C++ test suite passed in fork run 32069739093. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400
Return an invalid-argument error instead of dereferencing a null tokenizer, with a focused regression test and temporary fork validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400
Keep the public contract strict: callers must pass a JSON object or null, never an empty string. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400
The strict kwargs validation and null-tokenizer regression pass the full C API C++ suite in run 32070849855. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400
|
Quick stack update: this leaf PR is ready for maintainer review; CLA and validation are green. The dependent drafts are microsoft/onnxruntime-genai#2421 and microsoft/foundry-local#1009. Full stacked validation is green, including the Foundry rebase onto the shared @microsoft/onnxruntime-extensions, could someone review this and run |
Sayan Shaw (sayanshaw24)
left a comment
There was a problem hiding this comment.
looks great, thanks for adding this!
## Summary - add backward-compatible C and C++ tokenizer APIs for typed chat-template kwargs - preserve the existing `ApplyChatTemplate` behavior by delegating with null kwargs - pass model-specific context such as `enable_thinking` and `reasoning_effort` to ONNX Runtime Extensions - add focused C API coverage for typed values and legacy equivalence ## Dependency This PR depends on microsoft/onnxruntime-extensions#1102. The production dependency pin is intentionally unchanged; this PR should remain draft until #1102 merges and ORT GenAI updates its normal Extensions pin. ## Motivation Foundry Local issue microsoft/foundry-local#808 needs a request path for: ```json {"chat_template_kwargs":{"enable_thinking":false}} ``` Qwen 3 defaults to reasoning and can exhaust bounded output budgets before producing an answer or tool call. Qwen 2.5 has no equivalent reasoning-template branch. ## Validation The code was stacked against the tested #1102 head only inside a disposable fork workflow. The native build compiled and `CAPITests.ChatTemplate` passed: https://github.com/jennyf19/onnxruntime-genai/actions/runs/32071927312 No personal-fork dependency appears in this PR's production diff. --------- Co-authored-by: Jenny Ferries <jenny.ferries@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a9f5bae1-1b88-4311-8fac-6224769e0400 Copilot-Session: 023653cc-8b13-428d-84dc-92c3fa96cabb
Preserve the existing API while allowing typed JSON context values for model-specific chat templates.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com