2025-12-06 16:47:17 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2025-11-23 10:55:04 +08:00
|
|
|
from functools import lru_cache
|
2025-12-06 16:47:17 +08:00
|
|
|
import os
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
from typing import Optional
|
2025-11-23 10:55:04 +08:00
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
|
|
|
|
|
2025-12-06 16:47:17 +08:00
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
2025-11-23 10:55:04 +08:00
|
|
|
class Settings(BaseSettings):
|
|
|
|
|
"""集中管理项目配置,来源于 .env / 环境变量。"""
|
|
|
|
|
|
|
|
|
|
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
|
|
|
|
|
|
|
|
|
|
supabase_url: str
|
2025-12-06 16:47:17 +08:00
|
|
|
supabase_anon_key: Optional[str] = None
|
2025-11-23 10:55:04 +08:00
|
|
|
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"
|
2025-12-08 19:56:24 +08:00
|
|
|
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
|
2025-11-23 10:55:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache
|
|
|
|
|
def get_settings() -> Settings:
|
|
|
|
|
"""惰性实例化设置,避免重复读取文件。"""
|
|
|
|
|
return Settings()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
settings = get_settings()
|