diff --git a/README.md b/README.md index 21e6dd3..721415f 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,11 @@ ![Python](https://img.shields.io/badge/python-3.11-blue.svg) ![FastAPI](https://img.shields.io/badge/FastAPI-0.109.0-green.svg) ![React](https://img.shields.io/badge/react-18.3.1-blue.svg) -![TypeScript](https://img.shields.io/badge/typescript-5.9.3-blue.svg) ![License](https://img.shields.io/badge/license-GPL%20v3-blue.svg) -**一款基于 AI 的智能小说创作助手,帮助你轻松创作精彩故事** +**基于 AI 的智能小说创作助手** -[特性](#-特性) • [快速开始](#-快速开始) • [部署方式](#-部署方式) • [配置说明](#%EF%B8%8F-配置说明) • [项目结构](#-项目结构) +[特性](#-特性) • [快速开始](#-快速开始) • [配置说明](#%EF%B8%8F-配置说明) • [项目结构](#-项目结构) @@ -19,42 +18,37 @@ ## ✨ 特性 -- 🤖 **多 AI 模型支持** - 支持 OpenAI、Google Gemini、Anthropic Claude 等主流 AI 模型 -- 📝 **智能向导** - 通过向导式引导快速创建小说项目,AI 自动生成大纲、角色和世界观 -- 👥 **角色管理** - 创建和管理小说角色,包括人物关系、组织架构等 -- 📖 **章节编辑** - 支持章节的创建、编辑、重新生成和润色功能 -- 🌐 **世界观设定** - 构建完整的故事世界观和背景设定 -- 🔐 **多种登录方式** - 支持 LinuxDO OAuth 登录和本地账户登录 -- 🐳 **Docker 部署** - 一键部署,开箱即用 -- 💾 **数据持久化** - 支持 PostgreSQL 和 SQLite 双数据库,多用户数据隔离 -- 🎨 **现代化 UI** - 基于 Ant Design 的美观界面,响应式设计 - +- 🤖 **多 AI 模型** - 支持 OpenAI、Gemini、Claude 等主流模型 +- 📝 **智能向导** - AI 自动生成大纲、角色和世界观 +- 👥 **角色管理** - 人物关系、组织架构可视化管理 +- 📖 **章节编辑** - 支持创建、编辑、重新生成和润色 +- 🌐 **世界观设定** - 构建完整的故事背景 +- 🔐 **多种登录** - LinuxDO OAuth 或本地账户登录 +- 💾 **PostgreSQL** - 生产级数据库,多用户数据隔离 +- 🐳 **Docker 部署** - 一键启动,开箱即用 ## 📋 TODO List -以下是正在规划和开发中的功能: +- [ ] **灵感模式** - 创作灵感和点子生成 +- [x] **自定义写作风格** - 支持自定义 AI 写作风格 +- [x] **数据导入导出** - 项目数据的导入导出 +- [ ] **Prompt 调整界面** - 可视化编辑 Prompt 模板 +- [x] **章节字数限制** - 用户可设置生成字数 +- [ ] **设定追溯与矛盾检测** - 自动检测设定冲突 +- [ ] **思维链与章节关系图谱** - 可视化章节逻辑关系 +- [x] **根据分析一键重写** - 根据分析建议重新生成 +- [x] **Linux DO 自动创建账号** - OAuth 登录自动生成账号 -- [ ] **灵感模式** - 提供创作灵感和点子生成功能 -- [✔] **自定义写作风格** - 支持自定义AI写作风格和语言风格 -- [✔] **支持数据导入导出** - 支持项目数据的导入和导出功能 -- [ ] **添加prompt调整界面** - 提供可视化的prompt模板编辑和调整界面 -- [✔] **开放章节内容字数限制** - 支持用户在生成章节内容时设置字数 @wyf007 -- [ ] **设定追溯与矛盾检测** - 对大纲、世界观、角色档案中的设定支持悬停查看注释,显示相关章节来源和佐证原文;自动检测新章节与已有设定的矛盾(吃书),标记为"矛盾"设定并提供解决建议,当新设定解决矛盾后自动更新注释说明 @lulujiang -- [ ] **思维链与章节关系图谱** - 为每章建立思维链,总结与上文的逻辑关系、明暗线发展;可选的章节关系满图功能,自动识别和标注伏笔埋设与揭晓、角色出场与呼应等内在联系,帮助提升小说结构的紧密性和连贯性 @lulujiang -- [ ] **根据分析建议一键重写** - 根据分析的的建议,实现一键重新生成章节内容 -- [ ] **Linux DO登录自动创建账号** - 使用Linux DO登录后,自动生成系统账号 - -> 💡 如果你有其他功能建议,欢迎提交 Issue 或 Pull Request! +> 💡 欢迎提交 Issue 或 Pull Request! ## 🚀 快速开始 ### 前置要求 -- **Docker 部署**:Docker 和 Docker Compose -- **本地开发**:Python 3.11+ 和 Node.js 18+ -- **必需**:至少一个 AI 服务的 API Key(OpenAI/Gemini/Anthropic) +- Docker 和 Docker Compose +- 至少一个 AI 服务的 API Key(OpenAI/Gemini/Claude) -### 方式一:从源码构建 Docker 镜像 +### Docker Compose 部署(推荐) ```bash # 1. 克隆项目 @@ -63,142 +57,136 @@ cd MuMuAINovel # 2. 配置环境变量 cp backend/.env.example .env -# 编辑 .env 文件,填入你的 API Keys +# 编辑 .env 文件,填入必要配置 -# 3. 启动服务(会自动构建镜像) +# 3. 启动服务 docker-compose up -d # 4. 访问应用 # 打开浏览器访问 http://localhost:8000 ``` -### 方式二:本地开发 - -#### 后端设置 +### 使用 Docker Hub 镜像 + +```bash +# 拉取最新镜像 +docker pull mumujie/mumuainovel:latest + +# 使用 docker-compose.yml 启动 +docker-compose up -d + +# 查看日志 +docker-compose logs -f + +# 更新到最新版本 +docker-compose pull +docker-compose up -d +``` + +### 本地开发 + +#### 后端 ```bash -# 进入后端目录 cd backend - -# 创建虚拟环境 python -m venv .venv - -# 激活虚拟环境 -# Windows: -.venv\Scripts\activate -# Linux/Mac: -source .venv/bin/activate - -# 安装依赖 +source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt -# 配置环境变量 +# 配置 .env 文件 cp .env.example .env -# 编辑 .env 文件,填入你的配置 -# 启动后端服务 +# 启动后端 python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload ``` -#### 前端设置 +#### 前端 ```bash -# 进入前端目录 cd frontend - -# 安装依赖 npm install - -# 开发模式(需要后端已启动) -npm run dev - -# 或构建生产版本 -npm run build +npm run dev # 开发模式 +npm run build # 生产构建 ``` -## 🐳 部署方式 +## ⚙️ 配置说明 -### Docker Compose 部署(PostgreSQL) +### 必需配置 -**推荐生产环境使用**,提供更好的性能和并发支持。 - -#### 快速启动 +创建 `.env` 文件: ```bash -# 1. 克隆项目 -git clone https://github.com/xiamuceer-j/MuMuAINovel.git -cd MuMuAINovel +# PostgreSQL 数据库(必需) +DATABASE_URL=postgresql+asyncpg://mumuai:your_password@postgres:5432/mumuai_novel +POSTGRES_PASSWORD=your_secure_password -# 2. 配置环境变量 -cp backend/.env.example .env -# 编辑 .env 文件,设置必要的配置: -# - POSTGRES_PASSWORD(数据库密码) -# - OPENAI_API_KEY(AI服务密钥) -# - 其他可选配置 - -# 3. 启动服务(包含PostgreSQL) -docker-compose up -d - -# 4. 查看服务状态 -docker-compose ps - -# 5. 查看日志 -docker-compose logs -f - -# 6. 访问应用 -# 打开浏览器访问 http://localhost:8000 -``` - -#### 环境变量配置 - -创建 `.env` 文件并配置: - -```bash -# PostgreSQL数据库密码(必须设置) -POSTGRES_PASSWORD=your_secure_password_here - -# AI服务配置(必须设置) -OPENAI_API_KEY=your_openai_api_key +# AI 服务(至少配置一个) +OPENAI_API_KEY=your_openai_key +OPENAI_BASE_URL=https://api.openai.com/v1 DEFAULT_AI_PROVIDER=openai -DEFAULT_MODEL=gpt-4 +DEFAULT_MODEL=gpt-4o-mini -# 本地账户登录(可选) +# 本地账户登录 LOCAL_AUTH_ENABLED=true LOCAL_AUTH_USERNAME=admin -LOCAL_AUTH_PASSWORD=admin123 - -# 其他配置见 backend/.env.example +LOCAL_AUTH_PASSWORD=your_password ``` -#### 服务说明 - -- **postgres**: PostgreSQL 18 数据库 - - 端口:5432 - - 数据持久化:`./postgres_data` - - 已优化配置,支持80-150并发用户 - -- **mumuainovel**: 主应用服务 - - 端口:8000 - - 自动等待数据库就绪 - - 日志持久化:`./logs` - -详细部署指南请参考:[Docker + PostgreSQL 部署文档](docs/docker-postgres-deployment.md) - -### Docker Compose 部署(SQLite) - -适合个人使用或小团队,配置更简单。 - -#### 使用 Docker Hub 镜像 - -项目已发布到 Docker Hub,可直接拉取使用: +### 可选配置 ```bash -# 查看可用版本 -docker pull mumujie/mumuainovel:latest +# Gemini +GEMINI_API_KEY=your_gemini_key +# Claude +ANTHROPIC_API_KEY=your_claude_key + +# LinuxDO OAuth +LINUXDO_CLIENT_ID=your_client_id +LINUXDO_CLIENT_SECRET=your_client_secret +LINUXDO_REDIRECT_URI=http://localhost:8000/api/auth/callback + +# PostgreSQL 连接池(高并发优化) +DATABASE_POOL_SIZE=30 +DATABASE_MAX_OVERFLOW=20 +``` + +### 中转 API 配置 + +支持所有 OpenAI 兼容格式的中转服务: + +```bash +# New API 示例 +OPENAI_API_KEY=sk-xxxxxxxx +OPENAI_BASE_URL=https://api.new-api.com/v1 + +# 其他中转服务 +OPENAI_BASE_URL=https://your-proxy-service.com/v1 +``` + +## 🐳 Docker 部署详情 + +### 服务架构 + +- **postgres**: PostgreSQL 18 数据库 + - 端口: 5432 + - 数据持久化: `./postgres_data` + - 优化配置: 支持 80-150 并发用户 + +- **mumuainovel**: 主应用服务 + - 端口: 8000 + - 日志目录: `./logs` + - 自动等待数据库就绪 + +### 常用命令 + +```bash # 启动服务 docker-compose up -d +# 查看状态 +docker-compose ps + # 查看日志 docker-compose logs -f @@ -208,354 +196,67 @@ docker-compose down # 重启服务 docker-compose restart -# 更新到最新版本 -docker-compose pull -docker-compose up -d +# 查看资源使用 +docker stats ``` -#### Docker Compose 配置文件示例 +### 数据持久化 -使用 Docker Hub 镜像的完整配置: +- `./postgres_data` - PostgreSQL 数据库文件 +- `./logs` - 应用日志文件 + +### 端口配置 + +修改 `docker-compose.yml` 中的端口映射: ```yaml -services: - ai-story: - image: mumujie/mumuainovel:latest - container_name: mumuainovel - ports: - - "8800:8000" # 宿主机端口:容器端口 - volumes: - # 持久化数据库和日志 - - ./data:/app/data - - ./logs:/app/logs - # 挂载环境变量文件 - - ./.env:/app/.env:ro - environment: - - APP_NAME=mumuainovel - - APP_VERSION=1.0.0 - - APP_HOST=0.0.0.0 - - APP_PORT=8000 - - DEBUG=false - # 其他环境变量会从 .env 文件自动加载 - restart: unless-stopped - healthcheck: - test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 10s - networks: - - ai-story-network - -networks: - ai-story-network: - driver: bridge -``` - -### 生产环境部署建议 - -#### 1. 环境变量配置 - -**必需配置**: -- `OPENAI_API_KEY` 或 `GEMINI_API_KEY`:至少配置一个 AI 服务 -- `LOCAL_AUTH_PASSWORD`:修改为强密码 - -**推荐配置**: -- `OPENAI_BASE_URL`:如果使用中转 API,修改为中转服务地址 -- `DEFAULT_AI_PROVIDER`:根据你的 API Key 选择 `openai`、`gemini` 或 `anthropic` -- `DEFAULT_MODEL`:选择合适的模型(如 `gpt-4o-mini`、`gemini-2.0-flash-exp`) - -#### 2. 数据持久化 - -**PostgreSQL部署**: -- `./postgres_data`:PostgreSQL 数据库文件 -- `./logs`:应用日志文件 - -**SQLite部署**: -- `./data`:SQLite 数据库文件 -- `./logs`:应用日志文件 - -#### 3. 端口配置 - -默认端口映射:`8800:8000` -- 宿主机端口:`8800`(可自定义修改) -- 容器内端口:`8000`(固定,不要修改) - -访问地址:`http://your-server-ip:8800` - - -配置后记得更新 `.env` 中的 `LINUXDO_REDIRECT_URI` 和 `FRONTEND_URL`。 - -#### 5. 资源限制(可选) - -在 `docker-compose.yml` 中添加资源限制: - -```yaml -services: - ai-story: - # ... 其他配置 - deploy: - resources: - limits: - cpus: '2.0' - memory: 2G - reservations: - cpus: '0.5' - memory: 512M -``` - -### 端口说明 - -- **默认端口**:`8800`(宿主机)→ `8000`(容器) -- **可自定义**:修改 docker-compose.yml 中的 `ports` 配置 -- **健康检查**:容器内部使用 `8000` 端口进行健康检查 - -## ⚙️ 配置说明 - -### 数据库选择 - -项目支持两种数据库: - -```bash -# .env 配置 -DATABASE_URL=postgresql+asyncpg://mumuai:password@postgres:5432/mumuai_novel -``` - -```bash -# .env 配置 -DATABASE_URL=sqlite+aiosqlite:///data/ai_story.db -``` - -### 环境变量 - -创建 `.env` 文件并配置以下变量: - -```bash -# ===== 数据库配置 ===== -# PostgreSQL(生产环境推荐) -DATABASE_URL=postgresql+asyncpg://mumuai:password@postgres:5432/mumuai_novel -POSTGRES_PASSWORD=your_secure_password_here - -# 或使用 SQLite(开发环境) -# DATABASE_URL=sqlite+aiosqlite:///data/ai_story.db - -# ===== AI 服务配置(必填)===== -# OpenAI 配置(支持官方API和中转API) -OPENAI_API_KEY=your_openai_key_here -OPENAI_BASE_URL=https://api.openai.com/v1 - -# Anthropic 配置 -# ANTHROPIC_API_KEY=your_anthropic_key_here -# ANTHROPIC_BASE_URL=https://api.anthropic.com - -# 中转API配置示例(使用OpenAI格式) -# New API 中转服务 -# OPENAI_API_KEY=your_newapi_key_here -# OPENAI_BASE_URL=https://api.new-api.com/v1 - -# 默认 AI 提供商和模型 -DEFAULT_AI_PROVIDER=openai -DEFAULT_MODEL=gpt-4o-mini -DEFAULT_TEMPERATURE=0.8 -DEFAULT_MAX_TOKENS=32000 - -# ===== 应用配置 ===== -APP_NAME=MuMuAINovel -APP_VERSION=1.0.0 -APP_HOST=0.0.0.0 -APP_PORT=8000 -DEBUG=false - -# ===== LinuxDO OAuth 配置(可选)===== -LINUXDO_CLIENT_ID=your_client_id_here -LINUXDO_CLIENT_SECRET=your_client_secret_here -LINUXDO_REDIRECT_URI=http://localhost:8000/api/auth/callback -FRONTEND_URL=http://localhost:8000 - -# ===== 本地账户登录配置 ===== -LOCAL_AUTH_ENABLED=true -LOCAL_AUTH_USERNAME=admin -LOCAL_AUTH_PASSWORD=your_secure_password_here -LOCAL_AUTH_DISPLAY_NAME=管理员 - -# 会话配置 -# 会话过期时间(分钟),默认120分钟(2小时) -SESSION_EXPIRE_MINUTES=120 -# 会话刷新阈值(分钟),剩余时间少于此值时可刷新,默认30分钟 -SESSION_REFRESH_THRESHOLD_MINUTES=30 - -# ===== CORS 配置(生产环境)===== -# CORS_ORIGINS=https://your-domain.com,https://www.your-domain.com -``` - -### AI 模型配置 - -项目支持多个 AI 提供商,你可以根据需要配置: - -| 提供商 | 推荐模型 | 用途 | -|--------|---------|------| -| OpenAI | gpt-4, gpt-3.5-turbo | 高质量文本生成 | -| Anthropic | claude-3-opus, claude-3-sonnet | 长文本创作 | - -#### 使用中转API服务 - -如果你无法直接访问 OpenAI 官方 API,或者想使用更经济实惠的中转服务,本项目完全支持各种 OpenAI 兼容格式的中转 API: - -##### 配置方法 - -只需修改 `.env` 文件中的两个参数: - -```bash -# 1. 填入中转服务提供的 API Key -OPENAI_API_KEY=your_api_key_from_proxy_service - -# 2. 修改 Base URL 为中转服务的地址 -OPENAI_BASE_URL=https://your-proxy-service.com/v1 -``` - -##### 常见中转服务配置示例 - -**New API** -```bash -OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx -OPENAI_BASE_URL=https://api.new-api.com/v1 -``` - -##### 注意事项 - -- ✅ 所有支持 OpenAI 接口格式的服务都可以使用 -- ✅ 确保中转服务的 Base URL 以 `/v1` 结尾 -- ✅ 根据中转服务支持的模型,修改 `DEFAULT_MODEL` 参数 -- ⚠️ 不同中转服务的模型名称可能不同,请参考服务商文档 -- ⚠️ 部分中转服务可能对请求频率或并发有限制 - -##### 推荐的中转服务 - -如果你需要中转服务,以下是一些常见选择: - -1. **New API** - 开源的 API 分发系统,支持多种模型 -2. **API2D** - 国内稳定的 API 中转服务 -3. **OpenAI-SB** - 提供多种 AI 模型的中转 -4. **自建服务** - 使用 One API 或 New API 自行搭建 - -> 💡 提示:使用中转服务时,请确保服务提供商的可靠性和数据安全性 - -### 登录方式配置 - -#### 本地账户登录(默认启用) - -适合个人使用或小型团队: - -```bash -LOCAL_AUTH_ENABLED=true -LOCAL_AUTH_USERNAME=admin -LOCAL_AUTH_PASSWORD=your_password -``` - -#### LinuxDO OAuth 登录 - -适合需要社区集成的场景,需要在 [LinuxDO](https://linux.do) 注册 OAuth 应用: - -```bash -LINUXDO_CLIENT_ID=your_client_id -LINUXDO_CLIENT_SECRET=your_client_secret -LINUXDO_REDIRECT_URI=http://your-domain:8000/api/auth/callback +ports: + - "8800:8000" # 宿主机:容器 ``` ## 📁 项目结构 ``` MuMuAINovel/ -├── backend/ # 后端服务 +├── backend/ # 后端服务 │ ├── app/ -│ │ ├── api/ # API 路由 -│ │ │ ├── auth.py # 认证接口 -│ │ │ ├── projects.py # 项目管理 -│ │ │ ├── chapters.py # 章节管理 -│ │ │ ├── characters.py # 角色管理 -│ │ │ ├── wizard_stream.py # 向导流式生成 -│ │ │ └── ... -│ │ ├── models/ # 数据模型 -│ │ ├── schemas/ # Pydantic 模型 -│ │ ├── services/ # 业务逻辑 -│ │ │ ├── ai_service.py # AI 服务封装 -│ │ │ └── oauth_service.py # OAuth 服务 -│ │ ├── middleware/ # 中间件 -│ │ ├── utils/ # 工具函数 -│ │ ├── config.py # 配置管理 -│ │ ├── database.py # 数据库连接 -│ │ └── main.py # 应用入口 -│ ├── data/ # 数据存储目录 -│ ├── static/ # 前端静态文件(构建后) -│ ├── requirements.txt # Python 依赖 -│ └── .env.example # 环境变量示例 -├── frontend/ # 前端应用 +│ │ ├── api/ # API 路由 +│ │ ├── models/ # 数据模型 +│ │ ├── services/ # 业务逻辑 +│ │ ├── middleware/ # 中间件 +│ │ ├── database.py # 数据库连接 +│ │ └── main.py # 应用入口 +│ ├── scripts/ # 工具脚本 +│ └── requirements.txt # Python 依赖 +├── frontend/ # 前端应用 │ ├── src/ -│ │ ├── pages/ # 页面组件 -│ │ │ ├── ProjectList.tsx # 项目列表 -│ │ │ ├── ProjectWizardNew.tsx # 创建向导 -│ │ │ ├── Chapters.tsx # 章节管理 -│ │ │ ├── Characters.tsx # 角色管理 -│ │ │ └── ... -│ │ ├── components/ # 通用组件 -│ │ ├── services/ # API 服务 -│ │ ├── store/ # 状态管理(Zustand) -│ │ ├── types/ # TypeScript 类型 -│ │ └── utils/ # 工具函数 -│ ├── package.json -│ └── vite.config.ts -├── docker-compose.yml # Docker Compose 配置 -├── Dockerfile # Docker 镜像构建 -└── README.md # 项目说明文档 +│ │ ├── pages/ # 页面组件 +│ │ ├── components/ # 通用组件 +│ │ ├── services/ # API 服务 +│ │ └── store/ # 状态管理 +│ └── package.json +├── docker-compose.yml # Docker Compose 配置 +├── Dockerfile # Docker 镜像构建 +└── README.md ``` ## 🛠️ 技术栈 -### 后端 +**后端**: FastAPI • PostgreSQL • SQLAlchemy • OpenAI/Claude/Gemini SDK -- **框架**:FastAPI 0.109.0 -- **数据库**:PostgreSQL / SQLite + SQLAlchemy(异步) -- **AI 集成**:OpenAI、Anthropic、Google Gemini SDK -- **认证**:LinuxDO OAuth2、本地账户 -- **日志**:Python logging + 文件轮转 - -### 前端 - -- **框架**:React 18.3 + TypeScript -- **UI 库**:Ant Design 5.27 -- **路由**:React Router 6.28 -- **状态管理**:Zustand 5.0 -- **HTTP 客户端**:Axios -- **构建工具**:Vite 7.1 +**前端**: React 18 • TypeScript • Ant Design • Zustand • Vite ## 📖 使用指南 -### 创建第一个小说项目 - -1. **登录系统** - - 使用本地账户或 LinuxDO 账户登录 - -2. **创建项目** - - 点击"创建项目"按钮 - - 选择"使用向导创建"或"手动创建" - -3. **使用向导(推荐)** - - 输入小说基本信息(标题、类型、背景等) - - AI 自动生成大纲、角色和世界观 - - 实时查看生成进度 - -4. **编辑和完善** - - 在项目详情页查看和编辑大纲 - - 管理角色和人物关系 - - 生成和编辑章节内容 - +1. **登录系统** - 使用本地账户或 LinuxDO 账户 +2. **创建项目** - 选择"使用向导创建" +3. **AI 生成** - 输入基本信息,AI 自动生成大纲和角色 +4. **编辑完善** - 管理角色关系,生成和编辑章节 ### API 文档 -应用启动后,可访问自动生成的 API 文档: - -- Swagger UI:`http://localhost:8000/docs` -- ReDoc:`http://localhost:8000/redoc` +- Swagger UI: `http://localhost:8000/docs` +- ReDoc: `http://localhost:8000/redoc` ## 🤝 贡献 @@ -569,38 +270,32 @@ MuMuAINovel/ ## 📝 许可证 -本项目采用 [GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.html) 开源协议 +本项目采用 [GNU General Public License v3.0](LICENSE) -**这意味着:** - -- ✅ **可以** - 自由使用、复制、修改和分发本项目 -- ✅ **可以** - 用于商业目的 -- ✅ **可以** - 用于个人学习和研究 -- 📝 **必须** - 开源你的修改版本 -- 📝 **必须** - 保留原作者版权声明 -- 📝 **必须** - 以相同的 GPL v3 协议发布衍生作品 - -详见 [LICENSE](LICENSE) 文件 +**GPL v3 意味着:** +- ✅ 可自由使用、修改和分发 +- ✅ 可用于商业目的 +- 📝 必须开源修改版本 +- 📝 必须保留原作者版权 +- 📝 衍生作品必须使用 GPL v3 协议 ## 🙏 致谢 -- [FastAPI](https://fastapi.tiangolo.com/) - 现代化的 Python Web 框架 -- [React](https://react.dev/) - 用户界面构建库 -- [Ant Design](https://ant.design/) - 企业级 UI 设计语言 -- [OpenAI](https://openai.com/) / [Anthropic](https://www.anthropic.com/) - AI 模型提供商 +- [FastAPI](https://fastapi.tiangolo.com/) - Python Web 框架 +- [React](https://react.dev/) - 前端框架 +- [Ant Design](https://ant.design/) - UI 组件库 +- [PostgreSQL](https://www.postgresql.org/) - 数据库 ## 📧 联系方式 -如有问题或建议,欢迎通过以下方式联系: - -- 提交 [Issue](https://github.com/yourusername/MuMuAINovel/issues) -- Linux DO [LD](https://linux.do/t/topic/1100112) +- 提交 [Issue](https://github.com/xiamuceer-j/MuMuAINovel/issues) +- Linux DO [讨论](https://linux.do/t/topic/1100112) ---
-**如果这个项目对你有帮助,请给个 ⭐️ Star 支持一下!** +**如果这个项目对你有帮助,请给个 ⭐️ Star!** Made with ❤️ diff --git a/backend/.env.example b/backend/.env.example index 3646421..4ea0761 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -11,19 +11,21 @@ APP_NAME=MuMuAINovel APP_VERSION=1.0.0 APP_HOST=0.0.0.0 APP_PORT=8000 -DEBUG=True +DEBUG=false +TZ=Asia/Shanghai # ========================================== -# 数据库配置 +# PostgreSQL 数据库配置 # ========================================== -# 选项1: PostgreSQL(生产环境推荐) -# DATABASE_URL=postgresql+asyncpg://username:password@localhost:5432/database_name -# 示例: -# DATABASE_URL=postgresql+asyncpg://mumuai:your_password@localhost:5432/mumuai_novel +# PostgreSQL 连接信息 +POSTGRES_DB=mumuai_novel +POSTGRES_USER=mumuai +POSTGRES_PASSWORD=your_secure_password_here +POSTGRES_PORT=5432 -# 选项2: SQLite(开发环境,默认) -DATABASE_URL=sqlite+aiosqlite:///data/ai_story.db +# 数据库连接 URL(Docker 部署时自动生成) +DATABASE_URL=postgresql+asyncpg://mumuai:your_secure_password_here@localhost:5432/mumuai_novel # PostgreSQL 连接池配置(优化后,支持80-150并发用户) DATABASE_POOL_SIZE=30 # 核心连接数(默认30,小团队可用20) @@ -37,73 +39,69 @@ DATABASE_POOL_USE_LIFO=True # 使用LIFO策略提高连接复用率 DATABASE_SESSION_MAX_ACTIVE=50 # 活跃会话警告阈值 DATABASE_SESSION_LEAK_THRESHOLD=100 # 会话泄漏严重告警阈值 -# SQLite 性能优化配置(仅在使用SQLite时生效) -SQLITE_CACHE_SIZE_MB=128 # SQLite缓存大小(MB),默认128 -SQLITE_MMAP_SIZE_MB=256 # 内存映射I/O大小(MB),默认256 -SQLITE_WAL_AUTOCHECKPOINT=1000 # WAL自动检查点间隔 - # 数据库监控配置 DATABASE_ENABLE_SLOW_QUERY_LOG=True # 启用慢查询日志 DATABASE_SLOW_QUERY_THRESHOLD=1.0 # 慢查询阈值(秒) DATABASE_ENABLE_METRICS=True # 启用性能指标收集 +# ========================================== +# 代理配置(可选) +# ========================================== +# HTTP_PROXY=http://your-proxy:port +# HTTPS_PROXY=http://your-proxy:port +# NO_PROXY=localhost,127.0.0.1 + # ========================================== # 日志配置 # ========================================== LOG_LEVEL=INFO -LOG_TO_FILE=True +LOG_TO_FILE=true LOG_FILE_PATH=logs/app.log LOG_MAX_BYTES=10485760 LOG_BACKUP_COUNT=30 # ========================================== -# CORS配置 +# CORS 配置 # ========================================== CORS_ORIGINS=["http://localhost:8000","http://127.0.0.1:8000"] # ========================================== -# AI服务配置 +# AI 服务配置(至少配置一个) # ========================================== -# OpenAI配置 +# OpenAI 配置 OPENAI_API_KEY=your_openai_api_key_here OPENAI_BASE_URL=https://api.openai.com/v1 -# 或使用兼容的API服务(如DeepSeek) -# OPENAI_BASE_URL=https://api.deepseek.com/v1 -# Gemini配置(可选) -# GEMINI_API_KEY=your_gemini_api_key_here -# GEMINI_BASE_URL=https://generativelanguage.googleapis.com - -# Anthropic配置(可选) +# Anthropic 配置(可选) # ANTHROPIC_API_KEY=your_anthropic_api_key_here # ANTHROPIC_BASE_URL=https://api.anthropic.com -# 默认AI配置 +# 默认 AI 配置 DEFAULT_AI_PROVIDER=openai -DEFAULT_MODEL=gpt-4 +DEFAULT_MODEL=gpt-4o-mini DEFAULT_TEMPERATURE=0.7 DEFAULT_MAX_TOKENS=2000 # ========================================== -# LinuxDO OAuth2 配置(可选) +# LinuxDO OAuth 配置(可选) # ========================================== -# LINUXDO_CLIENT_ID=your_client_id -# LINUXDO_CLIENT_SECRET=your_client_secret +# LINUXDO_CLIENT_ID=your_client_id_here +# LINUXDO_CLIENT_SECRET=your_client_secret_here # LINUXDO_REDIRECT_URI=http://localhost:8000/api/auth/callback -# 前端URL(OAuth回调后重定向) +# 前端 URL(OAuth 回调后重定向) FRONTEND_URL=http://localhost:8000 # 初始管理员(LinuxDO user_id) -# INITIAL_ADMIN_LINUXDO_ID=12345 +# INITIAL_ADMIN_LINUXDO_ID=your_linuxdo_user_id # ========================================== # 本地账户登录配置 # ========================================== -LOCAL_AUTH_ENABLED=True +LOCAL_AUTH_ENABLED=true LOCAL_AUTH_USERNAME=admin -LOCAL_AUTH_PASSWORD=admin123 +LOCAL_AUTH_PASSWORD=your_secure_password_here LOCAL_AUTH_DISPLAY_NAME=本地管理员 # ========================================== @@ -113,28 +111,21 @@ SESSION_EXPIRE_MINUTES=120 SESSION_REFRESH_THRESHOLD_MINUTES=30 # ========================================== -# 部署配置说明 +# 部署配置示例 # ========================================== -# 生产环境 PostgreSQL 配置示例(50-100并发用户): -# DATABASE_URL=postgresql+asyncpg://mumuai:SecurePassword123@db.example.com:5432/mumuai_prod -# DATABASE_POOL_SIZE=30 -# DATABASE_MAX_OVERFLOW=20 -# DATABASE_POOL_TIMEOUT=60 -# DATABASE_POOL_RECYCLE=1800 -# DATABASE_SESSION_MAX_ACTIVE=50 -# DEBUG=False -# LOG_LEVEL=WARNING - -# 高并发环境 PostgreSQL 配置示例(100+并发用户): -# DATABASE_URL=postgresql+asyncpg://mumuai:SecurePassword123@db.example.com:5432/mumuai_prod +# Docker 生产环境配置: +# POSTGRES_PASSWORD=your_very_secure_password # DATABASE_POOL_SIZE=40 # DATABASE_MAX_OVERFLOW=30 -# DATABASE_SESSION_MAX_ACTIVE=80 -# DATABASE_SESSION_LEAK_THRESHOLD=150 +# DEBUG=false +# LOG_LEVEL=WARNING -# Docker 部署配置示例: -# DATABASE_URL=postgresql+asyncpg://mumuai:password@postgres:5432/mumuai_novel -# OPENAI_BASE_URL=https://api.openai.com/v1 +# 外网访问配置: # FRONTEND_URL=https://your-domain.com -# LINUXDO_REDIRECT_URI=https://your-domain.com/api/auth/callback \ No newline at end of file +# LINUXDO_REDIRECT_URI=https://your-domain.com/api/auth/callback +# APP_PORT=8000 + +# 中转 API 配置示例: +# OPENAI_BASE_URL=https://api.new-api.com/v1 +# DEFAULT_MODEL=gpt-4o-mini \ No newline at end of file diff --git a/backend/app/config.py b/backend/app/config.py index 6acdd3a..e826fd3 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -13,15 +13,11 @@ DATA_DIR.mkdir(exist_ok=True) # 配置模块使用标准logging(在logger.py初始化之前) config_logger = logging.getLogger(__name__) -# 数据库配置:支持PostgreSQL和SQLite -# 优先使用环境变量DATABASE_URL,否则使用SQLite -DB_FILE = DATA_DIR / "ai_story.db" -DEFAULT_SQLITE_URL = f"sqlite+aiosqlite:///{str(DB_FILE.absolute()).replace(chr(92), '/')}" +# 数据库配置:PostgreSQL +# 从环境变量获取数据库URL +DATABASE_URL = os.getenv("DATABASE_URL", "postgresql+asyncpg://mumuai:password@localhost:5432/mumuai_novel") -# 从环境变量获取数据库URL,如果未设置则使用SQLite -DATABASE_URL = os.getenv("DATABASE_URL", DEFAULT_SQLITE_URL) - -config_logger.debug(f"数据库类型: {'PostgreSQL' if 'postgresql' in DATABASE_URL else 'SQLite'}") +config_logger.debug(f"数据库类型: PostgreSQL") config_logger.debug(f"数据库URL: {DATABASE_URL}") class Settings(BaseSettings): @@ -44,7 +40,7 @@ class Settings(BaseSettings): # CORS配置 cors_origins: list[str] = ["http://localhost:8000", "http://127.0.0.1:8000"] - # 数据库配置 - 支持PostgreSQL和SQLite + # 数据库配置 - PostgreSQL database_url: str = DATABASE_URL # PostgreSQL连接池配置(优化后支持80-150并发用户) @@ -59,11 +55,6 @@ class Settings(BaseSettings): database_session_max_active: int = 50 # 活跃会话警告阈值(从100降低到50) database_session_leak_threshold: int = 100 # 会话泄漏严重告警阈值 - # SQLite优化配置 - sqlite_cache_size_mb: int = 128 # SQLite缓存大小MB(从64提升到128) - sqlite_mmap_size_mb: int = 256 # 内存映射I/O大小MB - sqlite_wal_autocheckpoint: int = 1000 # WAL自动检查点间隔 - # 数据库监控配置 database_enable_slow_query_log: bool = True # 启用慢查询日志 database_slow_query_threshold: float = 1.0 # 慢查询阈值(秒) diff --git a/backend/app/database.py b/backend/app/database.py index c229bd0..dd4a30c 100644 --- a/backend/app/database.py +++ b/backend/app/database.py @@ -1,11 +1,10 @@ -"""数据库连接和会话管理 - 支持多用户数据隔离""" +"""数据库连接和会话管理 - PostgreSQL 多用户数据隔离""" import asyncio from typing import Dict, Any from datetime import datetime from sqlalchemy import select, text from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker from sqlalchemy.orm import declarative_base -from sqlalchemy.pool import StaticPool from fastapi import Request, HTTPException from app.config import settings from app.logger import get_logger @@ -46,9 +45,7 @@ _session_stats = { async def get_engine(user_id: str): """获取或创建用户专属的数据库引擎(线程安全) - 支持PostgreSQL和SQLite两种数据库: - - PostgreSQL: 所有用户共享一个数据库,通过user_id字段隔离数据 - - SQLite: 每个用户一个独立的数据库文件 + PostgreSQL: 所有用户共享一个数据库,通过user_id字段隔离数据 Args: user_id: 用户ID @@ -57,99 +54,45 @@ async def get_engine(user_id: str): 用户专属的异步引擎 """ # PostgreSQL模式:所有用户共享同一个引擎 - if "postgresql" in settings.database_url: - cache_key = "shared_postgres" - if cache_key in _engine_cache: - return _engine_cache[cache_key] - - async with _cache_lock: - if cache_key not in _engine_cache: - # 优化后的PostgreSQL连接配置 - connect_args = { - "server_settings": { - "application_name": settings.app_name, - "jit": "off", # 关闭JIT以提高短查询性能 - }, - "command_timeout": 60, # 命令超时60秒 - "statement_cache_size": 500, # 启用语句缓存,提升重复查询性能 - } - - engine = create_async_engine( - settings.database_url, - echo=False, # 生产环境关闭SQL日志 - future=True, - pool_size=settings.database_pool_size, # 核心连接数:30 - max_overflow=settings.database_max_overflow, # 溢出连接数:20 - pool_timeout=settings.database_pool_timeout, # 连接超时:60秒 - pool_pre_ping=settings.database_pool_pre_ping, # 连接前检测 - pool_recycle=settings.database_pool_recycle, # 连接回收:1800秒 - pool_use_lifo=settings.database_pool_use_lifo, # LIFO策略提高复用 - connect_args=connect_args - ) - _engine_cache[cache_key] = engine - logger.info( - f"✅ PostgreSQL引擎已创建(优化配置)\n" - f" ├─ 连接池: {settings.database_pool_size} 核心 + {settings.database_max_overflow} 溢出 = {settings.database_pool_size + settings.database_max_overflow} 总连接\n" - f" ├─ 超时: {settings.database_pool_timeout}秒\n" - f" ├─ 回收: {settings.database_pool_recycle}秒\n" - f" ├─ 策略: LIFO(提高复用率)\n" - f" └─ 预估并发: 80-150用户" - ) - - return _engine_cache[cache_key] - - # SQLite模式:每个用户独立的数据库文件 - if user_id in _engine_cache: - return _engine_cache[user_id] + cache_key = "shared_postgres" + if cache_key in _engine_cache: + return _engine_cache[cache_key] async with _cache_lock: - if user_id not in _engine_locks: - _engine_locks[user_id] = asyncio.Lock() - user_lock = _engine_locks[user_id] - - async with user_lock: - if user_id not in _engine_cache: - db_url = f"sqlite+aiosqlite:///data/ai_story_user_{user_id}.db" - engine = create_async_engine( - db_url, - echo=False, - future=True, - poolclass=StaticPool, - pool_pre_ping=True, - pool_recycle=3600, - connect_args={ - "timeout": 30, - "check_same_thread": False - } - ) + if cache_key not in _engine_cache: + # 优化后的PostgreSQL连接配置 + connect_args = { + "server_settings": { + "application_name": settings.app_name, + "jit": "off", # 关闭JIT以提高短查询性能 + }, + "command_timeout": 60, # 命令超时60秒 + "statement_cache_size": 500, # 启用语句缓存,提升重复查询性能 + } - try: - # 应用优化后的SQLite配置 - cache_size = -1024 * settings.sqlite_cache_size_mb # 负数表示KB单位 - mmap_size = settings.sqlite_mmap_size_mb * 1024 * 1024 # 转换为字节 - - async with engine.begin() as conn: - await conn.execute(text("PRAGMA journal_mode=WAL")) - await conn.execute(text("PRAGMA synchronous=NORMAL")) - await conn.execute(text(f"PRAGMA cache_size={cache_size}")) # 128MB缓存 - await conn.execute(text(f"PRAGMA mmap_size={mmap_size}")) # 256MB内存映射 - await conn.execute(text("PRAGMA temp_store=MEMORY")) - await conn.execute(text("PRAGMA busy_timeout=5000")) - await conn.execute(text(f"PRAGMA wal_autocheckpoint={settings.sqlite_wal_autocheckpoint}")) - - logger.info( - f"✅ 用户 {user_id} 的SQLite数据库已优化\n" - f" ├─ WAL模式\n" - f" ├─ 缓存: {settings.sqlite_cache_size_mb}MB\n" - f" ├─ 内存映射: {settings.sqlite_mmap_size_mb}MB\n" - f" └─ 预估并发: 15-20写入用户" - ) - except Exception as e: - logger.warning(f"⚠️ 用户 {user_id} SQLite数据库优化失败: {str(e)}") - _engine_cache[user_id] = engine - logger.info(f"为用户 {user_id} 创建SQLite数据库引擎") + engine = create_async_engine( + settings.database_url, + echo=False, # 生产环境关闭SQL日志 + future=True, + pool_size=settings.database_pool_size, # 核心连接数:30 + max_overflow=settings.database_max_overflow, # 溢出连接数:20 + pool_timeout=settings.database_pool_timeout, # 连接超时:60秒 + pool_pre_ping=settings.database_pool_pre_ping, # 连接前检测 + pool_recycle=settings.database_pool_recycle, # 连接回收:1800秒 + pool_use_lifo=settings.database_pool_use_lifo, # LIFO策略提高复用 + connect_args=connect_args + ) + _engine_cache[cache_key] = engine + logger.info( + f"✅ PostgreSQL引擎已创建(优化配置)\n" + f" ├─ 连接池: {settings.database_pool_size} 核心 + {settings.database_max_overflow} 溢出 = {settings.database_pool_size + settings.database_max_overflow} 总连接\n" + f" ├─ 超时: {settings.database_pool_timeout}秒\n" + f" ├─ 回收: {settings.database_pool_recycle}秒\n" + f" ├─ 策略: LIFO(提高复用率)\n" + f" └─ 预估并发: 80-150用户" + ) - return _engine_cache[user_id] + return _engine_cache[cache_key] async def get_db(request: Request): @@ -411,7 +354,7 @@ async def get_database_stats(): "engine_keys": list(_engine_cache.keys()), }, "config": { - "database_type": "PostgreSQL" if "postgresql" in settings.database_url else "SQLite", + "database_type": "PostgreSQL", "pool_size": settings.database_pool_size, "max_overflow": settings.database_max_overflow, "total_connections": settings.database_pool_size + settings.database_max_overflow, @@ -469,19 +412,14 @@ async def check_database_health(user_id: str = None) -> dict: try: # 检查引擎是否存在 + cache_key = "shared_postgres" if user_id: engine = await get_engine(user_id) - cache_key = user_id else: - if "postgresql" in settings.database_url: - cache_key = "shared_postgres" - if cache_key not in _engine_cache: - result["checks"]["engine"] = {"status": "not_initialized", "healthy": True} - return result - engine = _engine_cache[cache_key] - else: - result["checks"]["engine"] = {"status": "skipped", "message": "需要提供user_id检查SQLite"} + if cache_key not in _engine_cache: + result["checks"]["engine"] = {"status": "not_initialized", "healthy": True} return result + engine = _engine_cache[cache_key] # 测试数据库连接 AsyncSessionLocal = async_sessionmaker( diff --git a/backend/requirements.txt b/backend/requirements.txt index 49b1aee..d268955 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -5,9 +5,8 @@ python-multipart==0.0.20 # 数据库 sqlalchemy==2.0.25 -aiosqlite==0.19.0 # SQLite支持(保留用于开发环境) -asyncpg==0.29.0 # PostgreSQL异步驱动(生产环境) -psycopg2-binary==2.9.9 # PostgreSQL同步驱动(备用) +asyncpg==0.29.0 # PostgreSQL异步驱动 +psycopg2-binary==2.9.9 # PostgreSQL同步驱动(用于迁移脚本) # 数据验证 pydantic==2.12.4 diff --git a/docker-compose.yml b/docker-compose.yml index ce68e2b..089000b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,19 +3,19 @@ services: image: postgres:18-alpine container_name: mumuainovel-postgres environment: - POSTGRES_DB: mumuai_novel - POSTGRES_USER: mumuai + POSTGRES_DB: ${POSTGRES_DB:-mumuai_novel} + POSTGRES_USER: ${POSTGRES_USER:-mumuai} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mumuai_password_2024} POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C" - TZ: Asia/Shanghai + TZ: ${TZ:-Asia/Shanghai} volumes: - postgres_data:/var/lib/postgresql/data - ./backend/scripts/init_postgres.sql:/docker-entrypoint-initdb.d/init.sql:ro ports: - - "5432:5432" + - "${POSTGRES_PORT:-5432}:5432" restart: unless-stopped healthcheck: - test: ["CMD-SHELL", "pg_isready -U mumuai -d mumuai_novel"] + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-mumuai} -d ${POSTGRES_DB:-mumuai_novel}"] interval: 10s timeout: 5s retries: 5 @@ -25,29 +25,29 @@ services: command: - postgres - -c - - max_connections=200 + - max_connections=${POSTGRES_MAX_CONNECTIONS:-200} - -c - - shared_buffers=256MB + - shared_buffers=${POSTGRES_SHARED_BUFFERS:-256MB} - -c - - effective_cache_size=1GB + - effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-1GB} - -c - - maintenance_work_mem=64MB + - maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB} - -c - - checkpoint_completion_target=0.9 + - checkpoint_completion_target=${POSTGRES_CHECKPOINT_COMPLETION_TARGET:-0.9} - -c - - wal_buffers=16MB + - wal_buffers=${POSTGRES_WAL_BUFFERS:-16MB} - -c - - default_statistics_target=100 + - default_statistics_target=${POSTGRES_DEFAULT_STATISTICS_TARGET:-100} - -c - - random_page_cost=1.1 + - random_page_cost=${POSTGRES_RANDOM_PAGE_COST:-1.1} - -c - - effective_io_concurrency=200 + - effective_io_concurrency=${POSTGRES_EFFECTIVE_IO_CONCURRENCY:-200} - -c - - work_mem=4MB + - work_mem=${POSTGRES_WORK_MEM:-4MB} - -c - - min_wal_size=1GB + - min_wal_size=${POSTGRES_MIN_WAL_SIZE:-1GB} - -c - - max_wal_size=4GB + - max_wal_size=${POSTGRES_MAX_WAL_SIZE:-4GB} mumuainovel: build: @@ -59,46 +59,61 @@ services: postgres: condition: service_healthy ports: - - "8000:8000" + - "${APP_PORT:-8000}:8000" volumes: - # 持久化日志 - ./logs:/app/logs - # 挂载环境变量文件(可选) - ./.env:/app/.env:ro environment: # 应用配置 - - APP_NAME=AI Story Creator - - APP_VERSION=1.0.0 - - APP_HOST=0.0.0.0 + - APP_NAME=${APP_NAME:-MuMuAINovel} + - APP_VERSION=${APP_VERSION:-1.0.0} + - APP_HOST=${APP_HOST:-0.0.0.0} - APP_PORT=8000 - - DEBUG=false + - DEBUG=${DEBUG:-false} - # 数据库配置(使用PostgreSQL) - - DATABASE_URL=postgresql+asyncpg://mumuai:${POSTGRES_PASSWORD:-mumuai_password_2024}@postgres:5432/mumuai_novel + # 数据库配置 + - DATABASE_URL=postgresql+asyncpg://${POSTGRES_USER:-mumuai}:${POSTGRES_PASSWORD:-mumuai_password_2024}@postgres:5432/${POSTGRES_DB:-mumuai_novel} - # PostgreSQL连接池配置 - - DATABASE_POOL_SIZE=30 - - DATABASE_MAX_OVERFLOW=20 - - DATABASE_POOL_TIMEOUT=60 - - DATABASE_POOL_RECYCLE=1800 - - DATABASE_POOL_PRE_PING=True - - DATABASE_POOL_USE_LIFO=True + # PostgreSQL 连接池配置 + - DATABASE_POOL_SIZE=${DATABASE_POOL_SIZE:-30} + - DATABASE_MAX_OVERFLOW=${DATABASE_MAX_OVERFLOW:-20} + - DATABASE_POOL_TIMEOUT=${DATABASE_POOL_TIMEOUT:-60} + - DATABASE_POOL_RECYCLE=${DATABASE_POOL_RECYCLE:-1800} + - DATABASE_POOL_PRE_PING=${DATABASE_POOL_PRE_PING:-True} + - DATABASE_POOL_USE_LIFO=${DATABASE_POOL_USE_LIFO:-True} - - HTTP_PROXY=http://172.16.66.175:7890 - - HTTPS_PROXY=http://172.16.66.175:7890 - - NO_PROXY=localhost,127.0.0.1 + # 代理配置(可选) + - HTTP_PROXY=${HTTP_PROXY:-} + - HTTPS_PROXY=${HTTPS_PROXY:-} + - NO_PROXY=${NO_PROXY:-localhost,127.0.0.1} - # AI服务配置(建议在 .env 文件中设置) - # - OPENAI_API_KEY=${OPENAI_API_KEY} - # - GEMINI_API_KEY=${GEMINI_API_KEY} - # - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - # - DEFAULT_AI_PROVIDER=${DEFAULT_AI_PROVIDER:-gemini} - # - DEFAULT_MODEL=${DEFAULT_MODEL:-gemini-2.5-flash} + # AI 服务配置 + - OPENAI_API_KEY=${OPENAI_API_KEY:-} + - OPENAI_BASE_URL=${OPENAI_BASE_URL:-https://api.openai.com/v1} + - GEMINI_API_KEY=${GEMINI_API_KEY:-} + - GEMINI_BASE_URL=${GEMINI_BASE_URL:-} + - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-} + - ANTHROPIC_BASE_URL=${ANTHROPIC_BASE_URL:-} + - DEFAULT_AI_PROVIDER=${DEFAULT_AI_PROVIDER:-openai} + - DEFAULT_MODEL=${DEFAULT_MODEL:-gpt-4o-mini} + - DEFAULT_TEMPERATURE=${DEFAULT_TEMPERATURE:-0.7} + - DEFAULT_MAX_TOKENS=${DEFAULT_MAX_TOKENS:-2000} - # LinuxDO OAuth配置(⚠️ 必须设置正确的回调地址) - # - LINUXDO_CLIENT_ID=${LINUXDO_CLIENT_ID} - # - LINUXDO_CLIENT_SECRET=${LINUXDO_CLIENT_SECRET} - # - LINUXDO_REDIRECT_URI=${LINUXDO_REDIRECT_URI} + # LinuxDO OAuth 配置 + - LINUXDO_CLIENT_ID=${LINUXDO_CLIENT_ID:-} + - LINUXDO_CLIENT_SECRET=${LINUXDO_CLIENT_SECRET:-} + - LINUXDO_REDIRECT_URI=${LINUXDO_REDIRECT_URI:-} + - FRONTEND_URL=${FRONTEND_URL:-http://localhost:8000} + + # 本地账户登录配置 + - LOCAL_AUTH_ENABLED=${LOCAL_AUTH_ENABLED:-true} + - LOCAL_AUTH_USERNAME=${LOCAL_AUTH_USERNAME:-admin} + - LOCAL_AUTH_PASSWORD=${LOCAL_AUTH_PASSWORD:-admin123} + - LOCAL_AUTH_DISPLAY_NAME=${LOCAL_AUTH_DISPLAY_NAME:-本地管理员} + + # 会话配置 + - SESSION_EXPIRE_MINUTES=${SESSION_EXPIRE_MINUTES:-120} + - SESSION_REFRESH_THRESHOLD_MINUTES=${SESSION_REFRESH_THRESHOLD_MINUTES:-30} restart: unless-stopped healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]