from __future__ import annotations import os from dataclasses import dataclass from pathlib import Path from dotenv import load_dotenv ROOT_DIR = Path(__file__).resolve().parents[2] load_dotenv(ROOT_DIR.parent / ".env") load_dotenv(ROOT_DIR / ".env") def _bool(name: str, default: bool = False) -> bool: """读取常见布尔环境变量写法。""" value = os.getenv(name) if value is None: return default return value.strip().lower() in {"1", "true", "yes", "on"} @dataclass(frozen=True) class Settings: """集中管理服务、模型、存储和可选适配器配置。""" app_env: str = os.getenv("APP_ENV", "development") workspace_id: str = os.getenv("WORKSPACE_ID", "local-workspace") data_dir: Path = Path(os.getenv("DATA_DIR", str(ROOT_DIR / "data"))) demo_fallback: bool = _bool("DEMO_FALLBACK", True) llm_base_url: str = os.getenv("LLM_BASE_URL", "https://api.openai.com/v1").rstrip("/") llm_api_key: str = os.getenv("LLM_API_KEY", "") llm_model: str = os.getenv("LLM_MODEL", "gpt-4o-mini") embedding_base_url: str = os.getenv("EMBEDDING_BASE_URL", "https://api.openai.com/v1").rstrip("/") embedding_api_key: str = os.getenv("EMBEDDING_API_KEY", "") embedding_model: str = os.getenv("EMBEDDING_MODEL", "text-embedding-3-small") embedding_dimensions: int = int(os.getenv("EMBEDDING_DIMENSIONS", "1536")) embedding_min_score: float = float(os.getenv("EMBEDDING_MIN_SCORE", "0.35")) database_url: str = os.getenv( "DATABASE_URL", "postgresql://memory:memory@localhost:54329/memory_agents", ) redis_url: str = os.getenv("REDIS_URL", "redis://localhost:6379/0") letta_base_url: str = os.getenv("LETTA_BASE_URL", "http://localhost:8283").rstrip("/") letta_api_key: str = os.getenv("LETTA_API_KEY", "") letta_enabled: bool = _bool("LETTA_ENABLED") mem0_enabled: bool = _bool("MEM0_ENABLED") reme_enabled: bool = _bool("REME_ENABLED") memu_enabled: bool = _bool("MEMU_ENABLED") settings = Settings() if not 0.0 <= settings.embedding_min_score <= 1.0: raise ValueError("EMBEDDING_MIN_SCORE 必须在 0 到 1 之间") settings.data_dir.mkdir(parents=True, exist_ok=True) # 可选 SDK 通常只识别 OpenAI 标准变量,这里把项目配置同步给它们。 if settings.llm_api_key: os.environ.setdefault("OPENAI_API_KEY", settings.llm_api_key) os.environ.setdefault("DEEPSEEK_API_KEY", settings.llm_api_key) if settings.llm_base_url: os.environ.setdefault("OPENAI_BASE_URL", settings.llm_base_url) os.environ.setdefault("OPENAI_API_BASE", settings.llm_base_url) os.environ.setdefault("LLM_BACKEND", "openai") os.environ.setdefault("LLM_API_KEY", settings.llm_api_key) os.environ.setdefault("LLM_BASE_URL", settings.llm_base_url) os.environ.setdefault("LLM_MODEL_NAME", settings.llm_model)