forked from retoor/devplacepy
Let the gateway target non-OpenAI upstreams and allow client model passthrough
gateway_thinking_dialect overrides the URL-sniffed protocol dialect for a reverse-proxied upstream (e.g. Ollama) whose URL carries no identifying token; upstream_capabilities() uses the same effective dialect to stop sending stream_options to upstreams that don't support it. gateway_allow_client_model lets a client-requested model name through even with force-model on, for an upstream that serves many models with no single stable alias. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjW4qocnaJxhugUi5ca8Wo
This commit is contained in:
@@ -942,6 +942,107 @@ class FakeClientWithUsage_openai_gateway(FakeClient_openai_gateway):
|
||||
)
|
||||
|
||||
|
||||
def test_ollama_stream_does_not_send_stream_options(local_db, monkeypatch):
|
||||
monkeypatch.setattr(gwmod.httpx, "AsyncClient", FakeClient_openai_gateway)
|
||||
svc = GatewayService()
|
||||
cfg = svc.effective_config()
|
||||
cfg["gateway_upstream_url"] = "http://127.0.0.1:11434/api/chat"
|
||||
rt = svc.runtime()
|
||||
run_async(
|
||||
rt.handle_chat(
|
||||
{
|
||||
"messages": [{"role": "user", "content": "hi"}],
|
||||
"stream": True,
|
||||
"stream_options": {"include_usage": True},
|
||||
},
|
||||
cfg,
|
||||
("guest", "ollama_stream_opts"),
|
||||
"test",
|
||||
"default",
|
||||
)
|
||||
)
|
||||
upstream_payload = rt._client.calls[-1][1]
|
||||
assert upstream_payload["stream"] is True
|
||||
assert "stream_options" not in upstream_payload
|
||||
assert upstream_payload["think"] is False
|
||||
|
||||
|
||||
def test_ollama_explicit_dialect_overrides_url(local_db, monkeypatch):
|
||||
monkeypatch.setattr(gwmod.httpx, "AsyncClient", FakeClient_openai_gateway)
|
||||
svc = GatewayService()
|
||||
cfg = svc.effective_config()
|
||||
cfg["gateway_upstream_url"] = "https://ai.example.com/v1/chat/completions"
|
||||
cfg["gateway_thinking_dialect"] = "ollama"
|
||||
rt = svc.runtime()
|
||||
run_async(
|
||||
rt.handle_chat(
|
||||
{"messages": [{"role": "user", "content": "hi"}]},
|
||||
cfg,
|
||||
("guest", "ollama_dialect_override"),
|
||||
"test",
|
||||
"default",
|
||||
)
|
||||
)
|
||||
body = rt._client.calls[-1][1]
|
||||
assert body["think"] is False
|
||||
assert "thinking" not in body
|
||||
|
||||
|
||||
def test_client_model_allowed_when_allow_client_model_on(local_db, monkeypatch):
|
||||
monkeypatch.setattr(gwmod.httpx, "AsyncClient", FakeClient_openai_gateway)
|
||||
svc = GatewayService()
|
||||
cfg = svc.effective_config()
|
||||
cfg["gateway_force_model"] = True
|
||||
cfg["gateway_allow_client_model"] = True
|
||||
cfg["gateway_model"] = "deepseek-chat"
|
||||
rt = svc.runtime()
|
||||
run_async(
|
||||
rt.handle_chat(
|
||||
{"model": "llama3.2", "messages": [{"role": "user", "content": "hi"}]},
|
||||
cfg,
|
||||
("guest", "client_model"),
|
||||
"test",
|
||||
"default",
|
||||
)
|
||||
)
|
||||
assert rt._client.calls[-1][1]["model"] == "llama3.2"
|
||||
|
||||
|
||||
def test_molodetz_alias_still_remapped_with_allow_client_model(local_db, monkeypatch):
|
||||
from devplacepy.services.openai_gateway import routing
|
||||
|
||||
monkeypatch.setattr(gwmod.httpx, "AsyncClient", FakeClient_openai_gateway)
|
||||
original = routing.model_store.get("molodetz")
|
||||
routing.model_store.remove("molodetz")
|
||||
try:
|
||||
svc = GatewayService()
|
||||
cfg = svc.effective_config()
|
||||
cfg["gateway_force_model"] = True
|
||||
cfg["gateway_allow_client_model"] = True
|
||||
cfg["gateway_model"] = "deepseek-chat"
|
||||
rt = svc.runtime()
|
||||
run_async(
|
||||
rt.handle_chat(
|
||||
{"model": "molodetz", "messages": [{"role": "user", "content": "hi"}]},
|
||||
cfg,
|
||||
("guest", "molodetz_alias"),
|
||||
"test",
|
||||
"default",
|
||||
)
|
||||
)
|
||||
assert rt._client.calls[-1][1]["model"] == "deepseek-chat"
|
||||
finally:
|
||||
if original is not None:
|
||||
routing.model_store.set(
|
||||
routing.ModelRouteIn(
|
||||
**{
|
||||
field: getattr(original, field)
|
||||
for field in routing.ModelRouteIn.model_fields
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_stream_forwarded_to_upstream_with_forced_include_usage(local_db, monkeypatch):
|
||||
monkeypatch.setattr(gwmod.httpx, "AsyncClient", FakeClient_openai_gateway)
|
||||
svc = GatewayService()
|
||||
|
||||
Reference in New Issue
Block a user