Spaces:
Running
Running
| """全局配置:从环境变量加载(pydantic-settings)。 | |
| 简化点(相比原 Netlify 版): | |
| - 不再支持 XTC_PROVIDER_N_* 多槽位环境变量,仅用 GEMINI/OPENAI 做种子 | |
| - 不再支持配置加密(XTC_CONFIG_CRYPT_KEY) | |
| - 不再支持 XTC_CONFIG_ENV_ONLY / XTC_ADMIN_REQUIRE_KEY_ON_PAGE / XTC_ACCESS_SHORT_KEY / XTC_ACCESS_PIN | |
| - 不再支持 Edge 路径与三段式 env 读取 | |
| - 新增 XTC_JWT_SECRET 用于签发临时令牌 | |
| - 存储主体为持久卷(/data/xtc.db);配置文件额外通过 HF Hub dataset 仓库做备份 | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from functools import lru_cache | |
| from typing import List, Optional | |
| from pydantic import Field, field_validator | |
| from pydantic_settings import BaseSettings, SettingsConfigDict | |
| def _split_key_list(value: Optional[str]) -> List[str]: | |
| if not value: | |
| return [] | |
| out = [] | |
| for item in str(value).replace("\n", ",").replace(";", ",").split(","): | |
| s = item.strip() | |
| if s: | |
| out.append(s) | |
| return list(dict.fromkeys(out)) # 去重保序 | |
| class Settings(BaseSettings): | |
| model_config = SettingsConfigDict( | |
| env_file=".env", | |
| env_file_encoding="utf-8", | |
| extra="ignore", | |
| case_sensitive=False, | |
| ) | |
| # ===== 鉴权 ===== | |
| xtc_admin_key: str = Field(default="", alias="XTC_ADMIN_KEY") | |
| xtc_access_key: str = Field(default="", alias="XTC_ACCESS_KEY") | |
| xtc_jwt_secret: str = Field(default="", alias="XTC_JWT_SECRET") | |
| # ===== 紧急开关 ===== | |
| xtc_disable_admin: bool = Field(default=False, alias="XTC_DISABLE_ADMIN") | |
| # ===== /admin 页面访问门禁(可选)===== | |
| # 配置后访问 /admin 必须携带 ?k=<token> 才能进入登录页, | |
| # 否则返回 404 伪装该路径不存在。未配置时 /admin 行为不变。 | |
| # 注意:此为页面门禁,/admin/api/* 仍由 XTC_ADMIN_KEY 鉴权。 | |
| xtc_admin_access_token: str = Field(default="", alias="XTC_ADMIN_ACCESS_TOKEN") | |
| # ===== 种子厂商 ===== | |
| gemini_api_key: str = Field(default="", alias="GEMINI_API_KEY") | |
| openai_api_key: str = Field(default="", alias="OPENAI_API_KEY") | |
| openai_base_url: str = Field(default="https://api.openai.com", alias="OPENAI_BASE_URL") | |
| # ===== 超时 ===== | |
| upstream_timeout_ms: int = Field(default=120000, alias="UPSTREAM_TIMEOUT_MS") | |
| upstream_stream_timeout_ms: int = Field(default=120000, alias="UPSTREAM_STREAM_TIMEOUT_MS") | |
| # ===== HF Hub 配置备份(可选)===== | |
| # 配置文件通过 HF Hub dataset 仓库做持久化备份,解决免费档磁盘 ephemeral 问题 | |
| # 未配置时降级为纯本地存储(功能正常,只是 restart/stop 后配置会丢失) | |
| hf_token: str = Field(default="", alias="HF_TOKEN") | |
| hf_config_repo: str = Field(default="", alias="HF_CONFIG_REPO") | |
| # ===== 临时令牌 ===== | |
| xtc_access_token_ttl_sec: int = Field(default=1800, alias="XTC_ACCESS_TOKEN_TTL_SEC") | |
| xtc_access_token_length: int = Field(default=8, alias="XTC_ACCESS_TOKEN_LENGTH") | |
| # ===== 运行 ===== | |
| port: int = Field(default=7860, alias="PORT") | |
| # ===== 数据库路径 ===== | |
| db_path: str = Field(default="/data/xtc.db", alias="XTC_DB_PATH") | |
| def _clamp_token_length(cls, v: int) -> int: | |
| return max(6, min(24, v)) | |
| def _clamp_token_ttl(cls, v: int) -> int: | |
| return max(60, min(86400, v)) | |
| def gemini_api_keys(self) -> List[str]: | |
| # 兼容 GEMINI_API_KEYS(逗号分隔) | |
| return _split_key_list(os.environ.get("GEMINI_API_KEYS")) or _split_key_list(self.gemini_api_key) | |
| def openai_api_keys(self) -> List[str]: | |
| return _split_key_list(os.environ.get("OPENAI_API_KEYS")) or _split_key_list(self.openai_api_key) | |
| def is_admin_enabled(self) -> bool: | |
| return not self.xtc_disable_admin | |
| def has_admin_key(self) -> bool: | |
| return bool(self.xtc_admin_key) | |
| def has_admin_access_token(self) -> bool: | |
| return bool(self.xtc_admin_access_token) | |
| def has_access_key(self) -> bool: | |
| return bool(self.xtc_access_key) | |
| def has_jwt_secret(self) -> bool: | |
| return bool(self.xtc_jwt_secret) | |
| def get_settings() -> Settings: | |
| return Settings() | |
| # Gemini 上游地址(固定) | |
| GEMINI_BASE_URL = "https://generativelanguage.googleapis.com" | |
| GEMINI_API_VERSION = "v1beta" | |
| GEMINI_API_CLIENT = "google-genai-sdk/1.34.0" | |
| GEMINI_DEFAULT_MODEL = "gemini-flash-latest" | |
| GEMINI_DEFAULT_EMBEDDINGS_MODEL = "gemini-embedding-001" | |
| # RR 计数器数据库 key 前缀 | |
| RR_KEY_PREFIX = "rr:provider:" | |
| # 伪流式会话 TTL | |
| PSEUDO_SESSION_TTL_SEC = 10 * 60 | |
| # 模型列表缓存 TTL | |
| MODELS_CACHE_TTL_SEC = 30 | |