Files

88 lines
2.9 KiB
Python
Raw Permalink Normal View History

2026-05-13 16:43:53 +08:00
import os
2026-03-28 01:01:13 +08:00
from typing import Optional, Dict
from nanobot.providers.azure_openai_provider import AzureOpenAIProvider
from nanobot.providers.openai_codex_provider import OpenAICodexProvider
from nanobot.providers.registry import find_by_name
2026-03-28 14:46:50 +08:00
from app.core.patched_openai_compat_provider import PatchedOpenAICompatProvider
2026-03-28 01:01:13 +08:00
def normalize_provider_name(provider: Optional[str]) -> Optional[str]:
if not provider:
return None
normalized = provider.strip().lower()
alias_map = {
"azure": "azure_openai",
"local": "vllm",
}
return alias_map.get(normalized, normalized)
2026-05-13 16:43:53 +08:00
def _running_in_docker() -> bool:
# Best-effort, cross-platform detection.
if os.environ.get("DATACLAW_RUNNING_IN_DOCKER", "").strip().lower() in ("1", "true", "yes", "y"):
return True
return os.path.exists("/.dockerenv")
def _rewrite_localhost_api_base(api_base: Optional[str]) -> Optional[str]:
"""
When running inside Docker, `localhost` points to the container itself.
For host-local LLMs (Ollama/vLLM), users often configure `http://localhost:...`,
which breaks in containers. We rewrite it to `host.docker.internal`.
"""
if not api_base:
return api_base
base = api_base.strip()
if base.startswith("http://localhost") or base.startswith("https://localhost"):
return base.replace("://localhost", "://host.docker.internal", 1)
if base.startswith("http://127.0.0.1") or base.startswith("https://127.0.0.1"):
return base.replace("://127.0.0.1", "://host.docker.internal", 1)
return api_base
2026-03-28 01:01:13 +08:00
def build_llm_provider(
*,
model: str,
provider: Optional[str] = None,
api_key: Optional[str] = None,
api_base: Optional[str] = None,
extra_headers: Optional[Dict[str, str]] = None,
):
provider_name = normalize_provider_name(provider)
spec = find_by_name(provider_name) if provider_name else None
backend = spec.backend if spec else "openai_compat"
2026-05-13 16:43:53 +08:00
if _running_in_docker():
api_base = _rewrite_localhost_api_base(api_base)
2026-03-28 01:01:13 +08:00
if backend == "openai_codex" or model.startswith("openai-codex/"):
return OpenAICodexProvider(default_model=model)
if backend == "azure_openai":
if not api_key or not api_base:
raise ValueError("Azure OpenAI requires api_key and api_base.")
return AzureOpenAIProvider(
api_key=api_key,
api_base=api_base,
default_model=model,
)
if backend == "anthropic":
from nanobot.providers.anthropic_provider import AnthropicProvider
return AnthropicProvider(
api_key=api_key,
api_base=api_base,
default_model=model,
extra_headers=extra_headers,
)
2026-03-28 14:46:50 +08:00
return PatchedOpenAICompatProvider(
2026-03-28 01:01:13 +08:00
api_key=api_key,
api_base=api_base,
default_model=model,
extra_headers=extra_headers,
spec=spec,
)