Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions serve/conv_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,27 @@
CHAT = "chat" # cache on
BATCH = "batch" # cache off

DEFAULT_BATCH_AFTER = 4


def resolve_batch_after(cli, cfg):
"""The run length the router uses: the CLI flag wins, then the config's key, then 4.

The launcher writes `conv_route_batch_after` into the run config and starts the server without the flag
(`strata-b70-serve.sh`), so a server that only read the flag ran 4 for every deployment - measured 2026-11-14:
a config of 1 and the default produced byte-identical mixed-traffic results until the flag was passed by hand.
"""
for v in (cli, (cfg or {}).get("conv_route_batch_after") if isinstance(cfg, dict) else None):
if v is None or isinstance(v, bool):
continue
try:
n = int(v)
except (TypeError, ValueError):
continue
if n >= 1:
return n
return DEFAULT_BATCH_AFTER


@dataclass
class Decision:
Expand Down
8 changes: 5 additions & 3 deletions serve/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
tool_choice_of, unmark_think_literals)
from serve.mcp import McpCancelled, hub_from_config # noqa: E402
from serve import conv_router as conv_route_mod # noqa: E402
from serve.conv_router import resolve_batch_after # noqa: E402
from serve import runconfig # noqa: E402
from serve.webfiles import subtree_file as web_subtree_file # noqa: E402
from strata_control import engine_component # noqa: E402
Expand Down Expand Up @@ -10386,8 +10387,9 @@ def notify_lifecycle(kind: str, payload: dict) -> None:
help="switch the engine's prompt/conversation cache per traffic shape: single-shot batches off "
"(prefill +33 %%), chat/agent on (a repeated context reuses, 5.3 s -> 0.3 s). 'shadow' only "
"logs what it would do (serve/conv_router.py)")
ap.add_argument("--conv-route-batch-after", type=int, default=4,
help="consecutive single-shot requests before the cache is switched off (default 4)")
ap.add_argument("--conv-route-batch-after", type=int, default=None,
help="consecutive single-shot requests before the cache is switched off (default: the config's "
"conv_route_batch_after, else 4)")
ap.add_argument("--thinking-policy", choices=["off", "shadow", "on"], default=None,
help="do not pay for a thinking block on a request that asks for a short direct answer "
"(extraction, formatting, translation, a one-word reply; serve/prompt_kind.py "
Expand Down Expand Up @@ -10731,7 +10733,7 @@ def request_stop(reason: str):
_pc = 6
_cr = cfg.get("conv_route")
svc.set_conv_route(a.conv_route or (_cr if isinstance(_cr, str) else "") or "off",
cache_on=_pc, batch_after=a.conv_route_batch_after)
cache_on=_pc, batch_after=resolve_batch_after(a.conv_route_batch_after, cfg))
if (cfg.get("arch") or "") == "deepseek41" and vision is None and a.engine == "strata":
# DeepSeek-V4.1 reads pictures with the engine's own tower (--vision on, the default): no separate reader process.
# `--vision off` in the config's args, or a pack without a tower, leaves svc.vision None: pictures are refused with the 400 as before.
Expand Down
13 changes: 12 additions & 1 deletion serve/test_conv_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from serve.conv_router import BATCH, CHAT, Router # noqa: E402
from serve.conv_router import BATCH, CHAT, Router, resolve_batch_after # noqa: E402


def one(text="Summarise this document."):
Expand Down Expand Up @@ -106,6 +106,17 @@ def test_report_counts_every_request():
assert rep["chat"] + rep["batch"] == 3


def test_the_config_key_is_honoured_when_the_flag_is_absent():
"""The launcher writes conv_route_batch_after into the config and passes no flag, so the config must win over 4."""
assert resolve_batch_after(None, {"conv_route_batch_after": 2}) == 2
assert resolve_batch_after(None, {"conv_route_batch_after": "3"}) == 3
assert resolve_batch_after(1, {"conv_route_batch_after": 2}) == 1, "an explicit flag wins over the config"
assert resolve_batch_after(None, {}) == 4, "no flag and no key keeps the old default"
assert resolve_batch_after(None, None) == 4
for bad in (0, -1, True, "off", [1], {}):
assert resolve_batch_after(None, {"conv_route_batch_after": bad}) == 4, f"malformed {bad!r} must not crash"


def test_the_prefix_history_is_bounded():
r = Router(repeat_window=8)
for i in range(50):
Expand Down
Loading