主题
知识库管理
本文引用的源码文件
本文引用的文件
- agent/src/rag/manager.js
- agent/src/rag/config.js
- agent/src/rag/install.js
- agent/src/rag/detect.js
- agent/src/rag/searcher.js
- agent/src/rag/embedding/index.js
- agent/src/rag/store/vectra.js
- agent/src/rag/document/loader.js
- agent/src/rag/errors.js
- agent/src/server.js
- test/unit/knowledge-batch-upload.unit.test.js
- agent/README.zh-CN.md
更新摘要
变更内容
- 新增知识库批量上传功能:支持最多 20 个文件的并发处理,包含 validateBatchFiles 和 runBatchIngest 两个核心函数
- 增强文件验证机制:数量上限校验、单个文件大小限制、扩展名白名单验证
- 改进错误处理:串行执行、失败继续、详细报告成功/失败统计信息
- 更新文档导入流水线:增加批量处理章节和相关流程图
目录
引言
本技术文档面向 RAG 知识库管理系统,覆盖知识库生命周期(创建、更新、删除、重建)、配置管理(向量存储、嵌入模型、检索参数)、安装部署与环境检测、数据一致性检测与修复、迁移与平滑升级、运维监控与日志分析、以及故障恢复与备份恢复。系统采用双进程架构:Chrome 扩展端通过本地 HTTP/WebSocket 调用 Agent 端的 RAG 能力;Agent 端负责索引构建、向量化、检索与状态持久化。新增批量上传功能支持同时处理最多 20 个文件,提供详细的验证和报告机制。
项目结构
RAG 子系统位于 agent/src/rag,按职责分层组织:
- 生命周期与编排:manager.js
- 配置与路径约定:config.js
- 可选依赖安装与自动恢复:install.js
- 运行时依赖检测:detect.js
- 检索器(向量+关键词增强):searcher.js
- 嵌入提供者工厂:embedding/index.js
- 向量存储适配器:store/vectra.js
- 文档加载与解析路由:document/loader.js
- 错误类型与翻译:errors.js
- HTTP 路由挂载点:server.js(按需加载 rag/routes.js)
graph TB subgraph "Agent 端" M["RagManager<br/>生命周期与导入/重建"] --> S["VectraStore<br/>向量索引"] M --> E["EmbeddingProvider<br/>本地/远端嵌入"] M --> SR["Searcher<br/>混合检索"] M --> C["Config<br/>默认配置/路径"] I["Install<br/>依赖安装/自动恢复"] --> D["Detect<br/>依赖探测"] L["Document Loader<br/>解析路由"] --> M end subgraph "扩展端" UI["选项页/侧边栏"] end UI --> |"HTTP/WebSocket"| Server["Server<br/>按需加载 RAG 路由"] Server --> M
图示来源
- agent/src/rag/manager.js#L1-L29
- agent/src/rag/config.js#L1-L70
- agent/src/rag/install.js#L1-L60
- agent/src/rag/detect.js#L1-L46
- agent/src/rag/searcher.js#L1-L26
- agent/src/rag/embedding/index.js#L1-L38
- agent/src/rag/store/vectra.js#L1-L21
- agent/src/rag/document/loader.js#L1-L14
- agent/src/server.js#L2050-L2065
章节来源
核心组件
- RagManager:知识库注册表与索引的编排者,负责创建/删除/启用停用、文档导入(文本/文件/URL)、统计、单库与多库检索、后台重建索引与进度上报。
- VectraStore:对 vectra 本地索引的封装,提供事务批量 upsert、按元数据查询/删除、全量枚举等。
- EmbeddingProvider:统一嵌入接口,支持本地 BGE 与 OpenAI 兼容远端模式,保证查询侧带前缀、文档侧不带前缀的非对称检索语义。
- Searcher:向量检索 + 关键词命中增强 + 阈值过滤 + 旁路探测,提升中文短专有名词召回。
- Install/Detect:RAG 可选依赖的一键安装、任务状态持久化、超时与进程树治理、启动自动恢复与 Node 版本检测。
- Config:RAG 根目录、注册表路径、默认嵌入/分块/检索参数、解析器路由。
- Document Loader:按扩展名动态加载解析器,输出纯文本供分块。
- Errors:业务错误码与响应层翻译。
章节来源
- agent/src/rag/manager.js#L172-L300
- agent/src/rag/store/vectra.js#L13-L65
- agent/src/rag/embedding/index.js#L10-L58
- agent/src/rag/searcher.js#L27-L77
- agent/src/rag/install.js#L239-L319
- agent/src/rag/detect.js#L48-L168
- agent/src/rag/config.js#L11-L54
- agent/src/rag/document/loader.js#L38-L48
- agent/src/rag/errors.js#L5-L29
架构总览
RAG 在 Agent 端以"注册表 + 索引目录"形式持久化,所有写操作通过互斥锁串行化,避免并发写坏索引;导入与重建走"临时目录构建 → 原子换入 → 提交注册表"的三段式流程,确保崩溃可恢复。
sequenceDiagram
participant Client as "客户端/扩展端"
participant Server as "Server(按需加载)"
participant Manager as "RagManager"
participant Store as "VectraStore"
participant Embed as "EmbeddingProvider"
participant FS as "文件系统"
Client->>Server : POST /api/rag/collections
Server->>Manager : createCollection()
Manager->>FS : 创建 kb_xxx 目录与 documents/
Manager->>Store : ensureCreated()
Manager->>Manager : _updateRegistry() (写入 collections.json)
Manager-->>Client : 返回知识库条目
Client->>Server : POST /api/rag/collections/{id}/ingest
Server->>Manager : ingestText()/ingestFile()/ingestUrl()
Manager->>Manager : chunkText()
Manager->>Embed : embedDocuments()
Manager->>Store : upsertChunks()
Manager->>FS : 保存原文备份
Manager-->>Client : {documentId, chunkCount}
图示来源
- agent/src/server.js#L2050-L2065
- agent/src/rag/manager.js#L271-L300
- agent/src/rag/manager.js#L849-L892
- agent/src/rag/store/vectra.js#L39-L65
- agent/src/rag/embedding/index.js#L45-L57
详细组件分析
知识库生命周期管理(创建/更新/删除/重建)
- 创建:生成唯一 ID,校验并合并 embedding/chunk 配置,创建索引目录与 documents 备份目录,最后写入注册表。
- 删除:校验存在性与空闲状态,递归删除索引目录,清理 provider 缓存,从注册表移除。
- 启用/停用:仅修改注册表 enabled 字段,不影响索引;停用后参与全局检索过滤,但显式引用仍可工作。
- 更新:名称/描述直接生效;embedding 或 chunk 配置变更触发后台重建;非空间级变更(如 apiKey/queryPrefix)直接生效。
- 重建:基于 documents 备份重放分块与向量化,写入临时目录,原子换入,最后提交注册表;失败保留旧索引。
flowchart TD
Start(["开始"]) --> CheckIdle["检查是否空闲"]
CheckIdle --> |否| ErrorBusy["报错:操作进行中"]
CheckIdle --> |是| NeedRebuild{"是否需要重建?"}
NeedRebuild --> |否| UpdateMeta["更新名称/描述/非空间配置"]
NeedRebuild --> |是| BuildTmp["临时目录构建新索引"]
BuildTmp --> Swap["原子换入索引目录"]
Swap --> CommitReg["提交注册表新配置/计数"]
CommitReg --> Cleanup["清理清单与临时目录"]
UpdateMeta --> Done(["完成"])
Cleanup --> Done
图示来源
- agent/src/rag/manager.js#L349-L407
- agent/src/rag/manager.js#L434-L549
- agent/src/rag/manager.js#L561-L640
章节来源
- agent/src/rag/manager.js#L271-L317
- agent/src/rag/manager.js#L327-L407
- agent/src/rag/manager.js#L434-L549
配置管理系统(向量存储/嵌入模型/检索参数)
- 向量存储:VectraStore 封装 vectra LocalIndex,提供事务批量写入、按元数据查询/删除、全量枚举。
- 嵌入模型:
- 本地模式:默认 Xenova/bge-small-zh-v1.5,查询侧自动附加 queryPrefix,文档侧不加。
- 远端模式:OpenAI 兼容 endpoint/apiKey/modelName/dimensions,未显式指定 dimensions 时不强制透传。
- 维度校验:导入与检索均校验实际向量维度与配置一致,不一致立即报错。
- 检索参数:topK 上限钳制(SEARCH_TOPK_MAX),threshold 钳制到 [-1,1];Searcher 提供关键词增强与旁路探测。
classDiagram
class EmbeddingProvider {
+string mode
+string modelName
+number dimensions
+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) number
}
class Searcher {
+search(query, options)
}
EmbeddingProvider <|-- LocalEmbedding
EmbeddingProvider <|-- OpenAICompatEmbedding
Searcher --> VectraStore : "使用"
Searcher --> EmbeddingProvider : "使用"
图示来源
- agent/src/rag/embedding/index.js#L10-L58
- agent/src/rag/store/vectra.js#L13-L124
- agent/src/rag/searcher.js#L27-L77
章节来源
- agent/src/rag/config.js#L23-L54
- agent/src/rag/embedding/index.js#L10-L58
- agent/src/rag/searcher.js#L46-L77
- agent/src/rag/manager.js#L908-L926
文档导入流水线(文本/文件/URL)
- 文本导入:大小预检 → 分块 → 批量向量化 → 事务写入 → 原文备份 → 更新计数。
- 文件导入:沙箱校验(allowedPaths/阻止清单)→ 解析为文本 → 同文本导入流程。
- URL 导入:协议校验 → 内网放行策略(开关+白名单)→ HTML/PDF/文本处理 → 空正文诊断 → 同文本导入流程。
- 进度上报:parsing/chunking/embedding/storing/done/error 阶段快照,前端轮询展示。
flowchart TD
A["选择导入方式"] --> B{"文本/文件/URL?"}
B --> |文本| T1["大小预检"]
B --> |文件| F1["沙箱校验"]
B --> |URL| U1["协议/策略校验"]
T1 --> C["分块"]
F1 --> C
U1 --> C
C --> D["批量向量化"]
D --> E["事务写入索引"]
E --> F["保存原文备份"]
F --> G["更新注册表计数"]
G --> H["上报 done 进度"]
图示来源
- agent/src/rag/manager.js#L723-L739
- agent/src/rag/manager.js#L749-L790
- agent/src/rag/manager.js#L806-L843
- agent/src/rag/manager.js#L849-L892
章节来源
批量文件上传功能(新增)
新增功能:知识库现在支持批量上传功能,通过 validateBatchFiles 和 runBatchIngest 两个核心函数实现,允许同时处理最多 20 个文件,提供独立的验证和详细报告。
批量文件验证(validateBatchFiles)
- 数量上限校验:整批拒绝超过最大数量的文件(MAX_COUNT=20)
- 单个文件大小限制:任一文件超过单文件大小上限则拒绝整个批次
- 扩展名白名单验证:只允许支持的文档格式(.txt, .md, .pdf, .docx, .doc, .xlsx, .xls, .csv, .pptx, .html, .htm, .json, .rtf, .odt, .odp, .ods, .epub)
- 错误分类:tooMany(数量超限)、tooLarge(文件过大)、badType(不支持的文件类型)
批量导入执行(runBatchIngest)
- 串行执行:严格按顺序处理每个文件,确保处理顺序一致
- 失败继续:单个文件失败不影响其他文件的处理
- 详细报告:汇总成功数、失败数、总分块数和失败详情
- 进度跟踪:每个文件的处理状态和结果都可追踪
flowchart TD
A["选择多个文件"] --> B["validateBatchFiles 验证"]
B --> C{"验证通过?"}
C --> |否| D["显示错误原因<br/>tooMany/tooLarge/badType"]
C --> |是| E["runBatchIngest 串行处理"]
E --> F["逐个文件处理"]
F --> G{"文件处理成功?"}
G --> |是| H["累加成功计数和分块数"]
G --> |否| I["记录失败详情"]
H --> J["继续下一个文件"]
I --> J
J --> K{"还有文件?"}
K --> |是| F
K --> |否| L["生成汇总报告<br/>successCount/failCount/totalChunks"]
L --> M["显示详细结果"]
图示来源
- test/unit/knowledge-batch-upload.unit.test.js#L89-L121
- test/unit/knowledge-batch-upload.unit.test.js#L123-L148
章节来源
- test/unit/knowledge-batch-upload.unit.test.js#L89-L121
- test/unit/knowledge-batch-upload.unit.test.js#L123-L148
检索与混合增强
- 向量检索:使用同一 EmbeddingProvider 的 embedQuery,确保查询侧带前缀。
- 关键词增强:英文/数字词边界匹配,中文最长片段匹配;高频词剔除;命中加分与保底分数。
- 阈值过滤与旁路探测:低于 threshold 的结果丢弃;为空时放宽阈值进行旁路探测,区分"无数据"与"被过滤"。
- 跨库检索:按库数均分 topK 配额,避免高得分库垄断结果。
flowchart TD
Q["查询"] --> V["向量候选(topK*2)"]
V --> K["关键词增强(抬分/新增)"]
K --> F["阈值过滤"]
F --> R{"结果为空?"}
R --> |否| Out["返回 topK 结果"]
R --> |是| P["旁路探测(放宽阈值)"]
P --> Out
图示来源
- agent/src/rag/searcher.js#L46-L77
- agent/src/rag/searcher.js#L89-L160
- agent/src/rag/manager.js#L1028-L1073
章节来源
依赖关系分析
- RagManager 依赖:config(路径/默认值)、embedding(provider 工厂)、store(vectra 适配器)、document loader(解析)、security/url-guard(安全)、i18n/crypto(密钥处理)。
- VectraStore 依赖 vectra 本地索引 API,封装事务与元数据约束。
- EmbeddingProvider 根据 mode 选择 LocalEmbedding 或 OpenAICompatEmbedding。
- Searcher 依赖 VectraStore 与 EmbeddingProvider,并复用 keyword-match 逻辑。
- Install/Detect 通过子进程探测真实磁盘状态,避免长驻进程模块求值缓存导致的误报。
graph LR Manager["RagManager"] --> Config["Config"] Manager --> Embed["EmbeddingProvider"] Manager --> Store["VectraStore"] Manager --> Loader["Document Loader"] Manager --> Security["Security/URL Guard"] Store --> Vectra["vectra LocalIndex"] Embed --> Local["LocalEmbedding"] Embed --> Remote["OpenAICompatEmbedding"] Searcher["Searcher"] --> Store Searcher --> Embed Install["Install"] --> Detect["Detect"]
图示来源
- agent/src/rag/manager.js#L10-L28
- agent/src/rag/store/vectra.js#L9-L21
- agent/src/rag/embedding/index.js#L7-L28
- agent/src/rag/searcher.js#L11-L14
- agent/src/rag/install.js#L21-L30
- agent/src/rag/detect.js#L9-L13
章节来源
- agent/src/rag/manager.js#L10-L28
- agent/src/rag/store/vectra.js#L9-L21
- agent/src/rag/embedding/index.js#L7-L28
- agent/src/rag/searcher.js#L11-L14
- agent/src/rag/install.js#L21-L30
- agent/src/rag/detect.js#L9-L13
性能与容量特性
- 单次 embedding 批大小固定为 10,兼顾内存占用与平台批量上限(如阿里云百炼 text-embedding-v3/v4)。
- 检索 topK 上限为 SEARCH_TOPK_MAX,防止超大入参放大候选集与 CPU/内存。
- 导入体积限制:文本 10MB,上传文件 50MB,避免解析/向量化前全量驻留内存导致 OOM。
- 关键词扫描限制 KEYWORD_SCAN_LIMIT=20000,大库跳过关键词通道以避免卡顿。
- 向量候选取 topK*2 进入排序与关键词扫描,再统一阈值过滤。
- 批量上传限制:最多 20 个文件,单个文件最大 50MB,串行处理确保稳定性。
章节来源
- agent/src/rag/config.js#L52-L54
- agent/src/rag/manager.js#L38-L45
- agent/src/rag/manager.js#L156-L170
- agent/src/rag/searcher.js#L17-L21
- agent/src/rag/manager.js#L723-L739
- test/unit/knowledge-batch-upload.unit.test.js#L71-L72
安装、部署与环境检测
- 官方安装渠道:GitHub Releases 自动构建产物下载;Agent 端为独立 Node.js 服务,扩展端通过本地 HTTP/WebSocket 调用。
- 可选依赖一键安装:
- 包清单来自 package.json 的 ragDependencies,不接受外部传入包名,防注入。
- Windows 优先直调 npm-cli.js(shell:false),否则回退 npm.cmd + shell:true 并对 spec 加引号。
- 安装任务异步执行,带 10 分钟超时;POSIX 下 detached 启动并通过进程树组杀终止。
- 安装完成后自动重新检测依赖可用性,避免"装上但加载失败"的假成功。
- 自动恢复:若 everSucceeded=true 且当前缺失依赖,启动时自动触发安装;Node 版本不满足则跳过。
- 环境检测:
- Node 版本要求 >=22(vectra/officeparser 等依赖)。
- 探测在新子进程执行,避免进程内模块求值失败缓存导致的误报。
- 检测结果缓存,并提供最近一次探测错误摘要。
sequenceDiagram
participant Admin as "管理员"
participant Server as "Server"
participant Install as "Install"
participant NPM as "npm 子进程"
participant Detect as "Detect"
Admin->>Server : POST /api/rag/install
Server->>Install : startRagInstall()
Install->>NPM : spawn install --no-save ...
NPM-->>Install : stdout/stderr 日志
Install->>Install : 超时/异常保护
Install->>Detect : resetRagDetection()
Detect->>Detect : runRagProbe() (子进程)
Detect-->>Install : ok/detail/errorSummary
Install-->>Admin : 状态轮询 {running,phase,logTail,...}
图示来源
- agent/src/rag/install.js#L91-L110
- agent/src/rag/install.js#L239-L319
- agent/src/rag/install.js#L351-L391
- agent/src/rag/detect.js#L81-L168
章节来源
- agent/src/rag/install.js#L1-L60
- agent/src/rag/install.js#L91-L110
- agent/src/rag/install.js#L239-L319
- agent/src/rag/detect.js#L48-L168
- agent/README.zh-CN.md#L488-L520
运维监控与日志分析
- 安装状态:/api/rag/install/status 返回 running/done/success/phase/logTail/packages,支持前端轮询。
- RAG 能力状态:/api/rag/status 暴露依赖可用性与安装状态。
- 导入进度:/api/rag/collections/{id}/ingest/status 返回 phase/current/total/done/error。
- 重建进度:更新集合触发重建时,同样通过 /ingest/status 轮询 rebuilding/done/error。
- 日志建议:
- 关注 "[RAG]" 前缀日志,包括 embed 进度、rebuild 完成/失败、恢复动作。
- 依赖检测失败会落结构化日志 rag_detect_failed,便于离线分析。
- 安装过程 logTail 保留末尾 50 行,便于定位 npm 输出问题。
章节来源
- agent/src/rag/install.js#L278-L293
- agent/src/rag/install.js#L397-L461
- agent/src/rag/detect.js#L144-L168
- agent/src/rag/manager.js#L396-L427
- agent/src/rag/manager.js#L694-L697
故障恢复与备份恢复
- 重建中断恢复:
- finalDir 缺失 + tmpRoot/<id> 含清单:新索引已构建完整但未换入 → 完成换入并补提交。
- finalDir 缺失 + tmpRoot/index_backup:换入空窗被杀 → 回滚旧索引。
- finalDir 存在 + 清单存在:换入完成但注册表未提交被杀 → 用清单补提交并清理。
- finalDir 正常 + 仅残留 tmpRoot:上次已完成或已回滚 → 安全清理。
- 进程重启自动收敛:recoverInterruptedRebuilds 扫描 .rebuild_* 目录,逐个幂等恢复。
- 文档备份:每次导入都会保存 documents/{docId}.json,作为重建与 BM25 docReader 的数据源。
- 注册表权限:collections.json 创建即 0600,并对历史遗留宽松权限收紧,保护远端密钥。
flowchart TD
S["进程启动/重建入口"] --> Scan["扫描 .rebuild_* 目录"]
Scan --> Case{"finalDir 是否存在?"}
Case --> |否| HasManifest{"tmpRoot/<id>/rebuild_manifest.json 存在?"}
HasManifest --> |是| Commit["换入 + 补提交注册表"]
HasManifest --> |否| HasBackup{"index_backup 存在?"}
HasBackup --> |是| Rollback["回滚旧索引"]
HasBackup --> |否| Alert["告警:现场需人工检查"]
Case --> |是| ManifestInFinal{"finalDir 含清单?"}
ManifestInFinal --> |是| Commit
ManifestInFinal --> |否| Clean["清理残留 tmpRoot"]
图示来源
- agent/src/rag/manager.js#L561-L640
- agent/src/rag/manager.js#L646-L670
- agent/src/rag/manager.js#L928-L932
- agent/src/rag/manager.js#L209-L229
章节来源
- agent/src/rag/manager.js#L561-L640
- agent/src/rag/manager.js#L646-L670
- agent/src/rag/manager.js#L928-L932
- agent/src/rag/manager.js#L209-L229
迁移与版本升级指南
- 平滑升级要点:
- 更新 Agent 进程后必须重启,新接口才生效(运行时约束)。
- 若 Node 版本不满足(<22),RAG 功能整体不可用,需先升级 Node。
- 若曾成功安装过 RAG 依赖,但被 npm -g 更新代理清空,启动时会自动恢复安装。
- 配置迁移:
- embeddingConfig 跨模式切换时会重置为对应模式默认值,避免字段污染。
- 远端模式未显式提供的字段优先继承远端当前值,其次远端默认(queryPrefix 默认空)。
- 索引重建:
- 当 embedding 的 mode/endpoint/modelName/dimensions 或 chunk 的 chunkSize/overlap 变更时,自动后台重建索引;重建期间旧索引与旧配置保持可用。
- 数据一致性:
- getStats 会实时聚合索引并回写注册表计数,修正可能的漂移。
章节来源
- agent/src/rag/install.js#L296-L319
- agent/src/rag/detect.js#L48-L55
- agent/src/rag/manager.js#L78-L101
- agent/src/rag/manager.js#L349-L407
- agent/src/rag/manager.js#L995-L1018
故障排查手册
- 常见错误与定位:
- 依赖不可用:查看 /api/rag/status 与 /api/rag/install/status;必要时手动触发 /api/rag/detect 获取 errorSummary。
- 向量维度不匹配:导入或检索时报 embeddingDimensionMismatch,检查远端 model/dimensions 与配置是否一致,必要时重建索引。
- 导入内容为空:URL 链路可能遇到反爬壳页/纯 JS 渲染页/无文本 PDF,检查 urlNoContent 错误。
- 路径不被允许:文件导入经 checkPath 沙箱校验,确认 allowedPaths 白名单与硬阻止清单。
- 检索结果为空:可能是 threshold 过高或关键词增强未命中,尝试降低 threshold 或扩大 topK(受上限约束)。
- 批量上传错误:tooMany(文件数量超过20个)、tooLarge(单个文件超过50MB)、badType(不支持的文件类型)。
- 日志关键字:
- "[RAG] rebuild failed"、"[RAG] embed ..."、"[RAG] depsMissing"、"rag_detect_failed"。
- 恢复步骤:
- 重建中断:等待 recoverInterruptedRebuilds 自动收敛,或手动检查 .rebuild_* 与 rebuild_manifest.json。
- 依赖缺失:触发一键安装,观察 logTail;若 everSucceeded=true,启动将自动恢复。
- 批量上传失败:检查 validateBatchFiles 返回的错误原因,调整文件数量和大小,确认文件类型在白名单中。
章节来源
- agent/src/rag/detect.js#L144-L168
- agent/src/rag/manager.js#L908-L926
- agent/src/rag/manager.js#L806-L843
- agent/src/rag/manager.js#L749-L790
- agent/src/rag/searcher.js#L46-L77
- agent/src/rag/install.js#L397-L461
- test/unit/knowledge-batch-upload.unit.test.js#L89-L121
结论
RAG 知识库管理系统以"注册表 + 索引目录"为核心,结合严格的并发控制、原子换入与清单机制,实现了健壮的生命周期管理与崩溃恢复。通过本地与远端两种嵌入模式、混合检索与旁路探测,系统在中文场景下具备较好的召回与稳定性。新增的批量上传功能进一步提升了用户体验,支持最多 20 个文件的并发处理,提供详细的验证和报告机制。安装与检测机制兼顾了易用性与可靠性,配合完善的日志与状态接口,便于运维监控与排障。建议在升级时遵循"先升级 Node → 再重启 Agent → 必要时触发依赖安装与索引重建"的顺序,以确保平滑过渡。