Files
mnote/recycle/design/mindmap-ai-v2.md
T
2026-04-13 19:21:42 +08:00

13 KiB
Raw Blame History

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.tsxOnlyOffice 文档查看/编辑入口(目前用于 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

用于节点的“可点击跳转”和“可追溯引用”:

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.notenode.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 + referencesLightRAG 会返回引用列表)
  • 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)
  • 节点写入 hyperlinkpublicFileUrl#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 的 insertOrUpdateBlockForSlashMenueditor.updateBlock(见 BlockNote 官方文档的 Suggestion Menus 示例)。