yau-plant-assistant/api/config.py
Claude 34d2ccc576 Scaffold the WRPS plant operations assistant repository
Build spec and host brief carried in from C:\Claude and WRPS/02-env; the
plant model (equipment, tags, alarm bitmask, enums, unit conversions) is
derived from WRPS/04-plc/register-map.csv, WRPS/05-scada/modbus/scada-points.csv
and WRPS-CTL-003.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 13:56:32 +10:00

96 lines
3.8 KiB
Python

"""Configuration, read once from the environment.
Values come from ~/ai/api.env on lin001 (0600, not in Git). .env.example in the
repo root lists every key with no values. Nothing here has a secret default,
and nothing here is ever logged.
"""
from __future__ import annotations
import os
from functools import lru_cache
from pydantic import BaseModel
class Settings(BaseModel):
# --- imh (pending) -----------------------------------------------------
use_fixtures: bool = True
# --- local -------------------------------------------------------------
pghost: str = "pg-ai"
pgport: int = 5432
pgdatabase: str = "plant"
pguser: str = "agent_ro"
pgpassword: str = ""
# --- Azure OpenAI ------------------------------------------------------
azure_openai_endpoint: str = ""
azure_openai_api_key: str = ""
azure_openai_api_version: str = ""
chat_deployment: str = "" # flagship - final prose only
cheap_deployment: str = "" # classifier, entities, tool selection
embed_deployment: str = "" # text-embedding-3-small
# --- behaviour ---------------------------------------------------------
classifier_confidence_threshold: float = 0.7
site_timezone: str = "Australia/Sydney"
max_rows_returned: int = 5000
query_timeout_seconds: int = 30
max_output_tokens: int = 1200
# --- Cube --------------------------------------------------------------
cubejs_api_url: str = "http://cube:4000/cubejs-api/v1"
cubejs_api_secret: str = ""
# --- Langfuse ----------------------------------------------------------
langfuse_host: str = "http://langfuse:3000"
langfuse_public_key: str = ""
langfuse_secret_key: str = ""
def dsn(self) -> str:
"""Postgres DSN. Never log the result - it carries the password."""
return (
f"postgresql://{self.pguser}:{self.pgpassword}"
f"@{self.pghost}:{self.pgport}/{self.pgdatabase}"
)
def redacted(self) -> dict[str, object]:
"""Safe to log and safe to return from /healthz."""
secret = {"pgpassword", "azure_openai_api_key", "cubejs_api_secret",
"langfuse_secret_key"}
return {
k: ("set" if v else "unset") if k in secret else v
for k, v in self.model_dump().items()
}
@lru_cache
def settings() -> Settings:
env = os.environ
return Settings(
use_fixtures=env.get("USE_FIXTURES", "true").lower() == "true",
pghost=env.get("PGHOST", "pg-ai"),
pgport=int(env.get("PGPORT", "5432")),
pgdatabase=env.get("PGDATABASE", "plant"),
pguser=env.get("PGUSER", "agent_ro"),
pgpassword=env.get("PGPASSWORD", ""),
azure_openai_endpoint=env.get("AZURE_OPENAI_ENDPOINT", ""),
azure_openai_api_key=env.get("AZURE_OPENAI_API_KEY", ""),
azure_openai_api_version=env.get("AZURE_OPENAI_API_VERSION", ""),
chat_deployment=env.get("CHAT_DEPLOYMENT", ""),
cheap_deployment=env.get("CHEAP_DEPLOYMENT", ""),
embed_deployment=env.get("EMBED_DEPLOYMENT", ""),
classifier_confidence_threshold=float(
env.get("CLASSIFIER_CONFIDENCE_THRESHOLD", "0.7")
),
site_timezone=env.get("SITE_TIMEZONE", "Australia/Sydney"),
max_rows_returned=int(env.get("MAX_ROWS_RETURNED", "5000")),
query_timeout_seconds=int(env.get("QUERY_TIMEOUT_SECONDS", "30")),
max_output_tokens=int(env.get("MAX_OUTPUT_TOKENS", "1200")),
cubejs_api_url=env.get("CUBEJS_API_URL", "http://cube:4000/cubejs-api/v1"),
cubejs_api_secret=env.get("CUBEJS_API_SECRET", ""),
langfuse_host=env.get("LANGFUSE_HOST", "http://langfuse:3000"),
langfuse_public_key=env.get("LANGFUSE_PUBLIC_KEY", ""),
langfuse_secret_key=env.get("LANGFUSE_SECRET_KEY", ""),
)