feat: 初始提交
This commit is contained in:
186
docs/RAG.md
Normal file
186
docs/RAG.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# RAG + LLM + 向量化系统设计文档
|
||||
|
||||
## 一、系统目标
|
||||
|
||||
构建一个可持续生成长篇小说的系统,满足以下需求:
|
||||
|
||||
1. 支持多章节、多人物、多阵营的复杂叙事
|
||||
2. 保持世界观、人物关系、剧情逻辑一致
|
||||
3. 每章生成后可向量化存储,用于下一章 RAG 检索
|
||||
4. 支持章节修改/删除时,向量库同步更新
|
||||
5. 可控 Prompt 输入,确保写作风格统一
|
||||
|
||||
---
|
||||
|
||||
## 二、信息层级设计
|
||||
|
||||
| 层级 | 内容 | 数据格式 | 是否 RAG 检索 | 功能 |
|
||||
| --------- | ---------------- | ------------------------------ | --------- | --------------- |
|
||||
| L1 世界蓝图 | 世界设定、人物档案、规则、阵营 | JSON | ❌ 否 | 提供固定约束,保证逻辑一致性 |
|
||||
| L2 剧情记忆 | 已生成章节的分块文本 | 向量库(FAISS / Qdrant / Weaviate) | ✅ 是 | 检索与当前章节相关的情节、事件 |
|
||||
| L3 章节摘要 | 章节标题 + 摘要 + 主要人物 | JSON / Markdown | ✅ 是 | 检索辅助,缩小上下文范围 |
|
||||
| L4 上下文桥接 | 上一章摘要 + 结尾 500 字 | Markdown | ✅ 是 | 保持衔接自然,情绪与逻辑连贯 |
|
||||
| L5 当前章节输入 | 标题、摘要、写作指令 | 自然语言 | ❌ 否 | 明确写作目标与情节点 |
|
||||
|
||||
---
|
||||
|
||||
## 三、章节生成流程
|
||||
|
||||
### Step 1:输入章节目标
|
||||
|
||||
* 当前章节标题 + 摘要 + 写作指令
|
||||
* 系统接收后,准备上下文
|
||||
|
||||
### Step 2:RAG 检索上下文
|
||||
|
||||
1. **检索剧情记忆层**
|
||||
|
||||
* 根据章节标题、摘要或人物/场景标签检索最相关 chunk
|
||||
* 建议 top-K = 5
|
||||
|
||||
2. **检索章节摘要层**
|
||||
|
||||
* 辅助判断要引用的前后章节
|
||||
* 可选 top-K = 3–5
|
||||
|
||||
### Step 3:拼接 Prompt
|
||||
|
||||
```
|
||||
【世界蓝图】(JSON)
|
||||
{蓝图}
|
||||
|
||||
【上一章摘要】
|
||||
{上一章摘要}
|
||||
|
||||
【上一章结尾】
|
||||
{上一章结尾500字}
|
||||
|
||||
【检索到的剧情上下文】(Markdown)
|
||||
{相关chunk文本拼接}
|
||||
|
||||
【当前章节目标】
|
||||
标题:{chapter_title}
|
||||
摘要:{chapter_summary}
|
||||
写作要求:{writing_notes}
|
||||
```
|
||||
|
||||
### Step 4:调用 LLM 生成章节
|
||||
|
||||
* 输出章节正文
|
||||
|
||||
---
|
||||
|
||||
## 四、章节向量化设计
|
||||
|
||||
### Step 1:分块策略
|
||||
|
||||
* **chunk_size**:300–600 字
|
||||
* **chunk_overlap**:80–130 字
|
||||
* **切分逻辑**:
|
||||
|
||||
1. 首选 LangChain `RecursiveCharacterTextSplitter`,按照段落/句子逐级回退切分,自动去除冗余空白
|
||||
2. 未安装 LangChain 时退回到内置的段落 + 标点切分策略
|
||||
* 每块保证语义完整,多句多段落
|
||||
|
||||
### Step 2:附加 metadata
|
||||
|
||||
* chapter_number
|
||||
* chapter_title
|
||||
* chunk_id
|
||||
* tags(人物、场景、事件,可选)
|
||||
|
||||
### Step 3:向量化存储
|
||||
|
||||
```python
|
||||
for chunk in chunks:
|
||||
vector_store.upsert({
|
||||
"id": unique_id,
|
||||
"text": chunk_text,
|
||||
"embedding": get_embedding(chunk_text),
|
||||
"metadata": {
|
||||
"chapter": chapter_number,
|
||||
"title": chapter_title,
|
||||
"chunk_id": chunk_id,
|
||||
"tags": [人物, 场景]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、章节修改与删除策略
|
||||
|
||||
1. **删除操作**
|
||||
|
||||
* 根据 `chapter_number` 或 `chapter_id` 删除对应向量块
|
||||
* 避免下一章引用过时内容
|
||||
|
||||
```python
|
||||
vector_store.delete(filter={"chapter": 12})
|
||||
```
|
||||
|
||||
2. **修改操作**
|
||||
|
||||
* 删除旧 chunk
|
||||
* 生成新章节
|
||||
* 分块向量化并插入数据库
|
||||
* 更新章节摘要索引
|
||||
|
||||
3. **版本控制(可选)**
|
||||
|
||||
* 每个 chunk 增加 `version` 字段
|
||||
* 保留历史版本用于调试或回滚
|
||||
|
||||
---
|
||||
|
||||
## 六、检索策略
|
||||
|
||||
* **上一章摘要 + 结尾**:高权重
|
||||
* **RAG检索相关 chunk**:中权重
|
||||
* **蓝图 JSON**:不需检索,直接作为规则约束
|
||||
* **标签筛选**:人物、场景、事件标签可用于精准检索
|
||||
|
||||
---
|
||||
|
||||
## 七、Prompt 格式建议
|
||||
|
||||
* **蓝图**:JSON
|
||||
* **检索上下文**:Markdown
|
||||
* **章节目标**:自然语言
|
||||
* **系统指令**:固定模板,约束风格与逻辑
|
||||
|
||||
---
|
||||
|
||||
## 八、数据存储设计
|
||||
|
||||
| 数据类型 | 存储形式 | 用途 |
|
||||
| ------------- | --------------- | ------------ |
|
||||
| 蓝图 JSON | 文件 / 数据库 | 人物、世界观、规则约束 |
|
||||
| 剧情 chunk | 向量数据库 | RAG 检索,保持上下文 |
|
||||
| 章节摘要 | JSON / Markdown | 辅助检索与上下文引用 |
|
||||
| 上一章结尾 | Markdown | Prompt桥接衔接自然 |
|
||||
| 标签 / Metadata | 向量库附加字段 | 精准检索 |
|
||||
|
||||
---
|
||||
|
||||
## 九、扩展优化建议
|
||||
|
||||
1. **动态检索 top-K**
|
||||
|
||||
* 章节少 → K 大
|
||||
* 章节多 → K 小,保证 token 限制
|
||||
|
||||
2. **Chunk 标签化**
|
||||
|
||||
* 每块 chunk 增加人物/场景/事件标签
|
||||
* 检索时可加 filter,精确上下文
|
||||
|
||||
3. **自动摘要生成**
|
||||
|
||||
* 每章生成后自动提炼摘要
|
||||
* 更新章节摘要索引,便于下一章检索
|
||||
|
||||
4. **可选多版本管理**
|
||||
|
||||
* 增加 `version` 字段
|
||||
* 支持修改回滚
|
||||
153
docs/novel_workflow.md
Normal file
153
docs/novel_workflow.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Arboris 长篇小说自动化流水线说明
|
||||
|
||||
本文档描述 Arboris 在「从概念到章节成稿」过程中的完整自动化流程、涉及的提示词、上下文载荷与模型参数。
|
||||
|
||||
---
|
||||
|
||||
## 1. 总体流程概览
|
||||
|
||||
```
|
||||
项目创建 → 概念对话 → 蓝图生成/编辑 → 章节生成 → 版本评审/选择
|
||||
↑ ↓
|
||||
(持续迭代) ← 手动编辑 ← 向量入库 ← 摘要提取 ← RAG 检索支撑下一章
|
||||
```
|
||||
|
||||
关键能力由以下组件协作完成:
|
||||
|
||||
| 阶段 | 主要接口 | 提示词 ID | 模型温度 | 说明 |
|
||||
|------|----------|-----------|----------|------|
|
||||
| 概念对话 | `POST /api/novels/{id}/concept/converse` | `concept`(附带 JSON schema 指令) | 0.8 | 引导用户梳理世界观与剧情要素 |
|
||||
| 蓝图生成 | `POST /api/novels/{id}/blueprint/generate` | `screenwriting` | 0.3 | 基于概念对话整理正式蓝图 |
|
||||
| 章节生成 | `POST /api/writer/novels/{id}/chapters/generate` | `writing` | 0.9 | 结合蓝图、前情摘要与 RAG 结果生成章节草稿 |
|
||||
| 章节评审 | `POST /api/writer/novels/{id}/chapters/evaluate` | `evaluation` | 0.3 | 对全部候选版本给出改进建议 |
|
||||
| 摘要提取 | 调用 `LLMService.get_summary`(生成/编辑/选择时触发) | `extraction` | 0.15 | 对最终正文提炼真实摘要 |
|
||||
|
||||
所有提示词原文保存在 `backend/prompts/` 目录,可由 Prompt 管理界面动态更新。
|
||||
|
||||
---
|
||||
|
||||
## 2. 阶段详解
|
||||
|
||||
### 2.1 概念阶段(Concept Converse)
|
||||
|
||||
- **入口**:`POST /api/novels/{project_id}/concept/converse`
|
||||
- **上下文**:
|
||||
- 历史概念对话(数据库 `NovelConversation` 表)
|
||||
- 用户本轮输入(JSON)
|
||||
- **提示词**:`concept` + `JSON_RESPONSE_INSTRUCTION`(强制返回结构化 JSON)
|
||||
- **LLM 参数**:温度 0.8,超时 240 秒
|
||||
- **输出**:`ConverseResponse`,包含 AI 建议、UI 控件描述以及对话状态;当 `is_complete` 为真时,允许进入蓝图阶段。
|
||||
|
||||
### 2.2 蓝图生成(Blueprint)
|
||||
|
||||
- **入口**:`POST /api/novels/{project_id}/blueprint/generate`
|
||||
- **上下文**:
|
||||
- 概念对话中成功解析的用户/助手消息(提取自存档 JSON)
|
||||
- **提示词**:`screenwriting`
|
||||
- **LLM 参数**:温度 0.3,超时 480 秒
|
||||
- **输出**:结构化蓝图 JSON,映射到 `NovelBlueprint`(世界观、角色、章节纲要等)
|
||||
- **后续**:
|
||||
- `PATCH /api/novels/{project_id}/blueprint` 可局部修改蓝图
|
||||
- `save_blueprint` 路径用于手动覆盖生成结果
|
||||
|
||||
### 2.3 章节生成(Writer.GenerateChapter)
|
||||
|
||||
- **入口**:`POST /api/writer/novels/{project_id}/chapters/generate`,请求体 `GenerateChapterRequest`
|
||||
- **上下文组装**:
|
||||
1. **蓝图**:剔除章节细节字段(章节摘要、对话、角色动态等),仅保留世界观框架。
|
||||
2. ~~**已完成章节摘要**:逐章真实摘要;若缺失则调用 `get_summary` 以 `extraction` 提示词生成。~~
|
||||
3. **上一章桥接**:上一章真实摘要 + 正文末尾 500 字。
|
||||
4. **RAG 检索结果**(由 `ChapterContextService` 提供):
|
||||
- 查询向量来源:章节标题 + 纲要摘要 + 可选写作指令 → `LLMService.get_embedding`
|
||||
- 文本来源:`VectorStoreService.query_chunks/query_summaries`(若数据库不支持向量函数,则回退到应用层余弦距离排序)
|
||||
- 默认 Top-K:正文片段 5 条、章节摘要 3 条(可通过环境变量调整)
|
||||
5. **写作提示词**:`writing`
|
||||
- **LLM 参数**:温度 0.9,超时 600 秒,候选版本数默认为 3(可通过系统配置或环境变量覆盖)
|
||||
- **输出**:章节候选版本数组(JSON),写入 `ChapterVersion`;`Chapter` 状态设置为 `generating`。
|
||||
|
||||
> **注意**:章节上下文生成失败(如无向量库)时,流程会降级为“蓝图 + 历史摘要”模式继续执行。
|
||||
|
||||
### 2.4 章节版本选择 / 手动编辑
|
||||
|
||||
- **选择版本**:`POST /api/writer/novels/{project_id}/chapters/select`
|
||||
- 选定后调用 `get_summary`(温度 0.15)生成真实摘要
|
||||
- 触发 `ChapterIngestionService.ingest_chapter` 切分正文、摘要并写入向量库
|
||||
|
||||
- **手动编辑**:`POST /api/writer/novels/{project_id}/chapters/edit`
|
||||
- 更新正文、重算摘要
|
||||
- 同样触发向量入库,以覆盖旧 chunk
|
||||
|
||||
### 2.5 章节评审(Evaluation)
|
||||
|
||||
- **入口**:`POST /api/writer/novels/{project_id}/chapters/evaluate`
|
||||
- **上下文**:
|
||||
- 蓝图(完整结构)
|
||||
- 当前章节全部版本内容(按创建时间排序)
|
||||
- **提示词**:`evaluation`
|
||||
- **LLM 参数**:温度 0.3,超时 360 秒
|
||||
- **输出**:评审报告文本,写入 `ChapterEvaluation`。
|
||||
|
||||
### 2.6 摘要提取(Summary Extraction)
|
||||
|
||||
- **触发点**:
|
||||
- 章节自动生成阶段(“前情摘要缺失”场景)
|
||||
- 章节版本确认
|
||||
- 手动编辑保存
|
||||
- **调用**:`LLMService.get_summary`
|
||||
- **提示词**:`extraction`
|
||||
- **LLM 参数**:温度 0.15(默认 0.2,在调用处覆盖),超时 180 秒
|
||||
- **目标**:为后续章节生成提供真实摘要,避免使用纲要内容。
|
||||
|
||||
---
|
||||
|
||||
## 3. 向量化与 RAG 细节
|
||||
|
||||
### 3.1 切分策略
|
||||
|
||||
- 默认使用 **LangChain `RecursiveCharacterTextSplitter`**:
|
||||
- `chunk_size = settings.vector_chunk_size`(默认 480)
|
||||
- `chunk_overlap = min(settings.vector_chunk_overlap, chunk_size // 2)`(默认 120)
|
||||
- 分隔符优先级:双换行 > 单换行 > 句号/问号/感叹号 > 逗号 > 空格 ➜ 确保靠近语义边界
|
||||
- 若未安装对应依赖,则回退到内置段落 + 标点切分算法,配合日志提示。
|
||||
- 摘要文本也使用同一套流程(通常为单条向量)。
|
||||
|
||||
### 3.2 向量存储
|
||||
|
||||
- **后端服务**:`VectorStoreService`
|
||||
- **存储实现**:libsql(可本地 `file:`,亦可云端),需手动配置 `VECTOR_DB_URL`
|
||||
- **表结构**:
|
||||
- `rag_chunks`(正文分块):`id`、`project_id`、`chapter_number`、`chunk_index`、`chapter_title`、`content`、`embedding`、`metadata`
|
||||
- `rag_summaries`(章节摘要):`id`、`project_id`、`chapter_number`、`title`、`summary`、`embedding`
|
||||
- **检索策略**:
|
||||
- 优先使用 libsql 的 `vector_distance_cosine`;若未启用,回退到 Python 端计算余弦距离(排序后截取 Top-K)。
|
||||
- 查询向量由 `LLMService.get_embedding` 生成,支持 OpenAI 与 Ollama(通过 `EMBEDDING_PROVIDER` 切换)。
|
||||
|
||||
### 3.3 向量生命周期
|
||||
|
||||
- **插入/更新**:章节版本被确认或编辑保存后,先删除旧向量,再批量写入最新正文/摘要分块。
|
||||
- **删除**:`delete_chapters` 接口会同步清理向量库,防止后续 RAG 读到过期内容。
|
||||
- **日志**:向量 service 与 ingestion service 会在关键阶段输出日志(初始化、切分数量、写入成功/失败),便于排查。
|
||||
|
||||
---
|
||||
|
||||
## 4. 运行依赖与配置总览
|
||||
|
||||
| 配置项 | 说明 | 默认/来源 |
|
||||
|--------|------|-----------|
|
||||
| `OPENAI_*` | 默认生成模型配置 | `.env` 或系统配置表 |
|
||||
| `EMBEDDING_PROVIDER` | 嵌入提供方(`openai` / `ollama`) | `.env` |
|
||||
| `EMBEDDING_MODEL` / `OLLAMA_EMBEDDING_MODEL` | 具体嵌入模型名 | `.env` |
|
||||
| `VECTOR_DB_URL` | libsql 数据库地址(支持 `file:`) | `.env` |
|
||||
| `VECTOR_TOP_K_CHUNKS` / `VECTOR_TOP_K_SUMMARIES` | 检索数量 | `.env` / 系统配置 |
|
||||
| `WRITER_CHAPTER_VERSION_COUNT` | 章节候选版本数 | 系统配置 / 环境变量 |
|
||||
|
||||
确保在部署环境中提前安装新依赖:
|
||||
|
||||
```bash
|
||||
pip install -r backend/requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
如需进一步开发,请配合此文档查看对应模块的实现文件(`backend/app/services/*`、`backend/app/api/routers/*`、`backend/prompts/*`),保持提示词与代码逻辑的一致性。
|
||||
|
||||
Reference in New Issue
Block a user