克隆并配置环境变量
cd question-mem-app
cp .env.example .env
生成密钥并填入 .env
# JWT 密钥
openssl rand -base64 32
# AES-256 主密钥(必须 base64 编码的 32 字节)
openssl rand -base64 32
将生成的值填入 .env 的 JWT_SECRET 和 AES_MASTER_KEY。
⚠️ 应用启动时会校验
AES_MASTER_KEY,若为change-me*前缀或长度不对将直接拒绝启动。
启动全部服务
docker compose up -d --build
服务列表:
| 服务 | 端口 | 说明 |
|---|---|---|
| postgres | 5432 | PostgreSQL 16 |
| redis | 6379 | Redis 7 |
| minio | 9000 / 9001 | MinIO API / 控制台 |
| backend | 8000 | FastAPI 后端 |
| worker | — | Celery 解析 worker |
| frontend | 80(nginx) | 前端 SPA |
注意:
docker-compose.yml默认只编排 postgres/redis/minio/backend/worker。前端通过frontend/Dockerfile+nginx.conf独立构建部署。
执行数据库迁移
docker compose exec backend alembic upgrade head
访问应用
http://localhost(nginx 托管)或开发模式 http://localhost:5174http://localhost:8000/api/docshttp://localhost:9001(minioadmin / minioadmin)所有配置通过环境变量管理,后端在 app/core/config.py 中读取 .env 文件。
| 环境变量 | 默认值 | 说明 |
|---|---|---|
DATABASE_URL | postgresql+asyncpg://...@localhost:5432/question_mem | 异步数据库连接串 |
DATABASE_URL_SYNC | postgresql://...@localhost:5432/question_mem | 同步连接串(Celery / Alembic) |
REDIS_URL | redis://localhost:6379/0 | Redis 连接串 |
MINIO_ENDPOINT | 127.0.0.1:9000 | MinIO 地址 |
MINIO_ACCESS_KEY | minioadmin | MinIO 访问键 |
MINIO_SECRET_KEY | minioadmin | MinIO 密钥 |
MINIO_BUCKET | question-mem | MinIO 桶名 |
MINIO_SECURE | False | 是否启用 HTTPS |
STORAGE_MODE | minio | 存储模式:minio 或 local(本地文件系统) |
JWT_SECRET | change-me-in-production | JWT HS256 签名密钥 |
JWT_ALGORITHM | HS256 | JWT 算法 |
JWT_ACCESS_EXPIRE_MINUTES | 15 | 访问令牌有效期(分钟) |
JWT_REFRESH_EXPIRE_DAYS | 7 | 刷新令牌有效期(天) |
AES_MASTER_KEY | change-me-... | AES-256-GCM 主密钥(base64 编码 32 字节,必填) |
OCR_TEXT_THRESHOLD | 50 | PDF 页面文本长度阈值,低于此值触发 OCR |
OLLAMA_BASE_URL | http://localhost:11434 | Ollama 本地大模型地址 |
LLM_CALL_TIMEOUT | 180 | 单次 LLM 结构化调用超时(秒),防止挂起阻塞解析 |
LLM_MAX_RETRIES | 2 | 瞬态错误(超时/网络/限流)最大重试次数,指数退避 |
INITIAL_ADMIN_EMAIL | "" | 首次注册此邮箱的用户自动设为 admin;留空则首个注册用户自动 admin |
ENABLE_PUBLIC_BANKS | True | 公共题库功能开关,False 时不注册 /api/public-banks 路由 |
安全提示:
AES_MASTER_KEY必须是 base64 编码的 32 字节字符串。应用启动时若检测到change-me*前缀或长度不合法将直接抛错拒绝启动。生成命令:openssl rand -base64 32。
大题库(MB 级 PDF)解析涉及多次串行 LLM 调用,相关参数需协同配置以保证稳定性:
| 参数位置 | 参数 | 默认值 | 说明 |
|---|---|---|---|
.env | LLM_CALL_TIMEOUT | 180 | 单次 LLM 调用超时;超时后包装为 RetryableError 触发重试 |
.env | LLM_MAX_RETRIES | 2 | 瞬态错误重试次数,指数退避(1s → 2s → 4s) |
celery_app.py | task_soft_time_limit | 1800 | 软超时(30分钟),触发 SoftTimeLimitExceeded 优雅标记失败 |
celery_app.py | task_time_limit | 2100 | 硬超时(35分钟),强制终止 worker 进程 |
celery_app.py | task_acks_late | True | 任务完成后才 ack,worker 崩溃后任务自动重投 |
解析中断恢复策略:瞬态错误(超时/网络)→ 指数退避重试;输出截断 → 二分拆分块重试;worker 崩溃 →
acks_late触发重投;整体超时 → 优雅标记parse_status="failed"并保留最后进度。