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
+149 -454
View File
@@ -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-配置说明) • [项目结构](#-项目结构)
</div>
@@ -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 KeyOpenAI/Gemini/Anthropic
- Docker 和 Docker Compose
- 至少一个 AI 服务的 API KeyOpenAI/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_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
# 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,258 +196,22 @@ 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
- "8800:8000" # 宿主机:容器
```
## 📁 项目结构
@@ -469,93 +221,42 @@ MuMuAINovel/
├── 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 # 环境变量示例
│ ├── 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
│ │ ── store/ # 状态管理
└── package.json
├── docker-compose.yml # Docker Compose 配置
├── Dockerfile # Docker 镜像构建
└── README.md # 项目说明文档
└── 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)
---
<div align="center">
**如果这个项目对你有帮助,请给个 ⭐️ Star 支持一下**
**如果这个项目对你有帮助,请给个 ⭐️ Star!**
Made with ❤️
+37 -46
View File
@@ -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,21 +39,23 @@ 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
@@ -62,18 +66,12 @@ LOG_BACKUP_COUNT=30
CORS_ORIGINS=["http://localhost:8000","http://127.0.0.1:8000"]
# ==========================================
# AI服务配置
# AI 服务配置(至少配置一个)
# ==========================================
# 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_API_KEY=your_anthropic_api_key_here
@@ -81,29 +79,29 @@ OPENAI_BASE_URL=https://api.openai.com/v1
# 默认 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 回调后重定向)
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
# 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初始化之前)
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 # 慢查询阈值(秒)
+4 -66
View File
@@ -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,7 +54,6 @@ 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]
@@ -98,59 +94,6 @@ async def get_engine(user_id: str):
return _engine_cache[cache_key]
# SQLite模式:每个用户独立的数据库文件
if user_id in _engine_cache:
return _engine_cache[user_id]
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
}
)
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数据库引擎")
return _engine_cache[user_id]
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"}
return result
# 测试数据库连接
AsyncSessionLocal = async_sessionmaker(
+2 -3
View File
@@ -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
+60 -45
View File
@@ -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
- 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')"]