OpenRouter stop cap is 4, GGUF tool-loop final pass forwards new fields
OpenRouter normalises to OpenAI's chat schema and inherits the 4-entry stop cap. The default 16-cap was too permissive; add stop_max=4 on both the backend provider registry and the frontend PROVIDER_STOP_MAX map. The GGUF tool-iteration final-answer pass at llama_cpp.py:5182 was carrying only the legacy sampling fields. Forward frequency_penalty, seed, and parallel_tool_calls there too so the cap-exhausted path matches the per-iteration loop. Test pins the OpenRouter 4-cap.
This commit is contained in:
parent
10ade237cd
commit
1d1a205a19
4 changed files with 47 additions and 6 deletions
|
|
@ -5202,6 +5202,14 @@ class LlamaCppBackend:
|
|||
stream_payload["t_max_predict_ms"] = _DEFAULT_T_MAX_PREDICT_MS
|
||||
if stop:
|
||||
stream_payload["stop"] = stop
|
||||
# Match the per-iteration tool loop above so sampling behavior
|
||||
# stays consistent when the cap-exhausted final-answer pass runs.
|
||||
if frequency_penalty is not None:
|
||||
stream_payload["frequency_penalty"] = frequency_penalty
|
||||
if seed is not None:
|
||||
stream_payload["seed"] = seed
|
||||
if parallel_tool_calls is not None:
|
||||
stream_payload["parallel_tool_calls"] = parallel_tool_calls
|
||||
stream_payload["stream_options"] = {"include_usage": True}
|
||||
|
||||
cumulative = ""
|
||||
|
|
|
|||
|
|
@ -312,6 +312,9 @@ PROVIDER_REGISTRY: dict[str, dict[str, Any]] = {
|
|||
},
|
||||
"notes": "Unified gateway to 300+ models across all major providers. HTTP-Referer and X-Title headers sent for attribution.",
|
||||
"model_list_mode": "curated",
|
||||
# OpenRouter normalises to OpenAI's chat schema and inherits
|
||||
# the 4-entry stop cap.
|
||||
"stop_max": 4,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -607,6 +607,34 @@ def test_kimi_web_search_uses_kimi_stop_cap_5(monkeypatch):
|
|||
assert body["stop"] == ["S0", "S1", "S2", "S3", "S4"], body
|
||||
|
||||
|
||||
def test_openrouter_stop_cap_is_4(monkeypatch):
|
||||
"""OpenRouter normalises to OpenAI's chat schema and inherits the
|
||||
4-entry stop cap; the default 16-cap is too permissive for it."""
|
||||
captured = _install_mock(monkeypatch, sse_payload = _oai_done_payload())
|
||||
|
||||
async def run():
|
||||
client = ExternalProviderClient(
|
||||
provider_type = "openrouter",
|
||||
base_url = "https://openrouter.ai/api/v1",
|
||||
api_key = "or-test",
|
||||
)
|
||||
async for _ in client.stream_chat_completion(
|
||||
messages = [{"role": "user", "content": "hi"}],
|
||||
model = "openai/gpt-4o",
|
||||
temperature = 0.5,
|
||||
top_p = 0.9,
|
||||
max_tokens = 64,
|
||||
stop = [f"S{i}" for i in range(10)],
|
||||
):
|
||||
pass
|
||||
await client.close()
|
||||
|
||||
_drive(run())
|
||||
body = captured["body"]
|
||||
assert len(body.get("stop", [])) == 4, body
|
||||
assert body["stop"] == ["S0", "S1", "S2", "S3"], body
|
||||
|
||||
|
||||
def test_kimi_drops_stop_strings_over_32_bytes(monkeypatch):
|
||||
"""Kimi limits each stop string to <= 32 bytes per
|
||||
https://platform.kimi.ai/docs/api/chat. Drop overlong entries
|
||||
|
|
|
|||
|
|
@ -64,12 +64,13 @@ export interface ProviderCapabilities {
|
|||
* Per-provider stop-sequence max count. Resolved by
|
||||
* `getProviderStopMax(providerType)`. Mirrors the backend's
|
||||
* `provider_info.stop_max` for the same provider type.
|
||||
* - openai: 4 (Chat Completions hard cap; Responses drops stop)
|
||||
* - anthropic: 16 (client-side guard; docs publish no max)
|
||||
* - kimi: 5 (https://platform.kimi.ai/docs/api/chat)
|
||||
* - deepseek: 16 (https://api-docs.deepseek.com/api/create-chat-completion)
|
||||
* - mistral: 16 (no documented max; widen to permissive default)
|
||||
* - default: 16 (covers ollama, vllm, llama.cpp, openrouter, custom)
|
||||
* - openai: 4 (Chat Completions hard cap; Responses drops stop)
|
||||
* - anthropic: 16 (client-side guard; docs publish no max)
|
||||
* - kimi: 5 (https://platform.kimi.ai/docs/api/chat)
|
||||
* - deepseek: 16 (https://api-docs.deepseek.com/api/create-chat-completion)
|
||||
* - mistral: 16 (no documented max; widen to permissive default)
|
||||
* - openrouter: 4 (normalises to OpenAI's chat schema)
|
||||
* - default: 16 (covers ollama, vllm, llama.cpp, custom)
|
||||
*/
|
||||
const PROVIDER_STOP_MAX: Record<string, number> = {
|
||||
openai: 4,
|
||||
|
|
@ -77,6 +78,7 @@ const PROVIDER_STOP_MAX: Record<string, number> = {
|
|||
kimi: 5,
|
||||
deepseek: 16,
|
||||
mistral: 16,
|
||||
openrouter: 4,
|
||||
};
|
||||
|
||||
export function getProviderStopMax(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue