Files
QMDSearch/app/config.py
T
kplam 6ae91679e2 feat: 接入 BGE-M3 本地嵌入默认配置 + 新增 Qwen3-Reranker 重排
- .env.example 嵌入默认改为本地 BGE-M3(EMBEDDING_PROVIDER=local, dim=1024),NAS 全新部署即用
- 新增 app/services/reranker.py:基于 Ollama /api/rerank 的 cross-encoder 重排服务
- retriever 在 chunk 候选阶段接入语义精排,调用失败优雅降级为 RRF 顺序
- docker-compose 拉取 qwen3-reranker:0.6b,OLLAMA_MAX_LOADED_MODELS 提至 3
- .gitignore 排除 .workbuddy/ 与 .trae/(防止误提交项目记忆与 IDE spec)
- 新增 reranker 单元与集成测试,全量测试 529 passed
2026-08-01 00:08:38 +08:00

93 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""应用配置,通过环境变量注入"""
# 应用
app_name: str = "QMDSearch"
log_level: str = "info"
# 嵌入模型
embedding_provider: str = "local" # openai | local
openai_api_key: str = ""
openai_base_url: str = "https://api.openai.com/v1"
embedding_model: str = "text-embedding-3-small"
# bge-m3(本地 Ollama 嵌入)维度为 1024;切换 openai provider 时需同步改为 1536
embedding_dimension: int = 1024
# Ollama 本地模型(用于文档三级总结)
ollama_base_url: str = "http://localhost:11434"
ollama_model: str = "qwen2.5:1.5b" # 备选: qwen2.5:3b
ollama_embedding_model: str = "bge-m3" # embedding_provider=local 时使用的嵌入模型
# 重排模型(cross-encoder,经 Ollama /api/rerank,对 chunk 候选做最终精排)
# 关闭时检索链路退化为纯 RRF 融合结果,行为不变
reranker_enabled: bool = False
reranker_model: str = "qwen3-reranker:0.6b"
reranker_timeout: float = 30.0
# Qdrant
qdrant_host: str = "localhost"
qdrant_port: int = 6333
# Redis
redis_url: str = "redis://localhost:6379/0"
# 检索参数
retrieval_top_k: int = 20 # L2 语义检索召回数
retrieval_final_k: int = 5 # L3 重排后返回数
# 文档入库参数
summary_min_text_length: int = 500 # 低于此字符数触发 2.5 级回退
# 入库异步任务
ingest_max_concurrency: int = 2 # 入库后台任务并发上限
ingest_task_ttl_done: int = 86400 # 任务状态 Redis 保留秒数(进行中与已完成,24h)
ingest_task_ttl_failed: int = 604800 # 失败任务状态 Redis 保留秒数(7 天)
# 知识分类(taxonomy
taxonomy_path: str = "" # taxonomy JSON 文件路径,为空用内置默认
classify_confidence_threshold: float = 0.6 # 低于此值归 uncategorized
classify_max_categories: int = 3 # query 路由命中类目数上限,超过走全库兜底
# 分层检索参数
l1_doc_top_n: int = 10 # L1 层候选文档数
l2_section_top_n: int = 5 # L2 层候选 section 数
l3_top_n: int = 10 # L3 层定位数
sparse_enabled: bool = True # 是否启用稀疏检索
cache_ttl: int = 300 # Redis 缓存秒数
# 分块参数
chunk_max_chars: int = 800 # chunk 超长二次切分阈值
# 认证(JWT
jwt_secret_key: str = "" # JWT 签名密钥,为空时启动自动生成(仅开发,生产必填)
jwt_algorithm: str = "HS256"
jwt_expire_minutes: int = 1440 # token 有效期(分钟),默认 24 小时
auth_register_enabled: bool = True # 是否开放 POST /auth/register
default_admin_username: str = "admin" # 启动时自动创建的默认管理员用户名
default_admin_password: str = "" # 默认管理员密码,为空则不创建默认管理员
# 文件上传
upload_dir: str = "./uploads" # 原始文件保存目录(相对路径以工作目录为基)
upload_max_size_mb: int = 20 # 单文件大小上限(MB
upload_allowed_extensions: str = (
".txt,.md,.html,.htm,.pdf,.docx" # 允许上传的扩展名(逗号分隔)
)
# PDF OCR(图片型/扫描件降级,pypdf extract_text 为空时触发)
pdf_ocr_enabled: bool = (
True # 是否启用 OCR 降级(关闭则扫描件按"无法提取文本"拒绝入库)
)
pdf_ocr_max_pages: int = 30 # 单文件 OCR 页数上限,超过仅前 N 页
pdf_ocr_dpi: int = 200 # 渲染 DPI(越高越准但越慢,72~300 合理)
# 检索结果 AI 总结
result_summary_max_hits: int = 5 # 参与总结的最大 hit 条数(控制 prompt 长度)
model_config = {"env_prefix": "", "case_sensitive": False}
settings = Settings()