- Add HF_ENDPOINT configuration option - Set HuggingFace mirror to https://hf-mirror.com - Fix 'cannot connect to huggingface.co' error - Update .env.example with HF_ENDPOINT setting Problem: - RAG engine uses sentence-transformers model - Model download requires connection to huggingface.co - China network cannot access huggingface.co - Error: 'We couldn't connect to https://huggingface.co' Solution: - Add HF_ENDPOINT environment variable support - Use hf-mirror.com as HuggingFace mirror - Set mirror before loading sentence-transformers - Document in .env.example Files: - backend/app/config.py: add HF_ENDPOINT config - backend/app/core/rag_engine.py: set HF_ENDPOINT before model load - backend/setup_hf_mirror.sh: setup script - backend/.env: configure mirror (not tracked)
71 lines
2.0 KiB
Python
71 lines
2.0 KiB
Python
from pydantic_settings import BaseSettings
|
||
from pydantic import ConfigDict, field_validator
|
||
from functools import lru_cache
|
||
from urllib.parse import quote_plus
|
||
|
||
|
||
class Settings(BaseSettings):
|
||
# Application
|
||
APP_NAME: str = "ERP AI Assistant"
|
||
APP_ENV: str = "development"
|
||
DEBUG: bool = True
|
||
SECRET_KEY: str
|
||
|
||
# Database
|
||
DB_DRIVER: str
|
||
DB_SERVER: str
|
||
DB_PORT: int = 1433
|
||
DB_NAME: str
|
||
DB_USER: str
|
||
DB_PASSWORD: str
|
||
|
||
# Claude API
|
||
ANTHROPIC_API_KEY: str
|
||
ANTHROPIC_BASE_URL: str | None = None # Optional custom base URL for proxy/self-hosted
|
||
CLAUDE_MODEL: str = "claude-sonnet-4-6"
|
||
CLAUDE_MAX_TOKENS: int = 8192
|
||
CLAUDE_TEMPERATURE: float = 0.7
|
||
|
||
# Knowledge Base
|
||
KNOWLEDGE_BASE_PATH: str = "./knowledge_base"
|
||
CHROMA_DB_PATH: str = "./knowledge_base/chroma_db"
|
||
EMBEDDING_MODEL: str = "all-MiniLM-L6-v2"
|
||
CHUNK_SIZE: int = 500
|
||
CHUNK_OVERLAP: int = 50
|
||
|
||
# HuggingFace
|
||
HF_ENDPOINT: str | None = None # Optional: HuggingFace mirror endpoint
|
||
|
||
@property
|
||
def DATABASE_URL(self) -> str:
|
||
"""构建数据库连接 URL(密码安全编码)"""
|
||
password = quote_plus(self.DB_PASSWORD)
|
||
return (
|
||
f"mssql+pyodbc://{self.DB_USER}:{password}"
|
||
f"@{self.DB_SERVER}:{self.DB_PORT}/{self.DB_NAME}"
|
||
f"?driver={quote_plus(self.DB_DRIVER)}"
|
||
)
|
||
|
||
@field_validator('CLAUDE_TEMPERATURE')
|
||
@classmethod
|
||
def validate_temperature(cls, v):
|
||
if not 0 <= v <= 2:
|
||
raise ValueError('CLAUDE_TEMPERATURE must be between 0 and 2')
|
||
return v
|
||
|
||
@field_validator('CHUNK_OVERLAP')
|
||
@classmethod
|
||
def validate_chunk_overlap(cls, v, info):
|
||
chunk_size = info.data.get('CHUNK_SIZE', 500)
|
||
if v >= chunk_size:
|
||
raise ValueError('CHUNK_OVERLAP must be less than CHUNK_SIZE')
|
||
return v
|
||
|
||
model_config = ConfigDict(env_file=".env", case_sensitive=True)
|
||
|
||
|
||
@lru_cache()
|
||
def get_settings() -> Settings:
|
||
"""获取配置单例"""
|
||
return Settings()
|