«

学习笔记-AIGC全栈认知与落地(7)

排骨非人 发布于 阅读:12 技术学习


第7章 · RAG——让AI真正"懂"你的业务(架构重构版)


开场:那个险些让我朋友递交辞职信的安全越权事件

如果说生产环境的业务幻觉会让你被业务方投诉,那么 RAG 系统的安全越权则能直接让你卷铺盖走人。

那是2024年底,我一位做技术负责人的老朋友为集团人力资源和高管团队做了一个内部“组织与战略助手”。由于涉及极其敏感的内部信息——包括还未公开的年度晋升名单、部分高管的薪酬分析以及下一年度的裁员预案——他们在系统设计之初就达成了共识:这个系统只能对 VP 级以上的管理层开放。

项目做得很顺利。他们将 HR 文档、内部邮件、高管例会纪要全部向量化,存入了一个独立的向量数据库中。内测时,高管们对它的理解力和检索速度赞不绝口。

直到内测的第三周,HR 部门的一个刚入职的年轻小姑娘来找我朋友,小声地问:“王哥,听说下个月要公布的晋升名单里有我,是真的吗?”

我朋友脑子里“嗡”的一声。这个名单当时只存在于一份高密级的 Word 文档里,只有 VP 和 HR 总监有权限查看,而她绝对不在这个范围内。

他颤抖着问她是怎么知道的。她说:“我用咱们新上的 AI 助手问‘公司下月有哪些晋升名单’,它就一五一十地列出来了,里面甚至还有我组里其他人的汇报线评估……”

他当晚彻夜未眠,和开发团队一行行对代码,最后发现了一个致命的系统架构漏洞:

他们把所有高密级文档和普通文档全部放在了同一个向量空间里。虽然产品在前端做了针对 VP 级用户的入口访问限制,但后端 RAG 的检索服务却在使用一个“超级管理员(Admin)”账号与向量数据库通信。只要问题击中了相似的向量语义,检索系统就会毫无保留地把越权文档召回,并作为上下文喂给大模型。而大模型根本不知道这份参考资料是“未公开的高密级文档”,它只会忠实地生成答案并呈现给问话的用户。

这个故障让他付出了极大的代价:系统紧急下线整顿,他和 HR 总监一起向集团 CEO 做现场口头复盘,并且花了一个月时间重构了整套系统的权限与过滤架构。

这段“惊魂记”也给我敲响了警钟,让我对 RAG(检索增强生成)有了一个残酷但清醒的认识:RAG 绝不仅仅是“向量数据库+大模型”的拼装玩具。在真实的企业级架构中,它是一场融合了数据脱敏、权限隔离、异构检索和上下文博弈的硬仗。

这一章,我不想重复那些教科书上到处都有的“如何用 LangChain 三行代码写个 RAG”的 Demo,我想从产品架构师的深度视角,为你还原企业级 RAG 落地的三大核心战役,以及我们在高合规、高并发、高准确度要求下,沉淀出的真实架构决策。


7.1 重新认识RAG:企业知识落地的“不可能三角”

在开始谈技术重构之前,我们必须先理清底层的商业与架构逻辑。企业为什么要千方百计地把知识喂给AI?因为大模型原生参数中的知识存在着无法调和的缺陷。

原生大模型的“知识硬伤”

很多非技术出身的产品经理经常问我:“既然大模型已经读了全网那么多书,为什么不直接帮我们写业务合同?”

因为大模型在企业落地时,有三层无法逾越的屏障:

  1. 时效性盲区(The Time Horizon):模型的预训练是一个以月甚至年为单位的周期。训练结束的那一刻,它的世界就定格了。今天上午发布的财报、两小时前修改的API文档,在模型的参数中是不存在的。这就是“静止的世界模型”与“流动的真实世界”之间的鸿沟。
  2. 私有域黑洞(The Private Domain):企业的核心竞争力往往固化在那些不公开的内部wiki、私有代码仓库、CRM历史纪要和合同中。大模型再聪明,也无法推导出一个它从未见过的私有业务规则。这就是所谓的“域外知识(Out-of-Distribution, OOD)”困境。
  3. 不可控幻觉(The Hallucination Cascade):大模型的底层原理是“概率预测下一个词”,它没有“事实检索(Fact-checking)”的直觉。当它参数中的知识不足以回答问题时,它会基于统计概率编造一个听起来极其专业的谎言。在企业协作中,一个“自信的谎言”往往比“不知道”更具破坏性。

为了打破这三层屏障,业界演进出了不同的技术路径。

给大模型注入知识的三条路线对比

作为架构师,你手里的工具箱里有三件武器:RAG、微调(Fine-Tuning)和超长上下文(Long-Context)直塞。很多团队在选型时极易陷入误区,误以为微调一定比RAG高级,或者觉得既然模型支持了128K token,直塞就可以了。

为了让非算法背景的团队快速做决策,我们对这三条路线做一个定量与定性的综合对比:

【图7-1】大模型知识注入三条路线对比

为了让大家在进行架构决策时有具体的数字支撑,我做了一次模拟的成本与效能计算。假设我们需要让大模型掌握一个包含 1000万Token(约合1500万字,大约相当于200本中型专业书)的企业技术文档库,日均查询量为 1万次,对比三种路线的资源与效能表现:

评估维度 路线A:标准RAG 路线B:全量微调(LoRA) 路线C:长上下文直塞
首次建设成本 极低(向量数据库+Embedding API,约2天开发) 极高(需租用GPU显卡进行训练,数据标注成本高,约2-3周) (直接将文档拼接入Prompt)
单次查询Token消耗 ~4,000 Token(100字Query + 3,000字召回上下文) ~300 Token(100字Query + 200字直接生成) 10,001,000 Token(每次必须直塞全量1000万字)
单日运行API费用 ~40元(按市面主流大模型API单价折算) ~3元(微调后模型推理费用稍高,但单次Token消耗极小) ~100,000元(单次调用千万级Token会导致费用爆炸)
知识更新周期 秒级(新文档写入向量库即可生效) 天级/周级(需要重新准备训练数据集并启动微调) 实时(直接修改传入的Prompt内容)
回答可解释性 极高(能够精准列出答案来自哪份文档的哪一页) 极低(知识固化在模型参数中,无法输出引用来源) 中等(模型知道在上下文中,但不易精确定位)
对GPU的依赖 无需训练GPU,只需标准CPU服务器托管向量库 (训练和推理微调模型均需要专属GPU显卡) 无需训练GPU,高度依赖云端超长上下文大模型

从上表可以非常直观地看出一个架构真理:

我的架构判断原则微调(Fine-Tuning)不适合用来给模型填充频繁变化的“事实性知识”。有些团队试图通过每天用新知识微调模型来解决时效性问题,这无异于为了更新每天的新闻让一个成年人天天去做脑部手术,不仅极其消耗算力,还会导致模型产生严重的“灾难性遗忘”(遗忘之前训练好的通用能力)。在企业级场景中,“RAG做事实检索,微调做格式和语气塑造”才是高阶架构的标配。


7.2 战役一:数据吞吐与ACL安全(Ingestion & Security)

绝大多数RAG架构图都把“数据摄入(Ingestion)”简化为一个箭头。但在企业级落地中,这个环节的复杂度占了整套系统工程量的40%。它涉及两个最核心的问题:如何把格式杂乱的PDF/Word变成高质量文本,以及如何在检索时保住企业的数据安全红线

表格与复杂版面的“杀手”:解析器选择

企业内部的文档,往往充斥着两栏排版、三级嵌套表格、复杂的统计图表以及扫描件。如果直接使用市面上开源的通用Python PDF解析库(如PyPDF/PDFMiner),你的RAG在第一步就已经夭折了。

它们会将两栏并排的论文段落按行强行拼接,导致左栏的一半和右栏的一半混在一起,语义彻底崩塌。更不用说表格里的数据,往往会直接变成没有行列关系的无序字符串。

为了应对极其恶劣的企业文档格式,我们在架构上将解析层升级为了“版面分析(Layout Analysis)管道”

  1. 文档分类前置:首先判断文档是电子版(Digital Native)还是扫描件(Scanned PDF)。扫描件必须强制走OCR提取文字。
  2. 版面结构提取(Document Layout Analysis):引入轻量级的目标检测模型(如LayoutLM/YOLOv8-OD),不直接提取字,而是先识别页面上的“元素块”:哪里是标题、哪里是表格、哪里是两栏正文。
  3. 表格专属提取:对于识别出的表格区域,绝不使用普通文本提取。我们使用Table Transformer(如TAT-TR)将表格转换为Markdown格式(包含|-符号),或者是HTML的<table>格式。因为大模型在预训练时读过海量的Markdown和HTML表格,对这种结构化格式的理解力极强。

我第一次做文档预处理时的教训:我当时想当然地认为"PDF就是PDF,用个库提取一下就行"。结果上线后用户投诉"AI给的表格数据是错的"——排查发现,PDF提取时把合并单元格的表格拆成了错乱的文本,数字和表头完全对不上。从那以后,我在做RAG项目时,第一件事就是抽样检查预处理后的文本质量,而不是假设提取工具能正确处理所有格式。

常见坑与具体表现

预处理流水线的最佳实践(Python代码逻辑抽象)
为了让工程落地,我们通常把这个流水线抽象为一个流水线类(DocumentPipeline):

class LayoutAwareParser:
    def __init__(self):
        self.layout_model = load_layoutlm_model()
        self.table_extractor = load_table_transformer()
        self.ocr_engine = load_ocr_engine()

    def parse_pdf(self, pdf_path):
        pages = convert_pdf_to_images(pdf_path)
        extracted_text = []
        for page_img in pages:
            # 1. 识别页面布局区域
            layout_blocks = self.layout_model.detect(page_img)
            # 对区域进行由上到下、由左到右的逻辑重新排序(解决双栏混淆问题)
            sorted_blocks = sorted(layout_blocks, key=lambda b: (b.bbox.y1, b.bbox.x1))

            for block in sorted_blocks:
                if block.type == "text":
                    text = self.ocr_engine.extract(block.image)
                    extracted_text.append(text)
                elif block.type == "table":
                    # 表格区域单独处理,转为带有 Markdown 语法格式的文本块
                    markdown_table = self.table_extractor.to_markdown(block.image)
                    extracted_text.append(f"\n{markdown_table}\n")
                elif block.type == "header" or block.type == "footer":
                    # 过滤页眉页脚干扰
                    continue
        return "\n".join(extracted_text)


【图7-2】文档版面解析与提取管道

“安全第一”:如何将企业ACL接入RAG

回到我开场提到的那个高危故障。如何防止AI助手成为内部黑客工具?答案是:检索阶段的ACL(访问控制列表)双向校验

如果用户在企业的角色发生变化(比如离职或调岗),或者某份文档的阅读权限被临时修改了,我们该怎么办?难道要把向量数据库里几百万个受影响的切片全部捞出来,重新修改元数据再写入一次吗?这在大规模分布式系统中,无论是写入延迟还是算力消耗都是不可承受的。

为了攻克这个难题,我们设计了一套“解耦型动态ACL架构设计模式”

【图7-3】解耦型动态ACL过滤架构

在这个设计中,我们实现权限解耦的核心在于:切片 metadata 中绝对不能直接存储“允许访问的具体用户列表(allowed_users)”,因为用户是极高频变动的实体。相反,我们应该在元数据中绑定相对稳定的“资源实体ID(resource_id)”“部门/角色安全标签(department_id/clearance_tag)”

具体运作流程如下:

  1. 切片入库阶段(Ingestion)
    文档切片存入向量数据库时,元数据中只记录该文档在企业系统中的唯一标识。例如:
    {
      "chunk_id": "ch_7_102",
      "text": "2026年度集团核心裁员名单...",
      "metadata": {
        "resource_id": "res_99872",
        "department_id": "dept_001_hr",
        "clearance_required": "level_5_secret"
      }
    }
  2. 查询阶段(Query Processing)
    当用户“张三”提问时,RAG网关会在第一时间向企业的IAM(身份权限系统)或统一用户中心发起一个微服务调用:
    • 输入:用户张三的Token。
    • 输出:张三当前合法拥有的 department_ids(例如 ["dept_999_sales", "dept_002_legal"]),以及他的安全密级 clearance(例如 level_3_confidential)。
  3. 物理检索阶段(Retrieval)
    向量数据库在接收到检索请求时,网关动态将张三的 IAM 权限结果拼装成元数据过滤器:

    # 动态权限过滤拼装,安全密级和部门属性双向匹配
    acl_filter = {
        "$and": [
            {"clearance_required": {"$lte": user_iam_info["clearance_level"]}},
            {
                "$or": [
                    {"department_id": {"$in": user_iam_info["authorized_depts"]}},
                    {"resource_id": {"$in": user_iam_info["individual_whitelisted_resources"]}}
                ]
            }
        ]
    }
    
    # 将权限过滤器作为元数据过滤参数传递给向量检索引擎
    results = vector_db.query(
        vector=query_vector,
        top_k=5,
        filter=acl_filter
    )

架构决策连接:通过这种动态解耦的设计,文档在向量库中的元数据只存储静态的“安全属性限制”,而将“谁能访问哪些属性”这一极度动态的业务规则交给了专门的IAM系统去管理。即便一个高管今天突然离职,IAM系统瞬间吊销其权限,他在下一秒向大模型助手提问时,底层检索便会自动将所有高密级文档切片过滤,召回结果直接为空。这才是真正经得起安全合规审计的企业级RAG设计方案。


7.3 战役二:检索精度的致命对决(Retrieval Strategy)

很多刚入行的工程师对检索有着盲目的信心:“Embedding模型能理解语义,那还要什么搜索引擎?”

然而在真实的业务场景中,纯向量检索(Semantic Search)是一场灾难

为什么纯向量检索会失效

我曾在重构一个内部IT服务台的RAG系统时,遇到了一个诡异的问题。
用户问:“我的电脑蓝屏了,报错代码是 0x0000007B,怎么解决?”
系统检索回来的Top-3文档居然是:

  1. “如何清理电脑C盘空间”
  2. “为什么电脑会无故死机”
  3. “公司电脑申请配置标准”

真正包含解决方案的文档——“关于 0x0000007B 蓝屏报错的临时处理预案”排在第10名开外,完全没有被召回。

为什么会这样?
因为Embedding模型会将整段文本压缩成一个几百维的浮点数向量,它更倾向于捕捉整体的、宏观的语义语义(例如“电脑故障、报销、申请”等)。但是对于企业场景中极其关键的强专有名词(如报错码 0x0000007B、产品型号 C3-Pro-2026、员工姓名 张三,在向量空间中,它们因为极其罕见,可能被判定为不那么重要,或者其微弱的特征在压缩过程中被其他高频词的特征“稀释”掉了。

混合检索(Hybrid Search):向量与关键词的结合

为了解决向量检索对专有名词不敏感的问题,现代RAG架构的必选项是混合检索(Hybrid Search)

我们将用户的输入Query,分发到两个并行的检索管道中:

  1. 稠密检索(Dense Retrieval / Vector Search):通过Embedding模型(如BGE-large-zh-v1.5)捕捉Query的语义意图(理解“蓝屏”代表“死机故障”)。
  2. 稀疏检索(Sparse Retrieval / Keyword Search):通过经典的BM25算法,对文档库进行分词、计算TF-IDF。它能够像精准的狙击枪一样,把包含 0x0000007B 的文档块死死锁定并召回。

更优雅的下一代检索:BGE-M3统一稀疏-稠密向量引擎
在以往的架构中,实现混合检索需要同时维护一个 Elasticsearch 集群(负责 BM25)和一个向量数据库集群(负责向量检索),运维复杂度极高。
我们在重构方案中引入了BGE-M3(多功能、多语言、多粒度模型),这个模型的神奇之处在于它能实现单模型、单通道的三重检索能力

通过 BGE-M3,我们可以直接在 Milvus 或 PGVector 数据库中建立多列表索引。检索时,通过单次 API 呼叫即可同时拿到向量相关度得分和稀疏分词精确匹配分,在数据库底层做极速的 RRF 融合。这大幅简化了我们整体底层架构的运维链条。

【图7-4】混合检索与Reranking重排序链路

架构大杀器:精排模型(Reranker)的引入

混合检索能保证“把鱼都捞进网里(高召回率 Recall)”,但捞出来的鱼里往往混杂着很多死鱼烂虾。为了把真正金子般的答案推到大模型的眼前,我们引入了RAG架构的画龙点睛之笔:Reranker(重排序模型)

为什么需要Reranker?因为双塔结构的Embedding模型有其理论上限(Query和文档是在不了解对方的情况下独立生成的编码)。而交叉双塔结构的Reranker(如Cohere Rerank、BGE-Reranker)则是将Query和每一个检索出来的文档块拼接成一个长文本,送入模型计算,这样模型就能在自注意力机制中极度精细地评估“这段文字到底是不是在针对性地回答这个问题”。

我的架构实测数据
在一个包含10万份技术规格书的庞大数据库中,我们的召回指标发生了戏剧性的变化:

检索方案 Recall@5(前5结果包含答案的比例) 检索平均延迟
纯向量检索 64.2% ~30ms
纯BM25检索 58.7% ~10ms
混合检索(Vector + BM25) 81.4% ~45ms
混合检索 + Reranker (Top-15 to Top-5) 94.8% ~180ms

架构师的权衡思考:引入Reranker虽然会将检索耗时增加约100-150ms(主要取决于Reranker模型的尺寸和推理算力),但是Recall@5直接拉升了十几个百分点!大模型“看错资料”的几率降低了近3倍。这笔用微小延迟换取准确率巨大跃升的交易,在企业级场景中极其划算。


7.4 战役三:上下文管理与精准生成(Generation Strategy)

好不容易检索到了最相关的4个文档切片,很多团队的处理方式是:把它们粗暴地拼接在一起,塞进Prompt,然后直接喂给大模型。

但你很快会遭遇两个大模型落地的经典陷阱:“迷失在中间(Lost in the Middle)”“无中生有的引用(Ghost Reference)”

陷阱一:迷失在中间(Lost in the Middle)

2023年底,斯坦福大学的一篇论文揭示了一个让大模型非常尴尬的特性:大模型对长上下文的头部和尾部信息极其敏感,但很容易忽略上下文“中间部分”的信息

【图7-5】“迷失在中间”现象与优化策略

如果你检索回来5个文档,最核心的答案恰好排在第3个,而你原封不动地把这5个切片按顺序塞进上下文里。大模型在处理时,受限于长距离注意力的衰减,极大概率会漏掉这第3个切片中的关键数字。

重构解法一:小到大检索(Sentence Window Retrieval / Parent Document Retrieval)

为了既让大模型在检索时感知到“精确的局部语义”,又在生成时拥有“宽阔的整体背景”,我们抛弃了“检索什么就直塞什么”的陈旧做法,采用父子文档级联(Parent-Child Document Strategy)

  1. 子文档(Child Chunk)向量化:我们将文档切分成极其细小、语义精确的子文档(例如100-200字),只拿子文档做向量化。由于子文档信息密度极高,能被非常精准地检索到。
  2. 父文档(Parent Chunk)回捞注入:每个子文档在写入向量库时,都会记录一个其所属的更宽阔的父文档ID(例如800-1500字的一整节,或者当前段落前后的上下句窗口)。当子文档被检索命中并经过Reranker筛选后,我们在最终塞进Prompt前,根据子文档的关联关系,自动“回捞并替换”为对应的父文档大段落
  3. 重排序注入(Heuristic Placement):如果依然命中多个切片,我们在组装Prompt时,人为干预拼接顺序:将相关性得分最高的第1、2名切片,物理拼接到Prompt最靠前的位置;将第3名拼接到Prompt最末尾,把相关性最弱的第4名埋在最中间。利用大模型注意力的“U型曲线”,将最核心的信息物理性地顶到最敏感的区域。

为了帮大家建立直观的工程概念,我把父子文档级联的数据结构在数据库中的映射逻辑画了出来:

// 子文档(用于语义特征检索)
{
  "child_chunk_id": "child_7_3024",
  "parent_id": "parent_7_002",
  "text_vector": [0.0123, -0.0456, ..., 0.9876],
  "raw_text": "深圳及北京地区协议酒店报销上限为每天600元。"
}

// 父文档(用于塞进大模型的Prompt作为背景)
{
  "parent_chunk_id": "parent_7_002",
  "document_name": "2026版腾讯云差旅合规标准手册.pdf",
  "full_text": "第4章 差旅住宿标准。\n4.1 境内出差:境内出差报销需严格遵守对应级别酒店标准。一线城市(深圳及北京地区)协议酒店报销上限为每天600元。二线城市报销上限为每天450元。若由于展会、大型活动等不可抗力导致价格超标,需提前向部门VP报备..."
}

这种架构设计的高明之处在于:向量检索时,我们寻找的是那个仅含10余字的精准事实(“深圳协议酒店600元”),但在生成时,大模型却获得了包含“二线城市、不可抗力、向部门VP报备”在内的整套逻辑背景(1000字)。大模型不再是“断章取义”,而是“高屋建瓴”。

陷阱二:如何消灭AI的“幻觉引用”

“老师,我的大模型确实给出了引用链接,但我点进去,根本没有那个文件,或者那个网页跟它说的事毫不相干!”

这是最常见的产品合规投诉。大模型在被要求输出“依据[文档A]第3章回答”时,它的“下一个词预测”本能会倾向于编造一些符合格式要求的、长得极其逼真的虚拟文件名 and 虚构章节名。

我们在重构时的Prompt模板设计(实战沉淀,已申请内部专利)

要阻止模型凭空捏造引用,核心是通过“逻辑断言”与“强制无解兜底”。我们目前在生产环境中跑得最稳的Prompt格式如下:

# 角色与系统指令
你是一个高度严谨的、只基于客观参考资料进行分析的企业分析师。

# 核心红线规则(必须无条件遵守)
1. 你的所有回答,必须百分之百基于【参考资料】中提供的内容。
2. 严禁基于你自身的先验知识、网络常识进行推理或推导。
3. 如果参考资料中的内容无法拼凑出完整的、无歧义的答案,你必须直接、诚实地回答:“根据当前内部资料,无法找到关于[XX问题]的确切信息,建议联系业务接口人进行线下核对。” 绝对不允许给出包含猜测性质的、合理的“建议”或“可能答案”。
4. 对于你给出的每一条事实陈述,必须在句尾通过 `[^文档编号-章节]` 的格式显式标注引用来源。绝对不允许合并引用或捏造未在参考资料中出现的文档编号。

# 参考资料
---
【参考文档 1】
ID: DOC_2026_HR_004
标题: 2026年企业差旅标准暂行条例
内容: ...深圳及北京地区协议酒店报销上限为每天600元...
---
【参考文档 2】
ID: DOC_2026_FI_012
标题: 财务报销审批系统常见Q&A
内容: ...若酒店费用超出协议上限,需由部门VP在系统内进行特批说明后方可报销...
---

# 用户问题
深圳出差酒店超标了,还能报销吗?怎么报?

# 回答示范格式
根据最新条例,深圳地区的协议酒店报销上限为每天600元[^DOC_2026_HR_004]。若您的费用超出了这个上限,依然可以报销,但必须由您的部门VP在报销系统内进行特批说明[^DOC_2026_FI_012]。

通过这套精心雕琢的架构和Prompt规则,我们成功将生产环境中的“幻觉引用率”从最初的14.8%生生拉低到了0.3%以下。如果检索不到,大模型会非常顺从地表示“对不起,当前资料不支持回答”,虽然产品体验上变保守了,但在商业合规上,我们彻底筑牢了防线。


7.5 评估与迭代:RAG落地的一套可量化度量体系

你做了一大堆重构,换了切片策略,加了Reranker,怎么向老板和业务方证明“效果变好了”?

很多团队的做法是让团队里的几个人每天“盲测(Blind Test)”几十个问题,凭主观感受打个分。这种不规范的迭代方法,会导致系统陷入“调好了A,改坏了B”的钟摆效应。

要让RAG工程化迭代,我们必须引入RAG的三元评测法(Triad of RAG Evaluation)。在生产中,我们使用目前业界最成熟的 Ragas 框架对系统进行自动化质量量化。

这套评测体系主要围绕以下三大指标进行机器(通过一个高阶审校模型,如GPT-4)自动化打分:

【图7-6】RAGAS三元评估体系

指标一:忠实度(Faithfulness / 无幻觉度)

我们常在生产中部署如下的裁判模型 Prompt 模板

# 任务
你的任务是评估大模型生成的 [Answer] 是否忠实于给定的 [Context]。

# 评估步骤
1. 将 [Answer] 拆解为若干条独立的事实陈述(Statements)。
2. 对于每条 Statement,检查 [Context] 是否提供了直接的逻辑支持。如果提供了,标记为 1;否则标记为 0。
3. 最终得分 = 标记为 1 的 Statement 数量 / 总 Statement 数量。

[Context]
{context}

[Answer]
{answer}

请严格按 JSON 格式输出,例如:
{
  "statements_evaluation": [
    {"statement": "...", "supported": 1, "reason": "..."},
    {"statement": "...", "supported": 0, "reason": "..."}
  ],
  "score": 0.5
}

$$\text{Faithfulness} = \frac{\text{可在Context中找到支持的事实陈述数量}}{\text{Answer中总的事实陈述数量}}$$

指标二:回答相关性(Answer Relevance)

指标三:上下文召回率(Context Recall)

$$\text{Context Recall} = \frac{\text{Ground Truth中被Context覆盖的语句数}}{\text{Ground Truth总语句数}}$$

产品架构师的建议:在你的RAG系统上线前,必须强制建立一个包含至少150个“典型问题-标准答案(Ground Truth)”的回归测试集。每次对系统进行重大改动(比如换数据库、调整Top-K、修改Prompt),都要把这个测试集在Ragas框架里跑一遍,输出这三大指标的雷达图。只有当三项指标均没有产生向下抖动时,改动才允许合并进主分支。这是大模型软件工程(LLM-Ops)最基本的纪律。


7.6 什么时候不应该做RAG

写到这里,我相信你已经感受到了构建一个靠谱的RAG系统所需要付出的工程汗水。我想在这一章的最后泼一盆冷水:作为架构师,你必须要克制自己的技术冲动。很多时候,RAG是错误的选型。

在评估业务需求时,如果发现以下特征,你应该主动考虑“不要用RAG”:

  1. 高精度的高维数据分析(Text-to-SQL更配)
    如果用户的需求是“帮我分析一下上个月深圳地区销售额排前三的客户各是谁,他们各贡献了多少利润”。
    这需要对数据进行高精度的聚合、计算和过滤。如果你试图把销售报表转成纯文本切片塞进RAG,AI极大率会漏掉某些行,或者计算出错误的加总。

    替代方案:搭建 Text-to-SQL(自然语言转数据库查询)系统,或者使用具有分析计算能力的 Agent 运行独立的 Python 代码去查数据库(见第8章)。

  2. 纯粹的长程推理任务(CoT / 提示词更配)
    如果你的任务是“根据一堆混杂的代码重构出一个新的逻辑”,或者是“分析一桩复杂民事纠纷中各方的责任逻辑”。
    这类场景需要的是大模型的深度逻辑推理能力,而不是去检索一个现成的知识块。你塞给它过多的背景知识,反而会破坏模型的推理带宽。
  3. 知识库极小且高度私密(单会话临时直塞)
    如果你的用户群体每次对话都只需要分析一个刚刚上传的临时文档(如一个特定的标书PDF),且在会话结束后不保留数据。

    替代方案:不要为了这一个临时文档去建立复杂的向量数据库,直接在内存中读取文本,作为会话的当前上下文(Using Context Window as Database)丢给模型,既快速又绝对安全。

  4. 秒级/毫秒级的实时交易与时序数据更新(缓存与时序数据库更配)
    如果你的业务场景涉及股票价格实时变动、打车软件里的司机GPS坐标实时更新、高频交易流、或者工业物联网(IoT)传感器的秒级波形图。
    大模型本身无法进行这种亚秒级的数据同步。如果你试图通过每毫秒将新状态进行 Embedding 并写入向量数据库来解决,你会瞬间遭遇:

    • 向量库写吞吐量爆炸:高频更新会导致分布式向量数据库不断触发索引重建(Index Rebuilding),引起系统锁死。
    • GPU推理开销雪崩:每秒几万条数据的向量化会消耗难以估量的GPU推理算力。

    替代方案:这类高频变动的流式数据,正确架构是让它们老老实实呆在 Redis 缓存或 InfluxDB 时序数据库中。当大模型遇到相关问题时,通过 Function Calling(函数调用 / 插件化架构) 直接发起一个超轻量级的 API 查询,带回最新的数值。不要试图让 RAG 去承载它无法承受之重的流式计算。

RAG vs 微调 vs 长上下文 vs 知识图谱决策矩阵

最后,为了便于产品团队在面对纷繁复杂的业务需求时迅速达成架构共识,我将四种大模型知识增强路径的决策因子总结为了一个高度实用的决策矩阵:

维度对比 RAG(检索增强) 微调(LoRA/全量) 超长上下文直塞 知识图谱(Graph RAG)
首选知识载体 非结构化文档库(PDF/Wiki) 稳定领域能力/格式规范 单一长文本(<5万字) 强关联、多实体网络
知识更新频率 实时(秒级注入) 极慢(需要天/周级训练) 实时(随对话即时传递) 中等(图谱拓扑需要更新)
黑盒与可追溯性 开箱白盒(附带源引用) 黑盒(无法追溯依据) 中等(长文本中搜索困难) 极高(可清晰追溯推理路径)
单次推理成本 中等(检索API+上下文Token) 极低(无冗余上下文Token) 极高(每次加载千万级Token) 较高(图查询+子图文本检索)
核心局限与克星 无法直接进行大规模精准计算 无法应对日更级的数据变动 受制于极限上下文吞吐预算 知识图谱建库工程极其沉重

本章小结

RAG的魅力在于,它打破了模型的时空枷锁,让大模型有了“现查现用”的知识外脑;但RAG的残忍之处在于,它是一块试金石,瞬间拉开了“玩具级Demo”和“生产级架构”的差距。

本章核心要点:

  1. 安全是一票否决的底线:在企业级场景中,RAG网关必须将用户身份标识透传,并在向量数据库物理检索时作为元数据硬过滤条件(Metadata Filter),严防安全越权。
  2. 没有高质量的预处理就不要奢谈检索:针对表格和复杂版面,必须建立包括目标检测和Table Transformer在内的版面分析(Layout-Aware)提取管道。
  3. 混合检索与精排重塑相关性:纯向量检索不等于全部。通过 BM25 + 向量检索的混合检索,并配合 Reranker 模型的精排,能够大幅度提升系统的检索召回精度。
  4. 管理大模型的注意力:利用“小到大检索(Parent-Child)”和“Prompt重排序”,让大模型对检索结果的吸收达到最大化,并依靠严苛的Prompt规则杜绝AI幻觉引用。
  5. 不规范打分是架构师的慢性自杀:通过回归测试集结合 Ragas 三元评估法,将系统的每一次改动落地到可量化、可追踪的雷达图指标上。

下章预告

到此为止,我们已经在脑海中建立了一个强壮的技术地基:我们学会了如何指挥模型(第6章:提示工程),学会了如何给模型提供安全、精准的知识支持(第7章:RAG)。

但是,如果用户给出的不是一个具体的、一问一答的问题,而是一个漫长的、复杂的任务流呢?

比如:“亚哥,下周一我们要和腾讯云的专家组开一个技术对接会。你帮我关注一下这周末有没有关于他们最新MaaS网关的技术更新或竞品分析。如果有,请帮我汇总出一份摘要,列出我们可能需要挑战他们的三个技术问题,在周日晚上20:00前,写成一封邮件发到我组里所有架构师的邮箱里。”

这个需求中,大模型不能只是扮演一个“查资料的图书管理员”,它必须能自主理解目标、拆解复杂任务、编写执行脚本、在互联网上巡检搜索、自我纠错,最后调用邮件接口把事情办妥

这就要求模型跳出静态问答的牢笼,化身为一个可以与物理世界产生真实交互的实体。
下一章,我们推开大模型最激动人心的一扇大门:AI Agent(智能体)的架构艺术


延伸阅读