update:1.更新readme.txt

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