Files
mnote/design/mindmap-ai-v2.md
T
2026-01-10 10:35:21 +08:00

295 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Mindmap AI v2 实施计划(文档大纲 / 小结带引用 / 搜索补全)
> 目标:把当前“仅能对话并返回 Markdown 列表”的 AI,升级为**可读可用**的“文档驱动思维导图”能力:
> 1) PDF/Word/PPT 按目录与大纲生成思维导图,并且节点可跳转到对应页/幻灯片;
> 2) 基于文档内容生成小结/知识点,并附带可点击引用(页码/链接);
> 3) 支持在节点上“搜索/查询后补完内容”(RAG + 可选联网检索)。
---
## 0. 现状与问题
### 0.1 当前实现(代码落点)
- `wolai-frontend/src/components/editor/blocks/MindmapSidebar.tsx`:AI 面板目前是“本地 Ollama /api/chat 流式输出 + Markdown 解析为节点”。
- `services/ingest_service`:已具备 **Supabase -> MinerU -> LightRAG** 的自动入库链路(用于全文检索/RAG)。
- `services/rag_gateway`:封装了对 LightRAG 的 HTTP 调用(`/query``/query/data`),可作为统一 RAG 网关。
- `wolai-frontend/src/app/onlyoffice/page.tsx`OnlyOffice 文档查看/编辑入口(目前用于 docx/pptx/xlsx 等)。
- `wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx`:节点超链接通过 `SET_NODE_HYPERLINK` 直接写入 URL。
### 0.2 为什么“离想象差很远”
当前 AI 只有“生成文本 -> 解析成节点”的能力,缺少:
- **与文档绑定**:没有把 PDF/Word/PPT 的结构(目录/标题层级)变成导图;
- **可验证的引用**:没有“这句话来自第几页/哪一段”,因此难以沉浸式阅读与回溯;
- **补全的检索依据**:没有把“补完节点”变成“基于检索结果 + 引用”输出,容易胡编;
- **工程化形态**:没有任务、进度、缓存、失败重试、可复用数据结构。
---
## 1. 用户故事与验收标准(以你的测试文件为准)
### 1.1 文档按目录/大纲生成导图(PDF/Word/PPT
**用户故事**
- 我上传(或选中)一个文档(PDF/Word/PPT),点击“按大纲生成思维导图”,自动生成多级节点。
- 我点击任意节点,可以跳转到该文档对应页(PDF)或对应位置(Word/PPT 至少能定位页/提示页码,理想是直接跳转)。
**验收**
-`wolai-frontend/test/卤化反应原理_1-9.pdf`
- 能生成至少 2 级结构(中心主题 -> 章节 -> 小节)。
- 至少章节级节点带可点击引用(页码/链接)。
- 点击节点后打开的 URL 包含 `#page=<n>`PDF 以浏览器内建查看器为准)。
### 1.2 小结/知识点生成(带链接引用)
**用户故事**
- 我选中“生成小结”,AI 输出“关键结论/反应机理/注意点”,每条结论附带引用(页码链接或文档片段来源)。
**验收**
-`wolai-frontend/test/卤化反应原理测试.pdf`
- 生成不少于 N(建议 8)条要点;
- 每条要点至少 1 个引用(页码/链接);
- 引用能点击打开对应 PDF 页。
### 1.3 搜索/查询后补完节点内容
**用户故事**
- 我选中一个/多个节点,输入“补完方向/问题”,AI 基于检索结果补充子节点或备注,附带引用。
**验收**
- 对同一 PDF 文档:
- “补完”后的内容至少包含 3 个子节点或 1 段结构化备注;
- 结论带引用(页码/链接);
- 不允许“无引用的长篇自由发挥”(默认强制引用)。
---
## 2. 总体方案(推荐架构)
核心原则:**先结构化,再生成**;**先检索证据,再写结论**;**引用是第一公民**。
### 2.1 三层能力拆分
1) **文档解析层(Document -> Outline/Chunks**
- 输出:`DocOutline`(层级标题 + 页码/位置)与 `DocChunks`(可引用文本块)。
2) **RAG/生成层(Outline/Chunks -> Mindmap/Summary/Expansion**
- 输出:思维导图节点树(含引用)、小结节点(含引用)、补全子节点(含引用)。
3) **渲染/交互层(Mindmap UI**
- 节点点击:打开引用的文档页/位置;支持“查看引用”“展开更多证据”。
### 2.2 数据来源优先级(PDF
按可靠性排序:
1) PDF 自带书签/目录(`pypdf` outline)→ **最靠谱**(本次 `卤化反应原理_1-9.pdf` 没有 outline
2) MinerU 解析结果(建议开启 `return_content_list`/`return_middle_json`)→ 可拿到更结构化的块,并可能带页信息
3) `pypdf` 分页提取文本 + 标题检测(规则 + LLM 辅助)→ 兜底方案
---
## 3. 关键数据结构(建议新增/统一)
### 3.1 引用结构 `NodeRef`
用于节点的“可点击跳转”和“可追溯引用”:
```ts
export type NodeRef = {
kind: "pdf" | "docx" | "pptx" | "url";
assetId?: string; // 优先用 assetId,避免 URL 过期
fileUrl?: string; // public URL 或 signed URL(兜底)
page?: number; // PDF 页码(1-based
slide?: number; // PPT 页码/幻灯片序号(1-based
title?: string; // 引用标题(例如“2.1 卤化机理”)
snippet?: string; // 可选:引用片段
};
```
### 3.2 节点存储方式
- **短链**(推荐):`node.data.refs: NodeRef[]`(自定义字段)
- **展示用超链接**:仍使用 `SET_NODE_HYPERLINK` 写入一个可点击 URL(例如 PDF `...#page=3`
- **引用详情**:写入 `node.data.note``node.data.data.note`(保持兼容)为 Markdown
- `- [p3] 证据片段...`
- `- [p5] ...`
说明:simple-mind-map 对 `data` 的自定义字段容忍度较高,但要确保序列化/反序列化后不丢字段。
---
## 4. 具体功能方案
### 4.1 “按目录/大纲生成思维导图”
#### 4.1.1 API(建议新增)
新增 Next Route(前端同域,避免跨域/鉴权麻烦):
- `POST /api/mindmap-ai/outline-to-mindmap`
- 入参:`{ assetId, documentId?, prefer: "bookmark" | "mineru" | "heuristic" }`
- 出参:`{ mindmapData, outline, refsSummary }`
后台实现可以优先走 `services/ingest_service` 或直接复用其逻辑(后续可沉到 `wolai-backend`)。
#### 4.1.2 解析策略(对测试 PDF 友好)
因为 `卤化反应原理_1-9.pdf` 没有书签:
1) 使用 `pypdf` 逐页提取文本(已有代码可参考 `services/ingest_service/app/services/auto_indexer.py`);
2) 对每页文本做标题候选抽取(规则:编号标题如 `1.` `1.1` `(一)` 等 + 行长/标点密度);
3) 用 LLM(可走 Ollama)把候选标题整理为层级结构,并返回 `{title, level, page}`
4) 转换为 mindmap:中心主题=文件名/第一页大标题,子节点=章节;每个章节节点写入 hyperlink `fileUrl#page=<page>`
#### 4.1.3 Word/PPT
阶段 1 先保证:
- Word/PPT 也能“生成大纲导图”,但跳转能力允许降级:
- 若 OnlyOffice 支持跳转 API:实现真实跳转;
- 若不支持:点击节点打开文档,并弹出“建议跳转页码/幻灯片序号”的提示(至少可用)。
(后续再把 Word/PPT 的“位置”提升为可跳转锚点)
---
### 4.2 “小结/知识点生成(带引用)”
#### 4.2.1 证据来源:优先 LightRAG,其次本地分页文本
优先走 `services/rag_gateway`
- `POST /rag/query`:拿到 `response + references`LightRAG 会返回引用列表)
- `POST /rag/graph`:拿结构化分块/引用(用于“点开看证据/更多片段”)
如果 LightRAG 返回引用信息不足以映射到页码,需要补齐“页码映射”:
- 方案 A(推荐):在入库时把“每页”作为 chunk,并把 `file_source + page` 写入可回传字段(需要改 ingest_service 装饰文本或分块入库方式)
- 方案 B(兜底):在本地用 `pypdf` 重新做“分页文本”,对引用片段做模糊匹配定位页码
#### 4.2.2 输出形态
在 Mindmap 里提供两种落地方式:
- 生成到“备注”(适合长文本 + 引用列表)
- 生成到“子节点”(每条要点一个子节点,子节点携带 `refs` 和 hyperlink
默认要求:**每条要点至少 1 个引用**(无引用则标记为“待核验”,并提示用户继续检索)。
---
### 4.3 “搜索/查询后补完节点内容”
#### 4.3.1 两种检索源(可配置)
1) **本地文档库检索**LightRAG(默认)
2) **联网检索**SearxNG(本仓库已存在 Docker 服务,可直接用)
##### 4.3.1.1 SearxNG 接入约定(基于仓库现状)
仓库已存在 `services/searxng-docker/.env`,其中包含:
- `SEARXNG_BASE_URL=http://127.0.0.1:8889`
- `SEARXNG_API_TOKEN=...`
建议接入方式:
- 前端**不要**直连 searxng(避免 token 暴露),通过 Next Route 代理:
- `POST /api/search/searxng`
- 入参:`{ q: string, count?: number, lang?: string }`
- 出参:`{ results: Array<{ title: string, url: string, snippet?: string, engine?: string }>} `
SearxNG 查询接口(推荐 JSON):
- `GET ${SEARXNG_BASE_URL}/search?q=<query>&format=json&language=zh-CN&categories=general&safesearch=1`
鉴权策略(需要实际跑通后确定,做成可配置):
- 方案 A:不加鉴权(本地内网服务)
- 方案 B:携带 token(例如 `X-API-Key` / `Authorization: Bearer` 之一;以你当前 searxng 配置为准)
> 注意:SearxNG 返回结果字段不同版本略有差异,后端代理层要做一次“结果归一化”和去重(按 url)。
#### 4.3.2 交互与输出
- 输入:用户选中节点 + “补完问题/方向”
- 系统 prompt 固定:强制输出结构化(Markdown 列表)+ 引用
- 输出策略:
- 子节点补全:把回答拆成 3~8 个子节点追加
- 备注补全:写入 note,并附引用列表
---
## 5. 前端 UI 改造建议(MindmapSidebar 的 AI 面板)
把当前“模型/地址/系统提示”改为“面向功能的工作流”,保留“高级设置”折叠:
1) **从文档生成**
- 选择文档资产(assetId)+ 生成按钮 + 进度(解析中/生成中/完成)
2) **生成小结**
- 可选:作用范围(整篇/选中节点对应章节)+ 要点数量 + 输出到(子节点/备注)
3) **补完节点**
- 输入框 + 检索源选择 + 输出到(子节点/备注)
同时在节点右键/工具栏增加:
- “打开引用”
- “查看引用(弹窗列出页码/片段)”
---
## 6. 工程落地步骤(里程碑)
> 建议按“先可用,再做强”的顺序推进。
### M1(1~2 天):PDF 大纲导图(可跳页)
- [ ] 新增 `/api/mindmap-ai/outline-to-mindmap`(仅支持 PDF
- [ ] 实现 “pypdf 分页文本 + 标题候选 + LLM 整理层级”
- [ ] MindmapSidebar 增加“从 PDF 生成导图”入口(基于 assetId)
- [ ] 节点写入 hyperlink`publicFileUrl#page=<n>`
- [ ] pw-tests:导入 `卤化反应原理_1-9.pdf`,断言生成节点数与 `#page=` 链接存在,并截图
### M2(2~3 天):小结生成(强制引用)
- [ ] 接入 `services/rag_gateway``/rag/query`(前端通过 Next Route 代理)
- [ ] 让小结输出“要点 + 引用”
- [ ] 引用映射到 `#page=`(先用本地分页匹配兜底)
- [ ] pw-tests:对 `卤化反应原理测试.pdf` 生成 N 条小结并截图
### M3(2~4 天):搜索补全节点(RAG)
- [ ] AI 面板增加“补完节点”模式
- [ ] 选中节点作为上下文,拼接检索 query:LightRAG(文档内)+ SearxNG(联网)
- [ ] 新增 `POST /api/search/searxng` 作为代理(隐藏 token + 统一返回格式)
- [ ] 将 searxng 的 `title/url/snippet` 作为“外部证据”,与 LightRAG 引用一起喂给模型生成
- [ ] 防胡编:无引用则提示“需要更多证据/换关键词”
- [ ] pw-tests:选中某节点补完,校验新增子节点与引用
### M4(可选):Word/PPT 真跳转
- [ ] 调研 OnlyOffice 是否支持跳页/跳幻灯片 API(不支持则维持降级)
- [ ] 若支持:在 `/onlyoffice` 页面接收 `page/slide` 参数并调用 DocsAPI 跳转
---
## 7. 风险与对策
- **PDF 无书签(当前测试文件就是)**:必须做“文本标题抽取 + LLM 结构化”的兜底。
- **页码引用难**:短期先用“本地分页匹配”;中期把“页级分块”纳入入库,引用直接带页码。
- **URL 过期/权限**:优先存 `assetId`,点击时再换取可用 URL(必要时扩展 `/api/media/signed-url` 支持 assetId)。
- **性能**:解析/生成尽量放到后端(Next Route 或 wolai-backend),前端只跑轻量 UI;长任务使用 job 表/轮询。
---
## 8. 与 BlockNote 的集成点(后续)
- Slash Menu 可加入口(例如 `/mind ai``/mind from pdf`),插入/更新块可用 BlockNote 的 `insertOrUpdateBlockForSlashMenu``editor.updateBlock`(见 BlockNote 官方文档的 Suggestion Menus 示例)。