Summary
BaseRT 0.1.7 native /v1/chat/completions does not reliably isolate Qwen3.6 hybrid tool-call requests when the server reuses a common prompt prefix. Sequential requests eventually lose the tool call; concurrent requests return corrupted arguments or exhaust max_tokens.
Restarting the server before every request makes the same requests pass 3/3. Routing the same model through our /v1/completions-based compatibility layer with a global request lock also passes repeatedly. This points to cross-request KV/recurrent-state reuse/isolation in the native chat path, rather than model weights or the new XML parser itself.
Environment
- BaseRT 0.1.7, official macOS arm64 release bundle
- macOS 26.4.1, M1 Max 64 GB
Qwen/Qwen3.6-35B-A3B, default-q4, converted with BaseRT
- Server (no paged-KV / CB / prefix-cache flags):
basert-serve model.base \
--host 127.0.0.1 --port 8896 \
--max-context 262144 --request-timeout 600000
Minimal sequential reproduction
Send this request repeatedly on one fresh server, changing only seq-N:
{
"model": "Qwen/Qwen3.6-35B-A3B",
"messages": [{"role":"user","content":"Call lookup_key with key seq-0."}],
"tools": [{
"type":"function",
"function": {
"name":"lookup_key",
"description":"Lookup a key",
"parameters": {
"type":"object",
"properties":{"key":{"type":"string"}},
"required":["key"]
}
}
}],
"max_tokens": 2048,
"temperature": 0
}
Observed on one fresh process:
seq-0 tool_calls lookup_key({"key":"seq-0"}) prompt=274 completion=142
seq-1 tool_calls lookup_key({"key":"seq-1"}) prompt=9 completion=102
seq-2 tool_calls lookup_key({"key":"seq-2"}) prompt=9 completion=90
seq-3 tool_calls lookup_key({"key":"seq-3"}) prompt=9 completion=82
seq-4 tool_calls lookup_key({"key":"seq-4"}) prompt=9 completion=120
seq-5 length no tool_calls prompt=9 completion=2048
The drop from 274 to 9 reported prompt tokens shows that the server is reusing the common rendered prefix. Restarting basert-serve before each of three requests (fresh-a/b/c) produces the correct single lookup_key call 3/3.
After the failing run, /slots reports:
[{"id":0,"is_processing":false,"cache_tokens":275,"cache_position":403}]
Concurrent reproduction (more severe)
From a fresh process, submit the same shape concurrently with distinct key values.
Two concurrent requests:
requested c2-0 -> lookup_key({"key":"key"}) WRONG
requested c2-1 -> finish_reason=length, 2048 tokens, no tool call
Four concurrent requests:
requested c4-0 -> lookup_key({"key":"4"}) WRONG
requested c4-1 -> lookup_key({"key":"4"}) WRONG
requested c4-2 -> finish_reason=length, no call
requested c4-3 -> lookup_key({"key":"4-3"}) WRONG (lost prefix)
So 0/2 and 0/4 requests preserved their requested argument. Access log timestamps show the POSTs overlap even though this Qwen3.6 hybrid model does not support independent recurrent sequences / continuous batching.
Controls
- Fresh server per request: correct 3/3.
- Different tool schemas separated by a plain chat request:
alpha_lookup(A1) -> plain response -> beta_fetch(Paris) -> beta_fetch(Rome) all correct in a short run. The failure is therefore sensitive to common-prefix reuse / repeated tool request shape, not simply “the previous schema always leaks.”
- Same 0.1.7 core via a
/v1/completions compatibility layer with a global lock: repeated tool calls correct 3/3.
- 0xAD/CJK fixes are healthy:
桜の and a 512-token Chinese generation both return HTTP 200 on this build.
Expected
Every HTTP request must have isolated recurrent/KV state. If the hybrid architecture cannot support independent concurrent sequences, basert-serve should serialize/queue requests internally rather than allow overlapping forwards. Common-prefix reuse must restore/branch all hybrid recurrent state correctly, not only attention KV.
Impact / workaround
This prevents us from retiring our compatibility layer after #21: a long-running agent backend eventually misses or corrupts tool calls, and concurrent callers can receive arguments derived from another request.
Current safe workaround is:
- global request lock outside
basert-serve; and
- use
/v1/completions with externally rendered prompts/tool parsing.
I have a small Python harness that reproduces the sequential and N=2/N=4 cases and can test a diagnostic build immediately.
Summary
BaseRT 0.1.7 native
/v1/chat/completionsdoes not reliably isolate Qwen3.6 hybrid tool-call requests when the server reuses a common prompt prefix. Sequential requests eventually lose the tool call; concurrent requests return corrupted arguments or exhaustmax_tokens.Restarting the server before every request makes the same requests pass 3/3. Routing the same model through our
/v1/completions-based compatibility layer with a global request lock also passes repeatedly. This points to cross-request KV/recurrent-state reuse/isolation in the native chat path, rather than model weights or the new XML parser itself.Environment
Qwen/Qwen3.6-35B-A3B,default-q4, converted with BaseRTMinimal sequential reproduction
Send this request repeatedly on one fresh server, changing only
seq-N:{ "model": "Qwen/Qwen3.6-35B-A3B", "messages": [{"role":"user","content":"Call lookup_key with key seq-0."}], "tools": [{ "type":"function", "function": { "name":"lookup_key", "description":"Lookup a key", "parameters": { "type":"object", "properties":{"key":{"type":"string"}}, "required":["key"] } } }], "max_tokens": 2048, "temperature": 0 }Observed on one fresh process:
The drop from 274 to 9 reported prompt tokens shows that the server is reusing the common rendered prefix. Restarting
basert-servebefore each of three requests (fresh-a/b/c) produces the correct singlelookup_keycall 3/3.After the failing run,
/slotsreports:[{"id":0,"is_processing":false,"cache_tokens":275,"cache_position":403}]Concurrent reproduction (more severe)
From a fresh process, submit the same shape concurrently with distinct key values.
Two concurrent requests:
Four concurrent requests:
So 0/2 and 0/4 requests preserved their requested argument. Access log timestamps show the POSTs overlap even though this Qwen3.6 hybrid model does not support independent recurrent sequences / continuous batching.
Controls
alpha_lookup(A1)-> plain response ->beta_fetch(Paris)->beta_fetch(Rome)all correct in a short run. The failure is therefore sensitive to common-prefix reuse / repeated tool request shape, not simply “the previous schema always leaks.”/v1/completionscompatibility layer with a global lock: repeated tool calls correct 3/3.桜のand a 512-token Chinese generation both return HTTP 200 on this build.Expected
Every HTTP request must have isolated recurrent/KV state. If the hybrid architecture cannot support independent concurrent sequences,
basert-serveshould serialize/queue requests internally rather than allow overlapping forwards. Common-prefix reuse must restore/branch all hybrid recurrent state correctly, not only attention KV.Impact / workaround
This prevents us from retiring our compatibility layer after #21: a long-running agent backend eventually misses or corrupts tool calls, and concurrent callers can receive arguments derived from another request.
Current safe workaround is:
basert-serve; and/v1/completionswith externally rendered prompts/tool parsing.I have a small Python harness that reproduces the sequential and N=2/N=4 cases and can test a diagnostic build immediately.