chat : pass reasoning_effort to template
* chat: add reasoning_effort to common_chat_templates_inputs Store OpenAI Chat Completions reasoning_effort and make it available to jinja templates (with model specific translations where required). Assisted-by: llama.cpp:Muse-Glimmer-30B * server : fixup reading reasoning effort from body server_chat_convert_responses_to_chatcmpl already handles conversion of Responses API reasoning.effort to reasoning_effort * chat : expose reasoning effort Assisted-by: Claude Opus 5 * chat : add reasoning_effort to generation_params Assisted-by: Claude Opus 5 * chat : move reasoning_effort next to enable_thinking Assisted-by: Claude Opus 5 * cont : mirror preserve_reasoning * cont : pass context through analyze function --------- Co-authored-by: Alde Rojas <hello@alde.dev>
This commit is contained in:
co-authored by
Alde Rojas
parent
9b05354ec6
commit
7e4c0a9688
@@ -3646,6 +3646,18 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
|
||||
}
|
||||
}
|
||||
).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_REASONING"));
|
||||
add_opt(common_arg(
|
||||
{"--reasoning-effort"}, "LEVEL",
|
||||
"reasoning effort level given to the chat template: 'default' to keep the template default,\n"
|
||||
"or a level such as 'minimal', 'low', 'medium', 'high', 'xhigh' or 'max' (default: default)",
|
||||
[](common_params & params, const std::string & value) {
|
||||
if (value == "default") {
|
||||
params.default_template_kwargs.erase("reasoning_effort");
|
||||
} else {
|
||||
params.default_template_kwargs["reasoning_effort"] = json(value).dump();
|
||||
}
|
||||
}
|
||||
).set_examples({LLAMA_EXAMPLE_SERVER, LLAMA_EXAMPLE_COMPLETION, LLAMA_EXAMPLE_CLI}).set_env("LLAMA_ARG_REASONING_EFFORT"));
|
||||
add_opt(common_arg(
|
||||
{"--reasoning-budget"}, "N",
|
||||
"token budget for thinking: -1 for unrestricted, 0 for immediate end, N>0 for token budget (default: -1)",
|
||||
|
||||
@@ -920,6 +920,10 @@ static std::string common_chat_template_direct_apply_impl(
|
||||
bool enabled = inp["preserve_reasoning"].get<bool>();
|
||||
jinja::caps_apply_preserve_reasoning(ctx, enabled);
|
||||
}
|
||||
if (inp.contains("reasoning_effort") && inp["reasoning_effort"].is_string() && !inp["reasoning_effort"].empty()) {
|
||||
std::string reasoning_effort = inp["reasoning_effort"].get<std::string>();
|
||||
jinja::caps_apply_reasoning_effort(ctx, reasoning_effort);
|
||||
}
|
||||
|
||||
jinja::global_from_json(ctx, inp, inputs.mark_input);
|
||||
|
||||
|
||||
+41
-8
@@ -17,7 +17,7 @@ namespace jinja {
|
||||
|
||||
using caps_json_fn = std::function<json()>;
|
||||
using caps_ctx_fn = std::function<void(context &)>;
|
||||
using caps_analyze_fn = std::function<void(bool, value &, value &, const std::string &)>;
|
||||
using caps_analyze_fn = std::function<void(context &, bool, value &, value &, const std::string &)>;
|
||||
|
||||
void caps_apply_preserve_reasoning(jinja::context & ctx, bool enabled) {
|
||||
ctx.set_val("preserve_thinking", mk_val<value_bool>(enabled));
|
||||
@@ -26,6 +26,12 @@ void caps_apply_preserve_reasoning(jinja::context & ctx, bool enabled) {
|
||||
ctx.set_val("drop_thinking", mk_val<value_bool>(!enabled));
|
||||
}
|
||||
|
||||
void caps_apply_reasoning_effort(jinja::context & ctx, const std::string & effort) {
|
||||
value var = mk_val<value_string>(effort); // bind to the same value for stats
|
||||
ctx.set_val("reasoning_effort", var);
|
||||
ctx.set_val("reasoning_strength", var);
|
||||
}
|
||||
|
||||
static void caps_try_execute(jinja::program & prog,
|
||||
const caps_json_fn & messages_fn,
|
||||
const caps_ctx_fn & ctx_fn,
|
||||
@@ -62,7 +68,7 @@ static void caps_try_execute(jinja::program & prog,
|
||||
// ignore exceptions during capability analysis
|
||||
}
|
||||
|
||||
analyze_fn(success, messages, tools, result);
|
||||
analyze_fn(ctx, success, messages, tools, result);
|
||||
}
|
||||
|
||||
// for debugging only
|
||||
@@ -87,6 +93,7 @@ std::map<std::string, bool> caps::to_map() const {
|
||||
{"supports_parallel_tool_calls", supports_parallel_tool_calls},
|
||||
{"supports_system_role", supports_system_role},
|
||||
{"supports_preserve_reasoning", supports_preserve_reasoning},
|
||||
{"supports_reasoning_effort", supports_reasoning_effort},
|
||||
{"supports_object_arguments", supports_object_arguments},
|
||||
};
|
||||
}
|
||||
@@ -124,7 +131,7 @@ caps caps_get(jinja::program & prog) {
|
||||
},
|
||||
nullptr, // ctx_fn
|
||||
nullptr, // tools_fn
|
||||
[&](bool success, value & messages, value &, const std::string &) {
|
||||
[&](context &, bool success, value & messages, value &, const std::string &) {
|
||||
auto & content = messages->at(0)->at("content");
|
||||
caps_print_stats(content, "messages[0].content");
|
||||
if (has_op(content, "selectattr") || has_op(content, "array_access")) {
|
||||
@@ -158,7 +165,7 @@ caps caps_get(jinja::program & prog) {
|
||||
},
|
||||
nullptr, // ctx_fn
|
||||
nullptr, // tools_fn
|
||||
[&](bool, value & messages, value &, const std::string &) {
|
||||
[&](context &, bool, value & messages, value &, const std::string &) {
|
||||
auto & content = messages->at(0)->at("content");
|
||||
caps_print_stats(content, "messages[0].content");
|
||||
if (!content->stats.used) {
|
||||
@@ -234,7 +241,7 @@ caps caps_get(jinja::program & prog) {
|
||||
},
|
||||
});
|
||||
},
|
||||
[&](bool success, value & messages, value & tools, const std::string &) {
|
||||
[&](context &, bool success, value & messages, value & tools, const std::string &) {
|
||||
if (!success) {
|
||||
return; // Nothing can be inferred
|
||||
}
|
||||
@@ -327,7 +334,7 @@ caps caps_get(jinja::program & prog) {
|
||||
},
|
||||
});
|
||||
},
|
||||
[&](bool success, value & messages, value & tools, const std::string &) {
|
||||
[&](context &, bool success, value & messages, value & tools, const std::string &) {
|
||||
if (!success) {
|
||||
result.supports_tool_calls = false;
|
||||
result.supports_tools = false;
|
||||
@@ -429,7 +436,7 @@ caps caps_get(jinja::program & prog) {
|
||||
},
|
||||
});
|
||||
},
|
||||
[&](bool success, value & messages, value &, const std::string &) {
|
||||
[&](context &, bool success, value & messages, value &, const std::string &) {
|
||||
if (!success) {
|
||||
result.supports_parallel_tool_calls = false;
|
||||
return;
|
||||
@@ -486,7 +493,7 @@ caps caps_get(jinja::program & prog) {
|
||||
caps_apply_preserve_reasoning(ctx, true);
|
||||
},
|
||||
nullptr, // tools_fn
|
||||
[&](bool, value &, value &, const std::string & output) {
|
||||
[&](context &, bool, value &, value &, const std::string & output) {
|
||||
// note: we cannot use stats here because the reasoning_content may be used for "if" condition test, but not actually outputted in the final result
|
||||
if (output.find(reasoning_placeholder) != std::string::npos) {
|
||||
result.supports_preserve_reasoning = true;
|
||||
@@ -494,6 +501,32 @@ caps caps_get(jinja::program & prog) {
|
||||
}
|
||||
);
|
||||
|
||||
JJ_DEBUG("%s\n", ">>> Running capability check: reasoning effort");
|
||||
|
||||
// case: reasoning effort level
|
||||
caps_try_execute(
|
||||
prog,
|
||||
[&]() {
|
||||
// messages
|
||||
return json::array({
|
||||
{
|
||||
{"role", "user"},
|
||||
{"content", "User message"}
|
||||
},
|
||||
});
|
||||
},
|
||||
[&](context & ctx) {
|
||||
ctx.set_val("enable_thinking", mk_val<value_bool>(true));
|
||||
caps_apply_reasoning_effort(ctx, "low");
|
||||
},
|
||||
nullptr, // tools_fn
|
||||
[&](context & ctx, bool, value &, value &, const std::string &) {
|
||||
value effort = ctx.get_val("reasoning_effort");
|
||||
caps_print_stats(effort, "reasoning_effort");
|
||||
result.supports_reasoning_effort = effort->stats.used;
|
||||
}
|
||||
);
|
||||
|
||||
JJ_DEBUG("%s\n", result.to_string().c_str());
|
||||
|
||||
return result;
|
||||
|
||||
@@ -16,6 +16,9 @@ struct caps {
|
||||
// supports preserve reasoning trace in the full history, not just the last assistant message
|
||||
bool supports_preserve_reasoning = false;
|
||||
|
||||
// supports reasoning effort levels
|
||||
bool supports_reasoning_effort = false;
|
||||
|
||||
// one of the 2 content capabilities must be true
|
||||
bool supports_string_content = true;
|
||||
bool supports_typed_content = false;
|
||||
@@ -32,5 +35,6 @@ struct caps {
|
||||
caps caps_get(jinja::program & prog);
|
||||
|
||||
void caps_apply_preserve_reasoning(jinja::context & ctx, bool enabled);
|
||||
void caps_apply_reasoning_effort(jinja::context & ctx, const std::string & effort);
|
||||
|
||||
} // namespace jinja
|
||||
|
||||
Reference in New Issue
Block a user