-
-
Notifications
You must be signed in to change notification settings - Fork 441
feat(serve): override the frontend chat template via --chat-template FILE #183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,9 +19,11 @@ | |
| #include <cctype> | ||
| #include <cstddef> | ||
| #include <cstdint> | ||
| #include <fstream> | ||
| #include <limits> | ||
| #include <memory> | ||
| #include <optional> | ||
| #include <sstream> | ||
| #include <span> | ||
| #include <stdexcept> | ||
| #include <string> | ||
|
|
@@ -230,6 +232,38 @@ fi::CompiledChatTemplate compile_chat_template(const FrontendResources& resource | |
| return fi::CompiledChatTemplate::resolve(resources.chat_template_jinja); | ||
| } | ||
|
|
||
| // Replaces the artifact chat template with an operator-provided source and keeps | ||
| // tokenizer_config.json.chat_template byte-consistent with it, so the existing | ||
| // validation and template-resolution gates run against the override unchanged. | ||
| void apply_chat_template_override(FrontendResources& resources, | ||
| const std::filesystem::path& chat_template_path) { | ||
| std::ifstream stream(chat_template_path, std::ios::binary); | ||
| if (!stream) { | ||
| throw std::invalid_argument("chat template file is not readable: " + | ||
| chat_template_path.string()); | ||
| } | ||
| std::ostringstream buffer; | ||
| buffer << stream.rdbuf(); | ||
| std::string source = buffer.str(); | ||
| if (source.size() > (10U << 20)) { | ||
|
Comment on lines
+245
to
+248
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Useful? React with 👍 / 👎. |
||
| throw std::invalid_argument("chat template file exceeds 10 MiB: " + | ||
| chat_template_path.string()); | ||
| } | ||
| // A single trailing newline is not template content: the jinja source parser | ||
| // drops it, and the acceptance digest is defined over the content without it. | ||
| if (!source.empty() && source.back() == '\n') { source.pop_back(); } | ||
| resources.chat_template_jinja = std::move(source); | ||
| Json tokenizer_config = | ||
| parse_resource_json(resources.tokenizer_config_json, "tokenizer_config.json"); | ||
| tokenizer_config["chat_template"] = resources.chat_template_jinja; | ||
| try { | ||
| resources.tokenizer_config_json = tokenizer_config.dump(); | ||
| } catch (const nlohmann::json::exception&) { | ||
| throw std::invalid_argument("chat template file is not valid UTF-8 text: " + | ||
| chat_template_path.string()); | ||
| } | ||
| } | ||
|
|
||
| [[noreturn]] void throw_processor_error(const fi::ProcessorError& error) { | ||
| switch (error.kind()) { | ||
| case fi::ProcessorErrorKind::BudgetExceeded: | ||
|
|
@@ -1355,6 +1389,11 @@ Frontend& Frontend::operator=(Frontend&&) noexcept = default; | |
| Frontend::~Frontend() = default; | ||
|
|
||
| Frontend make_frontend(const FrontendResources& resources, FrontendOptions options) { | ||
| if (!options.chat_template_path.empty()) { | ||
| FrontendResources overridden = resources; | ||
| apply_chat_template_override(overridden, options.chat_template_path); | ||
| return Frontend(std::make_shared<const Frontend::Impl>(overridden, true, options)); | ||
| } | ||
| return Frontend(std::make_shared<const Frontend::Impl>(resources, true, options)); | ||
| } | ||
|
|
||
|
|
@@ -1368,6 +1407,11 @@ Frontend FrontendTestAccess::create_component(const FrontendResources& resources | |
|
|
||
| Frontend FrontendTestAccess::create_component(const FrontendResources& resources, | ||
| FrontendOptions options) { | ||
| if (!options.chat_template_path.empty()) { | ||
| FrontendResources overridden = resources; | ||
| apply_chat_template_override(overridden, options.chat_template_path); | ||
| return Frontend(std::make_shared<const Frontend::Impl>(overridden, false, options)); | ||
| } | ||
| return Frontend(std::make_shared<const Frontend::Impl>(resources, false, options)); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
--chat-templateselects v22.5, thinking is enabled, and the client omitsreasoning_effort, the accepted source explicitly defaults tomedium(reasoning_effort_froggeric_v225_chat_template.jinja:17-29), but this branch aliases it to semantics whose capabilities and renderer default toXHigh(capabilities()at line 448 andresolve_reasoning_instructions()at line 367). Ordinary requests therefore receive an extra xhigh system instruction and are logged as xhigh instead of rendering the selected template; represent the v22.5 default and render behavior separately rather than aliasing it to the existing template.Useful? React with 👍 / 👎.