Replies: 9 comments 12 replies
|
The exception comes from the model chat template, not from llama.cpp. The template accepts only one system message, and that message must be first. The rule in the template
{%- for message in messages %}
{%- set content = render_content(message.content, true)|trim %}
{%- if message.role == "system" %}
{%- if not loop.first %}
{{- raise_exception('System message must be at the beginning.') }}
{%- endif %}The header block (lines 57-87) writes Why Claude Code is different from the web UIClaude Code uses the Anthropic endpoint First it puts the top-level auto system_param = json_value(body, "system", json());
if (!system_param.is_null()) {
...
oai_messages.push_back({
{"role", "system"},
{"content", system_content}
});
}Then it copies each item of if (content.is_string()) {
oai_messages.push_back(msg);
continue;
}Thus, if a request contains the top-level The web UI does not fail, because it sends only one system message. How to confirmStart the server with more log detail: llama-server ... -lv 4Then examine the messages of the failed request. Count the items that contain How to correct itGive the server a patched template. Copy the template from the model, then change lines 104-107. Write the later system message instead of stopping: {%- if message.role == "system" %}
{%- if not loop.first %}
{{- '<|im_start|>system\n' + content + '<|im_end|>' + '\n' }}
{%- endif %}Start the server with the new file: llama-server ... --jinja --chat-template-file ./qwen3.8-patched.jinjaYour other two questionsIs a template specific to the harness? No. The template is a property of the model, and llama.cpp reads it from the GGUF metadata. But each template has different rules. This template is strict, thus a harness that sends two system messages fails. Which models need Keep the default, and llama.cpp makes the decision for the model and the backend. |
|
If the template enforces a single system message, doesn't that mean that the model might not work properly if the template is hacked not enforce this? |
|
But so, if the need of flash attention and other params are things that's stored in the .gguf, why does the example specify all this on cmdline? |
|
Is it safe to remove the guard? Yes, but you lose content. In the main loop the To keep the content, write the block instead: {%- if message.role == "system" %}
{%- if not loop.first %}
{{- '<|im_start|>system\n' + content + '<|im_end|>' + '\n' }}
{%- endif %}How to get the template out of the GGUF Start the server, then read Then start the server with Why the example sets sampling parameters llama.cpp does read
To see which keys your file has: |
|
Managed to run the current master (ee4c505) with the latest Claude Code ( v2.1.237 ) without any problems using this patch : using |
|
I analyze patch anthropic-system-merge.patch against a real Claude Code session before adopting it, and it Setup: logging proxy in front of llama-server, real Claude Code session, How Claude Code actually sends system turns:
Cost: the patch inserts changing content at offset 0, so the common prefix
Full prompt averaged 67.7k tokens (max 82.5k), so ~90% of the context is reused Suggestion: the merge itself is the right idea — doing it in the converter is |
|
This is my current working configuration on V100 32GB. I updated my chat templates to the one in this repo which fixes several issues. https://github.com/jschmied/Qwen-Fixed-Chat-Templates It runs behind my LiteLLM proxy with the qwen3.8-dense alias and I launch Claude Code with the command below. Claude Code launch command.lamma.cpp launch command |
|
Thanks @realugbun anthropic-system-merge-2.patch against the current master (ee4c505) |
|
@mankeli The template is prefix-safe. Patch v2 is nearly prefix-safe, but not for Claude Code.
Nothing moves to offset 0, so the prefix stays stable. This is the "in-place" baseline @DanoPTT measured as good.
@AmmarkoV fold the leftover into the last message, not the first. For an append-at-tail client both are new that turn, so the prefix survives either way. Trade-off: the patch needs no template maintenance and also fixes the OAI path. The template needs no rebuild. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
After trying some unsloth qwen gguf and not understanding what was missing, I tried to follow #27080
I used cmdline
llama serve --host 0.0.0.0 \ -hf ggml-org/Qwen3.8-27B-GGUF:Q4_K_M \ -hfd ggml-org/Qwen3.8-27B-GGUF:Q4_0 \ --spec-default \ --spec-type draft-mtp \ --reasoning-preserveBut this doesn't work either. llama just prints
Now, after actually testing more, this seems to be related to Claude Code, since the web interface/cli works. I've been using 3.6 with some qwen3.6_chat_template.jinja I downloaded somewhere, but I didn't realize that the template needs to be harness specific?
Does anyone have good reference on explaining how these are supposed to work? I'm also very confused which models are supposed to be run with -fa for example.
All reactions