from __future__ import annotations from functools import lru_cache import os from pathlib import Path from typing import Optional from pydantic_settings import BaseSettings, SettingsConfigDict def _apply_local_supabase_env() -> None: """ 优先加载本地 .env 中的 Supabase 配置,避免宿主环境遗留的线上变量导致鉴权失败。 仅覆盖 SUPABASE_* 相关键。 """ env_path = Path(__file__).resolve().parents[1] / ".env" if not env_path.exists(): return content = env_path.read_text(encoding="utf-8").splitlines() kv: dict[str, str] = {} for line in content: stripped = line.strip() if not stripped or stripped.startswith("#") or "=" not in stripped: continue key, value = stripped.split("=", 1) kv[key.strip()] = value.strip() for key in ("SUPABASE_URL", "SUPABASE_SERVICE_ROLE_KEY", "SUPABASE_ANON_KEY"): file_value = kv.get(key) if not file_value: continue os.environ[key] = file_value _apply_local_supabase_env() class Settings(BaseSettings): """集中管理项目配置,来源于 .env / 环境变量。""" model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore") supabase_url: str supabase_anon_key: Optional[str] = None supabase_service_role_key: str redis_url: str = "redis://localhost:6379/0" frontend_url: str = "http://localhost:3000" openai_api_key: str = "" lightrag_db_url: str lightrag_collection: str = "wolai-docs" lightrag_llm_model: str = "qwen3:32b" lightrag_embedding_model: str = "qwen3-embedding:8b" lightrag_rerank_model: str = "dengcao/Qwen3-Reranker-4B:Q5_K_M" ollama_base_url: str = "http://127.0.0.1:11434" lightrag_embedding_dim: int = 4096 deepseek_api_key: str = "" deepseek_base_url: str = "https://api.deepseek.com" deepseek_model: str = "deepseek-chat" searxng_base_url: Optional[str] = None searxng_api_token: Optional[str] = None @lru_cache def get_settings() -> Settings: """惰性实例化设置,避免重复读取文件。""" return Settings() settings = get_settings()