providers: presets for polza/openai/ollama (--provider), keys from env, gpt-5.6-luna default for polza, multimodal heuristic for cloud ids
This commit is contained in:
+92
-1
@@ -67,6 +67,97 @@ NUDGE = (
|
||||
"then call a tool (turn or move, or interact if within 1.6 m)."
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Provider presets (OpenAI-compatible endpoints)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
PROVIDERS: dict[str, dict[str, str | None]] = {
|
||||
"polza": {
|
||||
"base_url": "https://polza.ai/api/v1",
|
||||
"env_key": "POLZA_API_KEY",
|
||||
"default_model": "openai/gpt-5.6-luna",
|
||||
},
|
||||
"openai": {
|
||||
"base_url": "https://api.openai.com/v1",
|
||||
"env_key": "OPENAI_API_KEY",
|
||||
"default_model": "gpt-4o-mini",
|
||||
},
|
||||
"ollama": {
|
||||
"base_url": "http://localhost:11434/v1",
|
||||
"env_key": None,
|
||||
"default_model": "gemma4:e2b",
|
||||
},
|
||||
}
|
||||
|
||||
# Best-effort multimodal detection for non-ollama providers (no way to
|
||||
# introspect remotely): ids carrying these markers usually accept images.
|
||||
_MULTIMODAL_HINTS = (
|
||||
"gpt-4o",
|
||||
"gpt-4.1",
|
||||
"gpt-5",
|
||||
"gemma",
|
||||
"gemini",
|
||||
"claude",
|
||||
"vl-",
|
||||
"vision",
|
||||
"luna",
|
||||
)
|
||||
|
||||
|
||||
def resolve_provider(
|
||||
*,
|
||||
provider: str | None,
|
||||
base_url: str | None,
|
||||
api_key: str | None,
|
||||
model: str | None,
|
||||
) -> tuple[str, str, str]:
|
||||
"""Resolve endpoint + key + model from a provider preset (or explicit args).
|
||||
|
||||
Keys come from the environment (POLZA_API_KEY / OPENAI_API_KEY) so nothing
|
||||
secret lives in the repo or on the command line.
|
||||
"""
|
||||
import os
|
||||
|
||||
if provider:
|
||||
preset = PROVIDERS.get(provider)
|
||||
if preset is None:
|
||||
raise ValueError(
|
||||
f"unknown provider {provider!r}; available: {', '.join(PROVIDERS)}"
|
||||
)
|
||||
base_url = preset["base_url"]
|
||||
if model is None:
|
||||
model = preset["default_model"]
|
||||
env_key = preset["env_key"]
|
||||
if api_key is None and env_key:
|
||||
api_key = os.environ.get(env_key)
|
||||
if api_key is None:
|
||||
raise ValueError(
|
||||
f"provider {provider!r} needs an API key: set ${env_key} "
|
||||
"(see https://polza.ai/dashboard/api-keys)"
|
||||
)
|
||||
else:
|
||||
base_url = base_url or str(PROVIDERS["ollama"]["base_url"])
|
||||
model = model or str(PROVIDERS["ollama"]["default_model"])
|
||||
if api_key is None:
|
||||
host = base_url.replace("http://", "").replace("https://", "").split("/")[0]
|
||||
if "polza" in host:
|
||||
api_key = os.environ.get("POLZA_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError("set $POLZA_API_KEY (polza.ai/dashboard/api-keys)")
|
||||
elif "openai" in host:
|
||||
api_key = os.environ.get("OPENAI_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError("set $OPENAI_API_KEY")
|
||||
else:
|
||||
api_key = "ollama" # local ollama ignores the key
|
||||
return base_url, api_key, model
|
||||
|
||||
|
||||
def looks_multimodal(model: str) -> bool:
|
||||
low = model.lower()
|
||||
return any(h in low for h in _MULTIMODAL_HINTS)
|
||||
|
||||
|
||||
COLOR_NAMES = [
|
||||
("beacon_cyan", (120, 210, 235)),
|
||||
("beacon_yellow", (255, 190, 90)),
|
||||
@@ -236,7 +327,7 @@ class LLMController:
|
||||
self.client = client
|
||||
self.model = model
|
||||
if multimodal is None:
|
||||
multimodal = detect_multimodal(base_url, model)
|
||||
multimodal = looks_multimodal(model) or detect_multimodal(base_url, model)
|
||||
self.multimodal = multimodal
|
||||
# The color-grid digest is the fallback channel for text-only models.
|
||||
# For multimodal models it is off unless explicitly requested.
|
||||
|
||||
Reference in New Issue
Block a user