8.9 KiB
8.9 KiB
7-52 LightRAG 图片 OCR 与搜索召回链路加固 v1
创建时间:2026-06-07
当前状态:
DONEOwner:07-ai / knowledge-rag / local-search
上位依据:
design/07-ai/done/7-50-lightrag-knowledge-rag-provider-v1.md
1. 问题结论
这不是 Page AI 某次回答措辞错误,而是 LightRAG 集成链路同时暴露了三层缺口:
- 图片 ingest 缺口:MNote 对图片 source 写入 LightRAG input 时使用 Markdown wrapper,当前 indexed chunk 只有
占位,没有把 MinerU OCR 文本写入 LightRAG chunk / reference。 - 工具契约缺口:
mnote_knowledge_rag_query把rawMetadata.keywords、实体和关系计数暴露给 agent,但没有明确这些只是查询处理元数据,agent 容易把它误判为“source OCR 成功且已返回原文”。 - 搜索召回缺口:
/api/search/documents仍是普通 local search,includeOcr=true目前不代表会查 LightRAG OCR 文本,因此搜索“线程作用域”不会命中目标图片。
2. 现场证据
目标 source:
/mnt/Data1T/Mnote_data/users/mnote-e2e/workspaces/my-space/新页面233155/image copy 6.png
已确认的事实:
- LightRAG source registry 中该图片为
processed,lightRagDocId=doc-781c4b5f39f135886eb6062d8606058e,lightRagFilePath=mnote-d0985c21239b677d-image copy 6.png.md。 kv_store_text_chunks.json中对应 chunk 内容只有# image copy 6.png和 Markdown 图片占位。- 直接调用 LightRAG 的 MinerU parser CLI 解析原 PNG 可以识别出包含“线程作用域”的文本,并生成
blocks.jsonl与 bbox。 /query/data能在 metadata 里返回rawMetadata.keywords.high_level=["线程作用域"],但 references/chunks 没有返回这段 OCR 原文;这只能证明查询分析或图谱元数据命中,不能证明引用文本已暴露。/api/search/documents查询线程作用域返回 0;代码中include_ocr只进入 meta,没有参与搜索。
3. 目标边界
本修复继续保持 7-50 的边界:
- LightRAG 是知识库 OCR / parse / chunk / vector / graph / query provider。
- MNote 不复制 LightRAG 图谱,不把 LightRAG chunk 当正文真相。
- MNote 必须负责 source registry、权限、引用打开、普通搜索入口的边界标注,以及 agent 工具契约。
- 普通搜索可以显示“资料库 OCR 命中”,但不能变成必须依赖 LightRAG 服务才能打开页面或搜索普通 Markdown。
4. 修复方案
P0:工具契约防误判
mnote_knowledge_rag_query 返回给 agent 的 compact result 必须明确:
rawMetadata.keywords、entity count、relation count 只是 provider 查询处理 / retrieval bookkeeping。- OCR 是否真正暴露,以
references[].quote和references[].contentDiagnostics.ocrTextExposed为准。 - 当 quote 为空或只有 Markdown 图片占位时,agent 必须说明“返回引用未暴露 OCR 原文”,不能声称 OCR 成功。
验收:
- 图片 wrapper quote
# image.png\n\n被标记为quoteOnlyImagePlaceholder=true、ocrTextExposed=false。 - Agent 工具 compact result 不再把 raw metadata 当 OCR 成功证据;真实 Page AI 回答必须以该工具契约为准。
P1:图片 ingest 让 OCR 文本进入 LightRAG 可引用内容
图片 source 不能只靠 Markdown wrapper 占位入库。需要二选一并以真实探针定案:
- 优先方案:扩展 LightRAG
/documents/scan支持.png/.jpg/.jpeg/.webp/.bmp/.tif/.tiff,并让 parser routing 对图片走 MinerU。MNote 对图片直接 symlink 原图入inputs/,registry 记录真实图片 source 和 LightRAG basename。 - 兼容方案:如果上游 scan 暂不支持图片,MNote connector 调用 LightRAG parser 能力为图片生成 provider sidecar,并写入包含 OCR 文本的受控
.mdingestion document,同时保留图片 openAction 指向原 source。该.md是 LightRAG staging 派生物,不进入 MNote 文件树正文。
无论选哪条,必须保证:
- LightRAG chunk/reference 中能返回 OCR 文本,不只是图片占位。
blocks.jsonl能通过 registry 反查到原图并生成EvidenceLocator。- reindex 会删除旧 wrapper doc,避免同一图片同时存在“占位 doc”和“OCR doc”。
验收:
- 重新索引目标图片后,
/query/data查询线程作用域的 references/chunks 至少一项包含 OCR 文本。 sourceRootRelativePath仍映射到新页面233155/image copy 6.png。- citation/openAction 打开原图资源,而不是打开派生 wrapper。
P1:reference enrichment 与诊断
当 LightRAG 返回的 reference quote 为空、缺失或仅为图片占位时,MNote connector 应做有界补全:
- 先按
chunk_id查kv_store_text_chunks.json。 - 再按 registry 的
lightRagFilePath查inputs/__parsed__/<file>.parsed/*.blocks.jsonl。 - 对图片占位类 quote,不能直接拿占位去匹配 sidecar;应允许按 query terms / block text 补最相关 OCR block。
- 返回
contentDiagnostics,标明quoteSource=chunk|sidecar|missing|placeholder、ocrTextExposed、locatorSource。
验收:
- OCR sidecar 已存在但 chunk 未带内容时,工具仍能返回一段真实 OCR quote,并标记来源为
sidecar。 - 若 sidecar 不存在,工具返回明确诊断,不把 metadata 当证据。
P1:普通搜索 includeOcr=true 语义落地
includeOcr=true 不能继续是 no-op。推荐先做“普通搜索 + 资料库 OCR 有界补充”:
- 普通 Markdown / title / resource metadata 仍走本地轻索引。
- 当
includeOcr=true且普通结果不足 limit 时,追加查询 LightRAG source registry + sidecar/chunk 的 OCR 文本结果。 - 搜索结果必须标注
boundary.kind=ordinary_local_search_with_knowledge_ocr,单条结果标注matchSource=knowledge_rag_ocr。 - LightRAG 不可用时普通搜索不失败,只设置
degraded=true、degradedReason=knowledge_rag_unavailable。
验收:
/api/search/documents查询线程作用域且includeOcr=true能返回目标图片或 owner page。includeOcr=false保持原普通搜索语义。- 返回结果包含可打开的 resource locator/citation,不只是一条不可点击文本。
P2:健康检查与 UI 暴露
资料库状态面板需要区分:
- source 是否 registered。
- LightRAG doc 是否 processed。
- OCR text 是否进入 chunk/reference。
- sidecar 是否存在且可用于 locator。
- 普通搜索是否能通过
includeOcr召回。
验收:
- 对目标图片能显示“processed but OCR text not exposed in reference/chunk”这类可操作状态,而不是只有绿灯。
5. 执行 Checklist
- P0 工具契约:compact reference 增加
contentDiagnostics并补单测。 - P0 agent 工具契约 smoke:确认 compact result 不再把 raw metadata 当 OCR 成功证据。
- P1 ingest spike:验证 LightRAG 直接 scan 图片扩展 vs MNote 调 parser 生成 OCR ingestion doc,选择一条实现。
- P1 reindex migration:删除旧图片 wrapper doc 后重新索引目标图片。
- P1 reference enrichment:sidecar/chunk/query term 补 quote,返回明确
quoteSource。 - P1 搜索:
includeOcr=true追加 knowledge OCR 命中,并保持 LightRAG 不可用时普通搜索降级。 - P1 browser/API smoke:
线程作用域在 knowledge-rag 和/api/search/documents两条入口都可召回并可打开来源。 - P2 状态 UI:把 OCR 文本是否真正进入 reference/chunk 暴露成诊断项。
7. 验收证据
2026-06-07 已完成目标图片重建索引:
- registry:
新页面233155/image copy 6.png->lightRagDocId=doc-ac03e578a6c6af7eb0a3224276e4b954,lightRagFilePath=mnote-d0985c21239b677d-image copy 6.[mineru].png,lightRagStatus=processed。 - LightRAG status diagnostics:
directImageScan=true、sidecarExists=true、ocrTextExposed=true、sidecarMeaningfulBlocks=2。 /api/knowledge-rag/query查询线程作用域:首条 reference 映射到新页面233155/image copy 6.png,quoteSource=sidecar,contentDiagnostics.ocrTextExposed=true,locatorDegraded=false,quote 含线程作用域。/api/search/documents查询线程作用域且includeOcr=true:返回 1 条knowledge_rag_ocr命中,path 为新页面233155/image copy 6.png,snippet 含线程作用域,boundary 为ordinary_local_search_with_knowledge_ocr。/api/search/documents查询线程作用域且includeOcr=false:返回 0 条,boundary 保持ordinary_local_search,证明普通搜索未被强依赖 LightRAG。
8. 当前禁止事项
- 不把
rawMetadata.keywords当 source OCR 证据。 - 不恢复 LiteParse 为默认 fallback。
- 不把 OCR 文本写回用户 Markdown 正文。
- 不让普通搜索强依赖 LightRAG 才能返回 Markdown 页面结果。
- 不保留同一图片的旧占位 wrapper doc 与新 OCR doc 双索引状态。