[Engine] Chat and Messages silently coerce boolean and fractional token limits
I maintainer di solito rispondono entro 3 giorni
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 72/100
Direzione di ricerca
Inizia in serve/server.py, nelle conversioni del limite di token intorno alle righe 7147 e 7395, poi leggi la convalida Responses correlata e il comportamento di Service.prepare intorno alle righe 4889-4898. Riproduci le richieste Chat e Messages elencate e confronta la loro convalida con quella di /v1/responses. Il lavoro è completato quando i limiti booleani e frazionari restituiscono HTTP 400, mentre i valori sentinella documentati -1 e 0 continuano a essere accettati.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Area
[Engine] (speed, kernels, models, the server and API)
Desktop app, Terminal or source?
Source (START-HERE.bat, setup.sh or a build)
What happened
/v1/chat/completions accepts true and 2.5 in either max_tokens or max_completion_tokens; my requests produced 1 and 2 completion tokens respectively. /v1/messages does the same for max_tokens. Chat max_tokens: false also succeeds and allows the 81-token answer to finish.
/v1/responses rejects the tested max_output_tokens: true and 2.5 requests with HTTP 400 and "max_output_tokens must be a positive whole number".
Expected: reject boolean and fractional token limits with HTTP 400 instead of silently converting them to a different generation budget. Preserve the documented integer -1 and 0 sentinel values.
Chat and Messages convert their selected token limit with int(...) at serve/server.py:7147 and serve/server.py:7395. This converts True to 1 and 2.5 to 2. With no other cap field supplied, False falls through the or expression to 0; Service.prepare treats that as the remaining context allowance (serve/server.py:4889-4898).
Smallest steps or command that reproduce it
The same build and config as in #4035 (commit 7dd5cf18). Server:
cd /content/Strata
python3 serve/server.py --engine strata --config /content/area3_config.json --host 127.0.0.1 --port 18091
Client:
import json
import urllib.error
import urllib.request
base = "http://127.0.0.1:18091"
prompt = "Count from 1 to 30, separated by single spaces, and nothing else."
def post(path, body):
req = urllib.request.Request(
base + path,
data=json.dumps(body).encode(),
headers={"Content-Type": "application/json"}
)
try:
with urllib.request.urlopen(req, timeout=300) as response:
return response.status, json.load(response)
except urllib.error.HTTPError as e:
return e.code, json.loads(e.read() or b"{}")
def chat(field, value):
body = {"model": "strata", "messages": [{"role": "user", "content": prompt}],
"temperature": 0, "reasoning_effort": "none", field: value}
status, r = post("/v1/chat/completions", body)
if status != 200:
return {"status": status, "error": r.get("error", r)}
c = r["choices"][0]
return {"status": status, "finish_reason": c["finish_reason"],
"completion_tokens": r["usage"]["completion_tokens"], "content": c["message"]["content"]}
def messages(value):
body = {"model": "strata", "messages": [{"role": "user", "content": prompt}],
"temperature": 0, "thinking": {"type": "disabled"}, "max_tokens": value}
status, r = post("/v1/messages", body)
if status != 200:
return {"status": status, "error": r.get("error", r)}
return {"status": status, "stop_reason": r["stop_reason"], "output_tokens": r["usage"]["output_tokens"],
"content": "".join(b.get("text", "") for b in r["content"] if b.get("type") == "text")}
def responses(value):
body = {"model": "strata", "input": prompt, "temperature": 0, "reasoning": {"effort": "none"},
"max_output_tokens": value}
status, r = post("/v1/responses", body)
if status != 200:
return {"status": status, "error": r.get("error", r)}
return {"status": status, "response_status": r.get("status"), "incomplete": r.get("incomplete_details"),
"output_tokens": (r.get("usage") or {}).get("output_tokens")}
cases = [
("chat max_tokens", lambda v: chat("max_tokens", v), [2, 1, True, False, 2.5]),
("chat max_completion_tokens", lambda v: chat("max_completion_tokens", v), [2, True, 2.5]),
("messages max_tokens", messages, [2, True, 2.5]),
("responses max_output_tokens", responses, [2, True, 2.5]),
]
for name, fn, values in cases:
for v in values:
print(json.dumps({"case": name, "value": v, **fn(v)}))
These cases are a subset of a larger client I ran; the log lines below are excerpts from that run, unchanged.
Reproduction status
Reproduced locally
Strata version
Commit 7dd5cf18e68c639a8773e096c5c79f971ea2a9f5 (main), engine 0.1.49.2
Graphics card, memory and system
NVIDIA RTX PRO 6000 Blackwell Server Edition 97,887 MiB · 176 GiB RAM · Ubuntu 24.04.4 LTS (Linux 6.6.122+, Google Colab), driver 580.82.07, CUDA 13.0.88, GCC 13.3.0, Python 3.13.16, AMD EPYC 9B45 (48 logical CPUs)
Model, size and settings
Qwen3.8-Flash-Next GSQ-RCO Q2_0 · 4096 context · INT8 KV · the config in #4035
Logs
Excerpts from my run, 2026-10-25:
{"case": "chat max_tokens", "value": 2, "status": 200, "finish_reason": "length", "completion_tokens": 2, "content": "1 "}
{"case": "chat max_tokens", "value": 1, "status": 200, "finish_reason": "length", "completion_tokens": 1, "content": "1"}
{"case": "chat max_tokens", "value": true, "status": 200, "finish_reason": "length", "completion_tokens": 1, "content": "1"}
{"case": "chat max_tokens", "value": false, "status": 200, "finish_reason": "stop", "completion_tokens": 81, "content": "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30"}
{"case": "chat max_tokens", "value": 2.5, "status": 200, "finish_reason": "length", "completion_tokens": 2, "content": "1 "}
{"case": "chat max_completion_tokens", "value": 2, "status": 200, "finish_reason": "length", "completion_tokens": 2, "content": "1 "}
{"case": "chat max_completion_tokens", "value": true, "status": 200, "finish_reason": "length", "completion_tokens": 1, "content": "1"}
{"case": "chat max_completion_tokens", "value": 2.5, "status": 200, "finish_reason": "length", "completion_tokens": 2, "content": "1 "}
{"case": "messages max_tokens", "value": 2, "status": 200, "stop_reason": "max_tokens", "output_tokens": 2, "content": "1 "}
{"case": "messages max_tokens", "value": true, "status": 200, "stop_reason": "max_tokens", "output_tokens": 1, "content": "1"}
{"case": "messages max_tokens", "value": 2.5, "status": 200, "stop_reason": "max_tokens", "output_tokens": 2, "content": "1 "}
{"case": "responses max_output_tokens", "value": 2, "status": 200, "response_status": "incomplete", "incomplete": {"reason": "max_output_tokens"}, "output_tokens": 2}
{"case": "responses max_output_tokens", "value": true, "status": 400, "error": {"message": "max_output_tokens must be a positive whole number", "type": "invalid_request_error", "param": "max_output_tokens", "code": null}}
{"case": "responses max_output_tokens", "value": 2.5, "status": 400, "error": {"message": "max_output_tokens must be a positive whole number", "type": "invalid_request_error", "param": "max_output_tokens", "code": null}}
Not checked in this run: streaming requests, numeric-string caps, false in chat max_completion_tokens, Messages max_tokens, or Responses max_output_tokens, or requests supplying both chat cap fields.
- Lingua principale
- C++
- Stelle
- 11.6k
- Fork
- 1k
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Niko1221/Strata
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
Niko1221/Strata#5138 · 2 commenti ·
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
Niko1221/Strata#5086 · 1 commento ·
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 3 giorni
-
[Other] Control hangs in platform.system() when Windows WMI is stuck: «Strata Control did not answer within 60 s (models list)», no GPU, nothing loadsForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 3 giorni
Tutte le issue di Niko1221/Strata
Issue simili
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
pocoproject/poco#5636 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
microsoft/cppwinrt#1646 · 7 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
[BUG] Segfault when all runs of a Complexity() benchmark are skippedForse già presa @nitanshnagpal l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 81/100