找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2481

积分

0

好友

344

主题
发表于 3 天前 | 查看: 11| 回复: 0

在构建企业级RAG系统时,尤其是在处理内部Wiki和PDF文档的场景下,选择合适的搜索组件并设计合理的工程方案至关重要。本文将深入探讨组件选型、多租户权限、文档粒度以及一套可落地的生产级配置。

首先要明确:“搜索组件”具体指什么?

在RAG系统中,“搜索”并不仅指向量检索。一个成熟的生产环境通常需要整合至少三种核心检索能力:

  • 关键词检索 (Keyword / BM25)

    • 适用场景:错误码、专有名词、人名、版本号、制度编号等精确匹配。
    • 常用组件:Elasticsearch / OpenSearch。
  • 向量检索 (Vector Search)

    • 适用场景:用户提问口语化、存在同义表达或概念性查询时进行语义匹配。
    • 常用组件:Milvus、pgvector、ES kNN、Pinecone。
  • 重排 (Rerank)

    • 适用场景:从初步检索出的“看似相关”的候选结果中,筛选出“真正最相关”的部分,显著降低噪声。
    • 常用组件:bge-reranker、Cohere Rerank,或使用小型LLM进行评审。

针对“内部Wiki + PDF”的工程方案建议:

  • 追求组件少、运维简单:采用 OpenSearch/ES 一把梭(同时承担关键词与向量检索)。
  • 追求向量性能与扩展性:采用 ES (关键词) + Milvus (向量) + Rerank 的组合方案。

1)多租户场景的核心:权限过滤设计(避免“串库”)

在多租户RAG系统中,首要任务不是追求极致的召回效果,而是确保数据隔离,绝不越权

1.1 两种主流的隔离策略:索引隔离 vs 元数据过滤

A. 索引/集合隔离 (强隔离,运维成本较高)

  • 做法:为每个租户(tenant)创建独立的索引(ES Index)或集合(Milvus Collection)。
  • 优点:天然物理隔离、审计清晰、实现逻辑简单。
  • 缺点:租户数量庞大时,索引数量会爆炸式增长,导致运维成本和存储成本高昂,数据迁移也变得复杂。

B. 单一大型库 + 元数据过滤 (更常见,对工程能力要求高)

  • 做法:所有租户的数据存储在同一个库中,但每条文本块(Chunk)都附带tenant_idorg_idACL(访问控制列表)等元数据字段。检索时必须先进行过滤(如 tenant_id = ? AND (ACL允许)),再进行召回。
  • 优点:运维简单、资源利用率高。
  • 缺点:一旦过滤逻辑出现漏洞即是严重的安全事故;此外,过滤条件若设计不当可能拖慢检索性能。

实践建议

  • 租户数量少、对隔离性要求极高:采用方案A。
  • 租户数量多、对成本敏感:采用方案B,但必须将权限过滤构建为平台底层“不可绕过”的核心能力。

1.2 权限过滤必须落实在“检索层”,而非仅依赖Prompt

切勿指望通过提示词(如“你只能使用本租户的资料”)来实现权限控制。正确的做法是:在检索阶段,系统就只返回当前租户权限内的文本块,确保大模型在生成答案时根本“看不到”其他租户的数据。

工程落地的必备元数据字段(每条Chunk都应包含)

  • tenant_id (租户标识)
  • source_type (数据源类型,如 wiki/pdf)
  • doc_id, chunk_id (文档及块标识)
  • updated_at (用于基于时效性的过滤)
  • acl (可选,用于部门、角色、用户等更细粒度的权限控制)
  • source_url / page (用于追溯和引用)

2)理解“粒度”:通常涉及两个层面

当讨论“粒度较细”时,在RAG工程中通常指以下两个维度:

2.1 文档粒度 (Document Granularity)

指权限控制和数据隔离的最小单位是什么?是按整篇文档管理,还是更细?
在企业环境中,通常权限管理在文档粒度较为合理,即一整篇Wiki文章或一个PDF文件拥有统一的访问权限。这样做的好处是权限管理模型简单,避免了同一文档部分内容可见、部分不可见的复杂情况。

2.2 切片粒度 (Chunk Granularity)

指将文档切分成多大尺寸的文本块用于索引和召回。
“粒度较细”通常意味着Chunk的尺寸更小。

  • 好处:语义匹配可能更精准。
  • 坏处:单个Chunk可能丢失上下文信息、需要召回更多数量才能覆盖问题、可能引入更多噪声、索引和检索成本更高。

工程实践中的默认建议(非常实用)

  • Wiki文档:按照标题层级(如H2/H3)进行切分,每块控制在300–600个tokens。
  • PDF文档:先按自然段落或小节切分,每块控制在350–700个tokens。
  • 重叠率(Overlap):建议设置为 10–15%,以保持块之间的上下文连贯性。

如果追求“更细的粒度”,不建议直接无限缩小Chunk尺寸。下面介绍一个生产级的优化方案。

3)生产级方案:子块召回 + 父块供给(兼顾细粒度与上下文完整性)

这个方法能有效解决“既要匹配精准,又要上下文完整”的矛盾,特别适合Wiki和PDF场景。

具体做法
在索引阶段,生成两种关联的文本块:

  • 父块 (Parent Chunk):较大的文本块(例如500–900 tokens),用于最终组合并喂给大模型,保证生成答案时的上下文完整性。
  • 子块 (Child Chunk):较细的文本块(例如150–300 tokens),用于精准召回。每个子块需要存储其所属父块的ID (parent_id)。

查询流程

  1. 使用子块进行检索,获取Top K个最相关的结果。
  2. 将这些子块映射回其对应的父块,并根据父块进行去重。
  3. 将去重后的Top N个父块组合起来,拼接到Prompt中供大模型生成答案。

核心收益

  1. 召回更准:利用细粒度的子块进行相似度计算,匹配精度高。
  2. 生成更稳:最终提供给模型的是完整的父块,上下文信息充足。
  3. 特别有效:对于PDF中的表格、法律条款等前后文依赖性强的内容,此方法优势明显。

4)Wiki 与 PDF 的差异化处理建议

4.1 内部Wiki(结构性强,标题清晰)

  • 推荐检索组合
    1. 关键词检索:非常重要,用于精确匹配标题、术语、制度编号。
    2. 向量检索:用于处理同义表达和口语化提问。
    3. 重排(Rerank):锦上添花,能显著去除噪声,提升Top结果质量。
  • 实践要点
    1. 切分Chunk时保留标题路径(如 公司制度 > 财务 > 报销 > 交通费),这对检索结果的可解释性和最终答案的引用都极有帮助。
    2. 对用户查询(Query)进行规范化预处理:去除多余空格、统一中英文标点、标准化数字格式等。

4.2 PDF文档(结构相对弱,解析风险大)

  • 推荐检索组合
    1. 首要任务是把解析做好:使用高质量的PDF解析库(如pdfplumberPyMuPDF),糟糕的解析结果会让后续搜索组件无能为力。
    2. 重排(Rerank)价值更大:PDF解析产生的文本块往往噪声更高,重排模型能有效筛选出真正相关的部分。
  • 实践要点
    1. 对于表格内容,优先将其转换为Markdown表格格式或生成“表格摘要文本”后再入库,这能极大提升检索和理解的准确性。
    2. 必须存储页码信息(page_number),以便在生成答案时提供精确的引用来源。

5)一套“开箱即用”的多租户RAG默认配置(V0起步版)

你可以将以下配置作为初始版本,上线后通过分析日志和用户反馈进行迭代优化。

  • 索引策略

    1. 存储:单一大库 + 元数据过滤(tenant_id为必需字段)。
    2. 块设计:采用子块(160–220 tokens) + 父块(600–900 tokens)的双层结构。
    3. 重叠率:10–15%。
  • 检索策略

    1. 方式:混合检索(关键词 + 向量)。
    2. 先过滤:tenant_id + ACL + doc_status=active
    3. 召回:使用子块检索Top K=40个候选。
    4. 映射与去重:映射到父块后,选取Top N=6个(去重后)最相关的父块。
  • 生成策略

    1. 输出格式:鼓励使用结构化输出(如JSON),并对引用的内容进行校验,确保其来自提供的证据(Evidence)。
    2. 处理未知:当检索到的信息不足以回答问题,应主动触发澄清流程(ask_clarify),而非强行生成可能错误的答案。
  • 观测与审计(多租户必需)

    1. 记录每次请求:tenant_idqueryretrieved_chunk_idsdoc_idssource_urlsprompt_version
    2. 安全审计:定期抽样检查日志,确认“跨租户的Chunk是否被召回”(此情况应为0)。安全是云栈社区技术讨论中永恒的重点。



上一篇:SpringBoot + Vue3开源低代码平台:自研工作流与国产数据库支持,快速构建企业应用
下一篇:Git:被低估的DevOps基石,如何构建可靠的自动化起点?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-24 01:42 , Processed in 0.805513 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表