An effort the model had never heard of
Reported from a live instance, on Bonsai: Jinja Exception: Unexpected reasoning effort high. Supported types are xhigh (default), medium, and low. Effort goes out two ways because no single field works, and the second -- chat_template_kwargs -- is not a parameter the server interprets. It is rendered into the model's own chat template, which does not ignore a value it does not know: it calls raise_exception, and the request dies before a token. So a perfectly ordinary option, drawn by this application in its own menu, took the whole reply with it. The vocabulary is per model and nobody agrees. gpt-oss takes low/medium/high. Bonsai takes low/medium/xhigh and refuses high. OpenAI has added minimal, xhigh and max at different points, and which of them a given model accepts varies again. One global tuple was going to be wrong for somebody whatever it held. A model carries its own list now, and the picker, the slash command and the request builder all read it. A column rather than a key in capabilities_json, for the reason context_length is one: that dict is rebuilt wholesale from the submitted checkboxes on every save. And it corrects itself. A refusal retries the reply once without the effort rather than losing it -- safe only because the template renders before any token, so nothing has been emitted, and there is a guard that keeps it that way -- then narrows the model's list. Bonsai's error states what it does take, so that is what gets stored. Note the parser bug, because it is a good one: "high" is a substring of "xhigh", so reading the advertised list by substring learned `high` from a sentence explaining that `high` is the problem. Whole words now, with a test named after it. /effort reads its levels off the picker instead of a second copy of the list kept in the browser. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -271,8 +271,21 @@
|
||||
|
||||
/* --- Reasoning effort ---------------------------------------------------
|
||||
The command drives the same select the composer shows, so there is one
|
||||
piece of state and the control updates itself when the command is used. */
|
||||
var EFFORTS = ["low", "medium", "high"];
|
||||
piece of state and the control updates itself when the command is used.
|
||||
|
||||
Which efforts exist is read off that select's own options rather than
|
||||
kept here. It used to be a second copy of `["low","medium","high"]`, which
|
||||
was wrong the moment the vocabulary became per model: a Bonsai takes
|
||||
`xhigh` and no `high`, so the list the server rendered and the list this
|
||||
file believed in disagreed -- and the one that decides what `/effort xhigh`
|
||||
does was this one. The select is the table; nothing else should hold it. */
|
||||
function efforts() {
|
||||
var select = el("[data-effort]");
|
||||
if (!select) return [];
|
||||
return Array.prototype.map
|
||||
.call(select.options, function (option) { return option.value; })
|
||||
.filter(function (value) { return value !== "off"; });
|
||||
}
|
||||
|
||||
function setEffort(rest) {
|
||||
var select = el("[data-effort]");
|
||||
@@ -283,12 +296,14 @@
|
||||
"error"
|
||||
);
|
||||
}
|
||||
var available = efforts();
|
||||
var listed = available.join(", ");
|
||||
var wanted = (rest || "").trim().toLowerCase();
|
||||
if (!wanted) {
|
||||
return note(
|
||||
EFFORTS.indexOf(select.value) === -1
|
||||
? "No effort is being sent. Try low, medium or high."
|
||||
: "Effort is " + select.value + ". /effort low, medium, high, or off."
|
||||
available.indexOf(select.value) === -1
|
||||
? "No effort is being sent. Try " + listed + "."
|
||||
: "Effort is " + select.value + ". /effort " + listed + ", or off."
|
||||
);
|
||||
}
|
||||
/* "off" is the option's real value, not an empty string: the new-chat form
|
||||
@@ -296,8 +311,11 @@
|
||||
sentinel and this has to match it. "default" and "none" still work,
|
||||
because somebody's fingers will type them. */
|
||||
if (wanted === "default" || wanted === "none") wanted = "off";
|
||||
else if (wanted !== "off" && EFFORTS.indexOf(wanted) === -1) {
|
||||
return note("“" + wanted + "” is not an effort. Try low, medium, high or off.", "error");
|
||||
else if (wanted !== "off" && available.indexOf(wanted) === -1) {
|
||||
return note(
|
||||
"“" + wanted + "” is not an effort this model takes. Try " + listed + " or off.",
|
||||
"error"
|
||||
);
|
||||
}
|
||||
select.value = wanted;
|
||||
select.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
|
||||
Reference in New Issue
Block a user