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:
@@ -7505,3 +7505,56 @@
|
|||||||
[28512300ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
[28512300ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
[28514857ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
[28514857ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
[28518619ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
[28518619ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28523522ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28529061ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28531079ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28533322ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28538120ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28540727ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28546195ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28549179ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28554313ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28559812ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28565254ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28568642ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28571765ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28575218ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28579019ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28581688ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28586866ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28590751ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28591753ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28592754ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28593756ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28594757ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28595761ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28596765ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28597770ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28598784ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28599809ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28600846ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28601947ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28603206ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28604456ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28606503ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28609814ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28612957ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28617768ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28621897ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28626310ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28630569ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28635095ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28640867ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28644270ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28649497ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28654991ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28660090ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28662946ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28665487ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28669449ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28674591ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28679193ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28683363ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28686271ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28688761ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
[28694226ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8001/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8000/:40
|
||||||
|
|||||||
+35
-6
@@ -32,11 +32,14 @@ import sys
|
|||||||
from aicc.client import AICCClient
|
from aicc.client import AICCClient
|
||||||
from aicc.transport.websocket import WebSocketClientTransport
|
from aicc.transport.websocket import WebSocketClientTransport
|
||||||
|
|
||||||
from testbed.llm_agent import CHAT_MISSION, LLMController, ollama_models
|
from testbed.llm_agent import (
|
||||||
|
CHAT_MISSION,
|
||||||
|
LLMController,
|
||||||
|
ollama_models,
|
||||||
|
resolve_provider,
|
||||||
|
)
|
||||||
|
|
||||||
DEFAULT_URL = "ws://127.0.0.1:8765"
|
DEFAULT_URL = "ws://127.0.0.1:8765"
|
||||||
DEFAULT_BASE_URL = "http://localhost:11434/v1"
|
|
||||||
DEFAULT_MODEL = "gemma4:e2b"
|
|
||||||
|
|
||||||
HELP = """\
|
HELP = """\
|
||||||
You are talking to the capsule's brain (LLM). Type what you want, e.g.:
|
You are talking to the capsule's brain (LLM). Type what you want, e.g.:
|
||||||
@@ -393,12 +396,26 @@ def main() -> int:
|
|||||||
help=f"bridge WebSocket URL (default {DEFAULT_URL})",
|
help=f"bridge WebSocket URL (default {DEFAULT_URL})",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--base-url", default=DEFAULT_BASE_URL, help="OpenAI-compatible endpoint"
|
"--base-url",
|
||||||
|
default=None,
|
||||||
|
help="OpenAI-compatible endpoint (default per --provider)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--model", default=DEFAULT_MODEL, help="model id on the endpoint"
|
"--provider",
|
||||||
|
choices=["polza", "openai", "ollama"],
|
||||||
|
default=None,
|
||||||
|
help="provider preset: endpoint + key from env (POLZA_API_KEY/OPENAI_API_KEY)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--model",
|
||||||
|
default=None,
|
||||||
|
help="model id on the endpoint (default per provider: polza -> openai/gpt-5.6-luna)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--api-key",
|
||||||
|
default=None,
|
||||||
|
help="API key (default: $POLZA_API_KEY / $OPENAI_API_KEY per provider)",
|
||||||
)
|
)
|
||||||
parser.add_argument("--api-key", default="ollama", help="API key for the endpoint")
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--auto-steps",
|
"--auto-steps",
|
||||||
type=int,
|
type=int,
|
||||||
@@ -447,6 +464,18 @@ def main() -> int:
|
|||||||
help="attach a fresh camera frame every N turns (0 disables; default 3)",
|
help="attach a fresh camera frame every N turns (0 disables; default 3)",
|
||||||
)
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
args.base_url, args.api_key, args.model = resolve_provider(
|
||||||
|
provider=args.provider,
|
||||||
|
base_url=args.base_url,
|
||||||
|
api_key=args.api_key,
|
||||||
|
model=args.model,
|
||||||
|
)
|
||||||
|
if args.provider:
|
||||||
|
print(f"[chat] provider: {args.provider} -> {args.base_url} model: {args.model}")
|
||||||
|
except ValueError as exc:
|
||||||
|
print(f"[chat] {exc}")
|
||||||
|
return 1
|
||||||
try:
|
try:
|
||||||
return asyncio.run(run(args))
|
return asyncio.run(run(args))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|||||||
+31
-5
@@ -37,9 +37,9 @@ from aicc.protocol import SessionInit
|
|||||||
from aicc.transport.websocket import WebSocketClientTransport
|
from aicc.transport.websocket import WebSocketClientTransport
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
|
from testbed.llm_agent import resolve_provider
|
||||||
|
|
||||||
DEFAULT_URL = "ws://127.0.0.1:8765"
|
DEFAULT_URL = "ws://127.0.0.1:8765"
|
||||||
DEFAULT_BASE_URL = "http://localhost:11434/v1"
|
|
||||||
DEFAULT_MODEL = "gemma4:e2b"
|
|
||||||
|
|
||||||
|
|
||||||
class FrameRecorder:
|
class FrameRecorder:
|
||||||
@@ -392,12 +392,26 @@ def main() -> int:
|
|||||||
help="agent driver (default auto: LLM if reachable, else scripted)",
|
help="agent driver (default auto: LLM if reachable, else scripted)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--base-url", default=DEFAULT_BASE_URL, help="OpenAI-compatible endpoint"
|
"--base-url",
|
||||||
|
default=None,
|
||||||
|
help="OpenAI-compatible endpoint (default per --provider)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--model", default=DEFAULT_MODEL, help="model id on the endpoint"
|
"--provider",
|
||||||
|
choices=["polza", "openai", "ollama"],
|
||||||
|
default=None,
|
||||||
|
help="provider preset: endpoint + key from env (POLZA_API_KEY/OPENAI_API_KEY)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--model",
|
||||||
|
default=None,
|
||||||
|
help="model id on the endpoint (default per provider: polza -> openai/gpt-5.6-luna)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--api-key",
|
||||||
|
default=None,
|
||||||
|
help="API key (default: $POLZA_API_KEY / $OPENAI_API_KEY per provider)",
|
||||||
)
|
)
|
||||||
parser.add_argument("--api-key", default="ollama", help="API key for the endpoint")
|
|
||||||
parser.add_argument("--max-steps", type=int, default=60, help="max agent steps")
|
parser.add_argument("--max-steps", type=int, default=60, help="max agent steps")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--vision",
|
"--vision",
|
||||||
@@ -429,6 +443,18 @@ def main() -> int:
|
|||||||
"into this directory, plus demo.gif animation and demo_summary.png",
|
"into this directory, plus demo.gif animation and demo_summary.png",
|
||||||
)
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
args.base_url, args.api_key, args.model = resolve_provider(
|
||||||
|
provider=args.provider,
|
||||||
|
base_url=args.base_url,
|
||||||
|
api_key=args.api_key,
|
||||||
|
model=args.model,
|
||||||
|
)
|
||||||
|
if args.provider:
|
||||||
|
print(f"[demo] provider: {args.provider} -> {args.base_url} model: {args.model}")
|
||||||
|
except ValueError as exc:
|
||||||
|
print(f"[demo] {exc}")
|
||||||
|
return 1
|
||||||
try:
|
try:
|
||||||
summary = asyncio.run(run_demo(args))
|
summary = asyncio.run(run_demo(args))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|||||||
+92
-1
@@ -67,6 +67,97 @@ NUDGE = (
|
|||||||
"then call a tool (turn or move, or interact if within 1.6 m)."
|
"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 = [
|
COLOR_NAMES = [
|
||||||
("beacon_cyan", (120, 210, 235)),
|
("beacon_cyan", (120, 210, 235)),
|
||||||
("beacon_yellow", (255, 190, 90)),
|
("beacon_yellow", (255, 190, 90)),
|
||||||
@@ -236,7 +327,7 @@ class LLMController:
|
|||||||
self.client = client
|
self.client = client
|
||||||
self.model = model
|
self.model = model
|
||||||
if multimodal is None:
|
if multimodal is None:
|
||||||
multimodal = detect_multimodal(base_url, model)
|
multimodal = looks_multimodal(model) or detect_multimodal(base_url, model)
|
||||||
self.multimodal = multimodal
|
self.multimodal = multimodal
|
||||||
# The color-grid digest is the fallback channel for text-only models.
|
# The color-grid digest is the fallback channel for text-only models.
|
||||||
# For multimodal models it is off unless explicitly requested.
|
# For multimodal models it is off unless explicitly requested.
|
||||||
|
|||||||
Reference in New Issue
Block a user