Skip to content

Auto parser detect / auto input-workaround detection / --parser none#4312

Open
dkalinowski wants to merge 59 commits into
mainfrom
detect
Open

Auto parser detect / auto input-workaround detection / --parser none#4312
dkalinowski wants to merge 59 commits into
mainfrom
detect

Conversation

@dkalinowski

@dkalinowski dkalinowski commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator
  • switch VLM pipelines to JINJA by default, making it aligned with LLM pipelines (jinja has broader support chat template application)

@dkalinowski dkalinowski requested a review from mzegla June 22, 2026 13:41
Base automatically changed from vlm-python-jinja to main June 23, 2026 10:07
Copilot AI review requested due to automatic review settings June 23, 2026 11:27
@dkalinowski dkalinowski added the WIP Do not merge until resolved label Jun 23, 2026
@dkalinowski dkalinowski changed the title [integration-branch] Auto parser detect / auto input-workaround detection Auto parser detect / auto input-workaround detection Jun 23, 2026

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

Adds chat-template capability detection plus request “input workarounds” so OVMS can (a) auto-pick tool/reasoning parsers from the template and (b) normalize incoming requests to match template expectations (e.g., Gemma4 object arguments, Llama3 non-null content) across both Python/Jinja and GenAI C++ paths.

Changes:

  • Introduces ChatTemplateAnalyzer + ChatTemplateCaps and wires analysis into servable initialization for auto-detecting model family/tool parser/reasoning parser.
  • Adds input_workarounds module and applies it before chat template rendering (JSON for Jinja; ChatHistory for GenAI).
  • Adds unit tests + Bazel targets for analyzer/workaround behavior, and updates example templates/docs.

Reviewed changes

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

Show a summary per file
File Description
src/test/llm/input_workarounds_test.cpp New unit tests for JSON-path workarounds (object args, non-null content, applyToJson).
src/test/llm/chat_template_analyzer_test.cpp New unit tests for template-family detection and inferred caps/parsers.
src/llm/visual_language_model/legacy/servable.cpp Applies input workarounds to Jinja JSON path and GenAI ChatHistory path in VLM legacy flow.
src/llm/visual_language_model/legacy/servable_initializer.cpp Updates chat-template mode selection (but currently duplicated).
src/llm/visual_language_model/continuous_batching/servable.cpp Applies input workarounds to both Jinja JSON and GenAI ChatHistory paths in VLM CB flow.
src/llm/servable.hpp Stores analyzed template caps + detected model family in GenAiServableProperties.
src/llm/servable.cpp Applies workarounds before template application on both Jinja and GenAI paths.
src/llm/servable_initializer.cpp Runs chat template analysis at init and auto-selects tool/reasoning parser when not explicitly configured.
src/llm/llm_calculator.proto Removes an outdated TODO comment for chat template mode.
src/llm/language_model/legacy/servable_initializer.cpp Updates chat-template mode selection (but currently duplicated).
src/llm/language_model/continuous_batching/servable_initializer.cpp Updates chat-template mode selection (but currently duplicated).
src/llm/input_workarounds.hpp Declares JSON + ChatHistory workaround APIs and aggregate apply functions.
src/llm/input_workarounds.cpp Implements workarounds for JSON and ChatHistory paths (but ChatHistory mutation currently broken).
src/llm/chat_template_caps.hpp New capability struct describing template requirements/support.
src/llm/chat_template_analyzer.hpp Declares analyzer result + analyzer entrypoint.
src/llm/chat_template_analyzer.cpp Implements Tier-1 pattern matching for family/caps/parser detection.
src/llm/BUILD Adds Bazel libraries for analyzer + workarounds and links them into genai servables.
src/BUILD Adds a new test library for analyzer/workaround tests into the main test target.
extras/chat_template_examples/chat_template_qwen36.jinja Updates example template to from_json tool-call arguments before iterating.
extras/chat_template_examples/chat_template_qwen35.jinja Adds a new example template variant with the same from_json workaround.
docs/plan_chat_template_input_workarounds.md Adds a design/plan document describing detection/workaround strategy and roadmap.

Comment thread src/llm/chat_template_adapter.cpp Outdated
Comment thread src/llm/chat_template_adapter.cpp Outdated
Comment thread src/llm/chat_template_adapter.cpp Outdated
Comment thread src/llm/chat_template_adapter.cpp Outdated
Comment thread src/llm/input_workarounds.cpp Outdated
Comment thread src/llm/input_workarounds.cpp Outdated
Comment thread src/llm/chat_template_adapter.cpp Outdated
Comment thread src/llm/servable.cpp Outdated
Compiles but not following Milosz redesign
Merge remote-tracking branch 'origin/main' into detect
result.caps.supportsToolCalls = true;
result.caps.supportsTools = true;
result.caps.supportsToolResponses = true;
return result;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

TODO: Add reasoning parser once @przepeck implements it

@dkalinowski dkalinowski requested a review from przepeck July 1, 2026 13:39
Comment thread src/llm/chat_template_analyzer.cpp Outdated
Comment thread src/test/llm/chat_template_compatibility.md Outdated
} else if (analysisResult.detectedToolParser.has_value()) {
properties->toolParserName = analysisResult.detectedToolParser.value();
SPDLOG_LOGGER_INFO(llm_calculator_logger, "Auto-detected tool_parser: {}", properties->toolParserName);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What if user for some reason don't want to use toolparser with model?
I remember, we were talking about CLI option --tool_parser none, don't we want to do it in this PR?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

it should be possible to set --tool_parser ""
i will verify and add tests, good catch

Comment thread src/llm/io_processing/input_processors/input_workarounds_processor.hpp Outdated
Comment thread src/llm/visual_language_model/legacy/servable.cpp
Comment thread src/llm/BUILD Outdated
Comment thread src/llm/chat_template_analyzer.cpp Outdated
Comment thread src/llm/io_processing/chat_template/analyzer.cpp

try {
strOk = PyJinjaTemplateProcessor::applyChatTemplate(templateProcessor, strArgsJson, strOut);
} catch (...) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is it always safe to just move on from exception? Could error in applyChatTemplate corrupt the state and second call that is done below would crash?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Neither of workarounds rely on exception check from jinja. Jinja doesnt throw an exception if it cannot apply the template. Either way, I added try catch. Will add error logs here just in case it changes in the future

Comment thread src/llm/chat_template_probe.hpp Outdated
Comment thread src/llm/chat_template_adapter.cpp Outdated
Comment thread src/llm/servable_initializer.cpp Outdated
Comment on lines +147 to +158
#if (PYTHON_DISABLE == 0)
if (properties->chatTemplateMode != ChatTemplateMode::JINJA) {
#endif
if (!probeChatTemplateBasicRenderMinja(properties->tokenizer)) {
SPDLOG_LOGGER_ERROR(llm_calculator_logger, "Chat template is not compatible with minja — basic rendering failed. "
"Disabling /chat/completions endpoint for this model.");
properties->tokenizer.set_chat_template("");
return;
}
#if (PYTHON_DISABLE == 0)
}
#endif

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

IMHO it's not a very readable construction with those ifdefs. Maybe we could determine if minja should be used earlier and just rely on the simple flag?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

btw. what about the jinja path? Is it used here?

@dkalinowski dkalinowski Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

IMHO it's not a very readable construction with those ifdefs. Maybe we could determine if minja should be used earlier and just rely on the simple flag?

I think @rasapala is working on that with runtime python check

btw. what about the jinja path? Is it used here?

No, we dont need basic probe for jinja, jinja doesnt silently fail

@dkalinowski dkalinowski changed the title Auto parser detect / auto input-workaround detection Auto parser detect / auto input-workaround detection / --parser none Jul 6, 2026

// =============================================================================
// Same story as Qwen3-8B.
// TODO(mzeglars): Do we keep it?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Don't think so. If qwen3-8B has the same type of template (in terms of needed adaptations) and we have separate tests in chat templates dir, then I suppose we can drop it here in the end to end test. Unless we wanted to check some VLM specific capabilities.

@mzegla mzegla requested a review from Copilot July 6, 2026 14:19

@przepeck przepeck left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

could you add to the docs/parameters.md information about --tool_parser none option?

@dkalinowski dkalinowski removed the WIP Do not merge until resolved label Jul 6, 2026

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

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

Comment thread src/llm/io_processing/input_processors/chat_template_adapter.cpp
Comment thread src/llm/io_processing/input_processors/chat_template_adapter.cpp
Comment on lines 16 to 19
#include <filesystem>
#include <chrono>
#include <future>
#include <memory>
Comment on lines +62 to +66
// detect what the template requires. This is model-agnostic and tests actual
// template behavior rather than relying solely on string pattern matching.
// Probes for:
// - requiresObjectArguments (workaround: string→object conversion of tool_call arguments)
// - requiresNonNullContent (workaround: ensure content="" rather than content=null for tool_call messages)
Comment on lines +149 to +153
// For now the capabilities are only related to tool calls, therefore we early exit here.
// In the future, if we add more capabilities to probe, we will need to remove this early exit and probe for those capabilities as well.
if (!caps.supportsToolCalls) {
return true;
}
Comment thread src/test/llm/chat_templates/chat_template_devstral.jinja
Comment thread src/test/llm/chat_templates/chat_template_phi4_mini.jinja
Comment thread src/test/llm/chat_templates/chat_template_phi4_mini.jinja
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.

4 participants