Constraint resolver: aggregate mass/footprint across a combo instead of pairwise-only checks, treat medium/atmosphere as agreement not supply/demand, reduce multi-provider checks by best/sum instead of AND-ing every provider, fail closed on unrecognized mutex values, add a propulsion-viability (thrust-to-weight) rule. Seed data updated to match (nuclear/solar-sail footprint floors, water-medium exclusions, explicit ground/gravity providers). Domain metric units were stored globally per metric name instead of per-domain, silently corrupting cost_efficiency for every domain but the first one seeded — fixed with a schema migration. Stub estimator's cost_efficiency/safety/availability/reliability were a backwards formula and flat constants; replaced with heuristics grounded in each entity's thrust_profile/energy_form/infrastructure. LLM estimate_physics() now receives each metric's unit and expected range instead of a bare name, fixing wildly miscalibrated estimates traced back to the prompt's own hardcoded example anchoring the model to the wrong order of magnitude. Sharpened the safety-estimation and plausibility-review prompts. Deduped provider parsing logic into llm/parsing.py. Web pipeline form can now pick an LLM provider per run instead of only via server env var. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
47 lines
1.8 KiB
Python
47 lines
1.8 KiB
Python
"""Build an LLMProvider from environment variables."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from physcom.llm.base import LLMProvider
|
|
|
|
|
|
def build_llm_provider(
|
|
provider: str | None = None,
|
|
model: str | None = None,
|
|
host: str | None = None,
|
|
) -> LLMProvider | None:
|
|
"""Return an LLMProvider, or None if not configured.
|
|
|
|
Explicit args (e.g. from a per-request web form) override env vars;
|
|
passing nothing falls back to the env-var-only behavior below.
|
|
|
|
LLM_PROVIDER — provider name ('gemini', 'ollama'; more can be added)
|
|
GEMINI_API_KEY — required when provider is 'gemini' (server env only,
|
|
never accepted as a request param)
|
|
GEMINI_MODEL — optional Gemini model name (default: gemini-2.0-flash)
|
|
OLLAMA_MODEL — optional Ollama model name (default: qwen2.5:7b)
|
|
OLLAMA_HOST — optional Ollama server URL (default: http://localhost:11434)
|
|
"""
|
|
provider = (provider or os.environ.get("LLM_PROVIDER", "")).lower().strip()
|
|
|
|
if not provider or provider == "stub":
|
|
return None
|
|
|
|
if provider == "gemini":
|
|
api_key = os.environ.get("GEMINI_API_KEY", "")
|
|
if not api_key:
|
|
raise ValueError("Gemini requires GEMINI_API_KEY to be set in the server environment")
|
|
model = model or os.environ.get("GEMINI_MODEL", "gemini-2.0-flash")
|
|
from physcom.llm.providers.gemini import GeminiLLMProvider
|
|
return GeminiLLMProvider(api_key=api_key, model=model)
|
|
|
|
if provider == "ollama":
|
|
model = model or os.environ.get("OLLAMA_MODEL", "qwen2.5:7b")
|
|
host = host or os.environ.get("OLLAMA_HOST", "http://localhost:11434")
|
|
from physcom.llm.providers.ollama import OllamaLLMProvider
|
|
return OllamaLLMProvider(model=model, host=host)
|
|
|
|
raise ValueError(f"Unknown LLM provider: {provider!r}. Supported: gemini, ollama, stub")
|