Skip to content

RAG 知识检索 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与容量特性
  8. 知识库管理端到端流程
  9. [长期记忆与 RAG 集成](#长期记忆与 rag 集成)
  10. 向量存储与索引机制
  11. 混合检索引擎
  12. 配置项与监控
  13. 故障排除指南
  14. 结论

引言 ​

本文件面向“RAG(检索增强生成)知识检索系统”的完整技术文档,覆盖从文档解析、文本分块、向量嵌入、索引构建、向量存储、混合检索到长期记忆注入的全链路。系统采用双进程架构:Chrome 扩展端通过本地 HTTP/WebSocket 调用 Agent 端的 RAG 能力;Agent 端负责实际的文件解析、向量化、索引与检索。所有实现以 agent 源码为准,版本为 2.3.1。

项目结构 ​

RAG 相关代码集中在 agent/src/rag,长期记忆在 agent/src/memory,两者通过共享的 embedding provider 和关键词匹配逻辑协作。

graph TB
subgraph "Agent 端"
RAG["RAG 子系统<br/>config / manager / searcher / store / embedding"]
MEMORY["长期记忆子系统<br/>service / injection / embedding-config"]
DETECT["依赖检测与安装<br/>detect / install"]
end
subgraph "外部依赖"
VECTRA["Vectra 本地向量索引"]
EMBED["Embedding Provider<br/>本地 BGE / OpenAI 兼容"]
end
RAG --> VECTRA
RAG --> EMBED
MEMORY --> EMBED
DETECT --> RAG

图表来源

章节来源

核心组件 ​

  • RAG 配置中心:定义数据根目录、知识库注册表、默认 embedding 配置、默认分块参数、默认检索参数、解析器扩展名路由。
  • RagManager:知识库生命周期管理、文档导入、重建索引、进度上报、安全校验、URL 导入策略。
  • Searcher:语义搜索 + 关键词命中增强 + 阈值过滤 + 旁路探测。
  • VectraStore:Vectra 本地索引适配器,封装事务写入、查询、按文档删除、全量扫描。
  • EmbeddingProvider:统一 embedding 接口,支持本地 BGE 中文模型与 OpenAI 兼容远端。
  • MemoryService:长期记忆的增删改查、召回、审查压缩、分级注入、向量缓存补齐。
  • Detect/Install:RAG 可选依赖检测与一键安装,含自动恢复、进程治理、状态持久化。

章节来源

架构总览 ​

RAG 的知识库由“元数据注册表 + Vectra 索引 + 原始文档备份”组成;长期记忆由 JSON 文件 + 向量派生缓存组成。两者共用 embedding provider,但数据域不同:RAG 面向文档切片,记忆面向事实与摘要。

sequenceDiagram
participant Client as "客户端/扩展端"
participant Manager as "RagManager"
participant Loader as "DocumentLoader"
participant Chunker as "Chunker"
participant Embedder as "EmbeddingProvider"
participant Store as "VectraStore"
participant Searcher as "Searcher"
Client->>Manager : 创建知识库
Manager->>Store : ensureCreated()
Manager-->>Client : 返回知识库元信息
Client->>Manager : 导入文档/文本/URL
Manager->>Loader : loadDocument(filePath)
Loader-->>Manager : {text, fileName}
Manager->>Chunker : chunkText(text, chunkConfig)
Chunker-->>Manager : chunks[]
Manager->>Embedder : embedDocuments(chunks)
Embedder-->>Manager : embeddings[][]
Manager->>Store : upsertChunks(documentId, chunks, embeddings, metadata)
Store-->>Manager : 成功
Client->>Manager : 检索 query
Manager->>Searcher : search(query, options)
Searcher->>Embedder : embedQuery(query)
Searcher->>Store : search(queryVec, query, topK*2)
Searcher-->>Manager : 结果集
Manager-->>Client : 最终检索结果

图表来源

详细组件分析 ​

RagManager:知识库生命周期与导入重建 ​

RagManager 是 RAG 的核心编排器,职责包括:

  • 注册表读写互斥保护,避免并发写坏 collections.json。
  • 知识库创建/删除/启用切换/更新。
  • 文档导入:文本、本地文件、上传内容、URL。
  • 索引重建:临时目录构建新索引 → 原子换入 → 提交注册表 → 清理现场。
  • 中断恢复:根据 rebuild_manifest 与 index_backup 收敛半完成状态。
  • 导入进度快照:供前端轮询展示阶段、当前数、总数、错误。

关键设计点:

  • 知识库 ID 正则校验,防止路径穿越。
  • embedding 配置跨模式重置,防字段污染。
  • 仅当 mode/endpoint/modelName/dimensions 或 chunkSize/overlap 变化时才触发重建。
  • 重建失败保留旧索引与旧配置,保证可用性。
  • URL 导入受内网放行策略控制,测试可注入覆盖。
flowchart TD
Start(["updateCollection"]) --> Validate["校验名称/描述/配置"]
Validate --> CheckRebuild{"是否需重建索引?"}
CheckRebuild --> |否| UpdateMeta["直接更新名称/描述/非敏感配置"]
UpdateMeta --> ReturnUpdate["返回已更新知识库"]
CheckRebuild --> |是| ReportProgress["上报 rebuilding 进度"]
ReportProgress --> RebuildIndex["_rebuildIndex(collectionId, nextEmbedding, nextChunk)"]
RebuildIndex --> RecoverInterrupted["recoverInterruptedRebuild()"]
RecoverInterrupted --> ReadBackups["读取 documents/ 备份"]
ReadBackups --> BuildNewIndex["临时目录构建新索引"]
BuildNewIndex --> AtomicSwap["原子换入:rename(finalDir) → rename(tmpRoot/collectionId)"]
AtomicSwap --> CommitRegistry["提交注册表:embeddingConfig/chunkCount/documentCount"]
CommitRegistry --> Cleanup["删除清单/旧索引备份/临时目录"]
Cleanup --> Done(["重建完成"])

图表来源

章节来源

文档处理管道:多格式解析与分块 ​

文档处理分为两步:

  1. 加载与解析:按扩展名路由到 text/html/pdf/office 解析器,输出纯文本。
  2. 分块:段落优先断点 + 字符窗口兜底 + 重叠回退,返回带原文偏移的分块。

支持的扩展名由 PARSER_ROUTES 定义,包括 txt/md/json/csv/html/htm/pdf/docx/pptx/xlsx/xls。chunker 默认 chunkSize=400、overlap=80,并警告超过 500 可能静默截断。

flowchart TD
Input["输入文件/文本"] --> Route["按扩展名路由"]
Route --> Parse["解析器解析为纯文本"]
Parse --> Normalize["规范化换行"]
Normalize --> Chunk["分段优先断点 + 窗口兜底 + 重叠"]
Chunk --> Output["chunks[{text,startPos,endPos}]"]

图表来源

章节来源

向量嵌入与索引构建 ​

EmbeddingProvider 提供统一接口:

  • embedQuery:查询侧自动附加 queryPrefix(BGE 中文模型必须)。
  • embedDocuments:文档侧不加前缀。
  • 支持 local(Xenova/bge-small-zh-v1.5)与 openai-compat(远端)两种后端。
  • dimensions=0 表示未显式指定,远端跟随平台默认维度。

索引构建流程:

  • 对每个文档分块后批量嵌入。
  • 使用 VectraStore.upsertChunks 事务写入,metadata 包含 documentId、chunkIndex、totalChunks、text、startPos、endPos。
  • 重建时先写临时索引,再原子换入,最后提交注册表。
classDiagram
class EmbeddingProvider {
+string mode
+string modelName
+number dimensions
+string queryPrefix
+embedQuery(query) number[]
+embedDocuments(texts) number[][]
}
class LocalEmbedding
class OpenAICompatEmbedding
class VectraStore {
+ensureCreated()
+upsertChunks(documentId, chunks, embeddings, metadata)
+search(queryVector, queryText, options)
+listAllItems()
+removeDocument(documentId)
}
EmbeddingProvider <.. LocalEmbedding : "本地 BGE"
EmbeddingProvider <.. OpenAICompatEmbedding : "远端兼容"
RagManager --> EmbeddingProvider : "创建 provider"
RagManager --> VectraStore : "写入索引"

图表来源

章节来源

向量存储系统:Vectra 适配与索引管理 ​

VectraStore 是对 vectra@0.15.0 的轻量适配层,关键点:

  • createIndex 对已存在索引抛错,因此 ensureCreated 先判 isIndexCreated。
  • 无批量 upsert API,使用 beginUpdate/endUpdate 事务包裹逐条 upsertItem。
  • 无按元数据删除 API,通过 listItemsByMetadata + deleteItems 两步删除。
  • queryItems 位置参数签名,query 仅 BM25 路径使用。
  • metadata 记录 documentId/startPos/endPos,为混合检索预留。

索引管理机制:

  • 每个知识库一个目录,包含 Vectra 索引与 documents/ 原始文档备份。
  • 重建时使用临时目录 .rebuild_<collectionId>,完成后原子换入。
  • 重建清单 rebuild_manifest.json 用于崩溃恢复。

章节来源

混合检索引擎:语义搜索、关键词匹配、重排序与阈值过滤 ​

Searcher 实现混合检索:

  • 语义通道:使用 EmbeddingProvider.embedQuery 生成查询向量,调用 VectraStore.search 获取候选。
  • 关键词通道:自建关键词匹配(非 Vectra 内置 BM25),英文按词边界,中文取最长命中片段。
  • 重排序:命中 chunk 抬分(保底 KEYWORD_MIN_SCORE + 单元加分),合并后再统一阈值过滤。
  • 旁路探测:过滤后为空时放宽阈值,区分“无数据”与“被过滤”。
flowchart TD
Query["查询 query"] --> EmbedQuery["embedQuery(query)"]
EmbedQuery --> VectorSearch["store.search(queryVec, query, topK*2)"]
VectorSearch --> Candidates["候选集合"]
Candidates --> KeywordBoost["关键词命中增强"]
KeywordBoost --> ThresholdFilter["阈值过滤 score >= threshold"]
ThresholdFilter --> EmptyCheck{"结果为空?"}
EmptyCheck --> |否| TopK["取 topK 返回"]
EmptyCheck --> |是| Fallback["放宽阈值 -0.2,最多 3 条"]
Fallback --> Return["返回结果 + fallback 标记"]

图表来源

章节来源

依赖检测与安装:RAG 可选依赖生命周期 ​

RAG 是高级功能,不强制安装。detect.js 在新子进程中探测 vectra 与 @huggingface/transformers 可用性,避免长驻进程内模块求值失败缓存问题。install.js 提供一键安装,包含:

  • 包清单来自 package.json 的 ragDependencies 字段。
  • Windows 优先直执行 npm-cli.js,否则回退 npm.cmd + shell: true。
  • 异步任务 + 安装锁 + 超时上限 10 分钟。
  • 状态持久化到 ~/.ai-helper-agent/rag-install-state.json。
  • 启动时自动恢复:曾成功安装过但依赖丢失时自动重装。
stateDiagram-v2
[*] --> Idle
Idle --> Installing : "startRagInstall()"
Installing --> Verifying : "npm 退出码 0"
Verifying --> Done : "detectRagAvailable() = true"
Verifying --> Failed : "detectRagAvailable() = false"
Installing --> Aborted : "stopRagInstall()"
Failed --> Idle : "重新安装"
Aborted --> Idle : "重新安装"
Done --> Idle : "自动恢复检查"

图表来源

章节来源

依赖关系分析 ​

RAG 与长期记忆共享 embedding provider,但数据域独立。RAG 依赖 Vectra 本地索引与 transformers.js 模型缓存;长期记忆依赖 JSON 文件与向量派生缓存。

graph LR
RAG["RAG 子系统"] --> VECTOR["Vectra 索引"]
RAG --> EMBED["EmbeddingProvider"]
MEMORY["长期记忆子系统"] --> EMBED
MEMORY --> JSON["global-memory.json"]
MEMORY --> VEC_CACHE["向量派生缓存"]
DETECT["detect/install"] --> RAG

图表来源

章节来源

性能与容量特性 ​

  • 分块大小:默认 400 字符,最大 2000,超过 500 告警(bge-small-zh-v1.5 最大 512 token)。
  • 嵌入批大小:固定 10,兼容阿里云百炼等平台单次批量上限。
  • 检索 topK 上限:SEARCH_TOPK_MAX=50,防止超大 topK 放大候选集。
  • 关键词扫描限制:KEYWORD_SCAN_LIMIT=20000,超过则跳过关键词通道。
  • 导入体积上限:文本 10MB,上传 50MB,防止 OOM。
  • 重建原子性:临时目录 + 原子换入 + 清单恢复,崩溃后可收敛。
  • 记忆召回锁外嵌入:避免外部网络调用阻塞同进程所有写入。

[本节为通用性能讨论,不直接分析具体文件]

知识库管理端到端流程 ​

以下示例展示从文档上传到查询响应的完整流程:

sequenceDiagram
participant User as "用户"
participant UI as "扩展端 UI"
participant Agent as "Agent 服务端"
participant Manager as "RagManager"
participant Loader as "DocumentLoader"
participant Chunker as "Chunker"
participant Embedder as "EmbeddingProvider"
participant Store as "VectraStore"
participant Searcher as "Searcher"
User->>UI : 选择 PDF/Office/文本文件
UI->>Agent : POST /api/rag/ingest (collectionId, fileBase64)
Agent->>Manager : ingestFile(collectionId, input)
Manager->>Loader : loadDocument(filePath)
Loader-->>Manager : {text, fileName}
Manager->>Chunker : chunkText(text, chunkConfig)
Chunker-->>Manager : chunks[]
Manager->>Embedder : embedDocuments(chunks)
Embedder-->>Manager : embeddings[][]
Manager->>Store : upsertChunks(documentId, chunks, embeddings, metadata)
Store-->>Manager : 成功
Manager-->>Agent : 返回 documentId/chunkCount
Agent-->>UI : 导入成功
User->>UI : 输入查询
UI->>Agent : GET /api/rag/search (collectionId, query, topK, threshold)
Agent->>Manager : search(collectionId, query, options)
Manager->>Searcher : search(query, options)
Searcher->>Embedder : embedQuery(query)
Searcher->>Store : search(queryVec, query, topK*2)
Searcher-->>Manager : 结果集
Manager-->>Agent : 最终结果
Agent-->>UI : 返回检索结果

图表来源

长期记忆与 RAG 集成 ​

长期记忆服务 MemoryService 提供:

  • store:新增/更新/删除记忆,含注入模式拦截、频率限制、去重。
  • recall:关键词通道 + 可选向量通道(RRF 融合),会话级去重,访问计数更新。
  • manage:审查价值分数、压缩淘汰低价值记忆。
  • injectSelect:三级注入策略(Tier1 常驻、Tier2 预算内、Tier3 按需)。
  • backfillVectors:显式重建向量缓存,支持超窗检测。
  • vectorStatus:只读状态,判断向量缓存是否陈旧。

与 RAG 的集成点:

  • 共享 EmbeddingProvider,支持本地 BGE 与 OpenAI 兼容远端。
  • 记忆召回可降级为关键词单通道,不影响正确性。
  • 记忆向量缓存与 RAG 索引独立,但都依赖同一 embedding 配置。
flowchart TD
Recall["recall(query, tags, memoryType, limit)"] --> TierCheck["判定 tierlocal/openai-compat"]
TierCheck --> EmbedQuery["embedQuery(query)"]
EmbedQuery --> LockRead["锁内只读:读真源、定候选、校验向量指纹"]
LockRead --> Backfill["锁外补齐缺失向量冷却 60s"]
Backfill --> Fuse["RRF 融合:关键词排名 + 语义排名"]
Fuse --> TagLift["标签名次加成"]
TagLift --> Dedup["会话去重 + 全局去重"]
Dedup --> UpdateAccess["更新访问计数"]
UpdateAccess --> Return["返回结果 + tier + vectorMatched"]

图表来源

章节来源

向量存储与索引机制 ​

VectraStore 封装了 Vectra 本地索引的关键操作:

  • ensureCreated:幂等创建索引。
  • upsertChunks:事务批量写入分块,metadata 包含文档标识与分块信息。
  • search:向量检索,返回统一结构。
  • listDocumentChunks:按文档列出分块。
  • removeDocument:按文档删除所有分块。
  • listAllItems:全量扫描,用于关键词通道统计。
  • recreate:清空重建,用于模型变更后强制重建。

索引管理机制:

  • 每个知识库一个目录,包含 Vectra 索引与 documents/ 原始文档备份。
  • 重建时使用临时目录,完成后原子换入。
  • 重建清单用于崩溃恢复,确保注册表与索引一致。

章节来源

混合检索引擎 ​

Searcher 实现混合检索的核心逻辑:

  • 语义搜索:使用 EmbeddingProvider.embedQuery 生成查询向量,调用 VectraStore.search 获取候选。
  • 关键词匹配:自建关键词匹配,英文按词边界,中文取最长命中片段,高频词剔除。
  • 重排序:命中 chunk 抬分(保底 KEYWORD_MIN_SCORE + 单元加分),合并后再统一阈值过滤。
  • 旁路探测:过滤后为空时放宽阈值,区分“无数据”与“被过滤”。
flowchart TD
Query["查询 query"] --> ExtractTerms["提取拉丁/CJK 术语"]
ExtractTerms --> VectorSearch["向量检索 topK*2"]
VectorSearch --> KeywordScan["全量扫描 chunks≤20000"]
KeywordScan --> Boost["命中 chunk 抬分"]
Boost --> Merge["合并候选 + 重排"]
Merge --> Filter["阈值过滤"]
Filter --> Fallback{"结果为空?"}
Fallback --> |是| Relax["放宽阈值 -0.2"]
Fallback --> |否| TopK["取 topK"]
Relax --> Return["返回结果 + fallback 标记"]
TopK --> Return

图表来源

章节来源

配置项与监控 ​

RAG 配置项 ​

  • RAG_ROOT:数据根目录,可通过环境变量 AI_HELPER_RAG_ROOT 覆盖。
  • COLLECTIONS_REGISTRY:知识库注册表文件。
  • MODELS_DIR:transformers.js 模型缓存目录。
  • DEFAULT_EMBEDDING_CONFIG:默认 embedding 配置(本地 BGE 中文模型)。
  • DEFAULT_CHUNK_CONFIG:默认分块参数(chunkSize=400, overlap=80)。
  • DEFAULT_SEARCH_CONFIG:默认检索参数(topK=5, threshold=0.3)。
  • EMBED_BATCH_SIZE:嵌入批大小(固定 10)。
  • PARSER_ROUTES:解析器扩展名路由表。

长期记忆配置项 ​

  • DEFAULT_MEMORY_EMBEDDING_CONFIG:默认记忆 embedding 配置(enabled=false)。
  • MEMORY_EMBEDDING_MODES:mode 白名单(openai-compat/local)。
  • MEMORY_INJECTION_CONFIG:三级注入策略配置(alwaysInjectImportance=8, budgetChars=1500, budgetCount=12)。

监控与诊断 ​

  • 依赖检测:detectRagAvailable() 返回 ok/detail/errorSummary。
  • 安装状态:getRagInstallStatus() 返回 running/done/success/phase/logTail。
  • 重建进度:_reportProgress() 上报 phase/current/total/done/error。
  • 向量状态:vectorStatus() 返回 indexed/total/storedModelKey/currentModelKey/stale/tier。

章节来源

故障排除指南 ​

RAG 依赖不可用 ​

  • 现象:detectRagAvailable() 返回 false,errorSummary 包含 vectra 或 @huggingface/transformers 错误。
  • 排查:
    • 检查 Node 版本是否 ≥22。
    • 运行 startRagInstall() 一键安装。
    • 查看 getRagInstallStatus().logTail 末尾日志。
    • 若自动恢复失败,检查 everSucceeded 标记与持久化状态文件。

索引重建失败 ​

  • 现象:updateCollection() 返回 rebuilding=true,但 _reportProgress() 上报 error。
  • 排查:
    • 检查 documents/ 备份是否损坏。
    • 查看临时目录 .rebuild_<collectionId> 是否残留。
    • 确认 rebuild_manifest.json 是否有效。
    • 手动清理临时目录后重试。

检索结果为空 ​

  • 现象:Searcher.search() 返回 total=0,fallback=false。
  • 排查:
    • 检查 threshold 是否过高。
    • 检查 embedding 维度是否与索引一致。
    • 检查关键词通道是否因高频词剔除而失效。
    • 尝试放宽阈值或关闭关键词通道。

长期记忆召回异常 ​

  • 现象:recall() 返回 vectorMatched=0 或结果不符合预期。
  • 排查:
    • 检查 memoryEmbedding.enabled 是否开启。
    • 检查 backfillVectors() 是否成功。
    • 查看 vectorStatus().stale 是否为 true。
    • 检查关键词通道是否因 df 过滤而误伤。

章节来源

结论 ​

RAG 知识检索系统在文档处理、向量嵌入、索引构建、混合检索、长期记忆注入等方面提供了完整的技术实现。系统强调安全性(沙箱校验、路径穿越防护)、可靠性(原子换入、崩溃恢复)、可观测性(进度上报、状态查询)与可扩展性(本地/远端 embedding 双模式)。通过 Vectra 本地索引与自建关键词通道,系统在中文场景下实现了语义与精确匹配的平衡。长期记忆与 RAG 共享 embedding provider,但数据域独立,便于独立演进与故障隔离。