RAG Works — 直到你遇到长尾

发布: (2026年1月12日 GMT+8 07:23)
11 min read
原文: Dev.to

Source: Dev.to

如果你每天使用 ChatGPT 或类似的大型语言模型,可能已经对它们产生了一定的信任。它们表达清晰、速度快,且常常表现出令人印象深刻的能力。许多工程师已经在编码帮助、文档编写或架构头脑风暴中依赖它们。

然而,迟早你会遇到瓶颈。

当你提出一个在日常工作中真正重要的问题——比如内部的、最近的或高度具体的内容——模型却突然变得模糊、错误,甚至自信地给出错误答案。这不是提示(prompting)的问题,而是结构性的局限。

本文将探讨这种现象背后的原因、当前解决方案为何只能部分缓解问题,以及为何将知识直接训练进模型权重可能成为未来的关键方向。

The real problem is not the knowledge cutoff

知识截止是大型语言模型(LLM)最显眼的限制。模型只在某个时间点之前的数据上进行训练,之后发生的任何事情对它们来说根本不存在。

然而,在实际使用中,这往往并不是最痛苦的问题。网页搜索、API 和工具往往可以缓解这一限制。

更深层次的问题是 知识的长尾

在真实的生产环境中,最有价值的问题很少涉及公开的、文档齐全的事实。它们往往涉及内部系统、未记录的决策、专有流程以及在公共互联网中不存在的领域特定约定。

示例包括

  • 为什么这个服务在看似无关的更改后开始出现故障?
  • 这个架构权衡是否已经在内部讨论过?
  • 我们公司如何解释某项具体的监管约束?

这些问题位于长尾,而正是大型基础模型表现最差的地方。

三种向语言模型提供知识的方式

如果去掉工具细节,实际上只有三种根本方式可以让语言模型“知道”新信息。

  1. 直接将知识放入提示中。
  2. 在推理时检索相关信息。
  3. 将知识训练进模型本身。

目前大多数系统几乎完全依赖前两种方式。

完整上下文:简单、昂贵且脆弱

最朴素的解决方案是把所有内容都放进提示词中。

prompt = f"""
You are an assistant with access to our internal documentation.

{internal_docs}

Question:
Why does service X fail under load?
"""

对于小文档,这种方式可行。实现简单,且不需要额外的基础设施。

然而,随着上下文规模的增长,会同时出现几个问题:

  • 令牌成本线性增长。
  • 延迟显著提升。
  • 随着加入更多弱相关信息,推理质量下降。

这不是实现上的问题,而是 transformer 模型工作原理的直接后果。

Transformer瓶颈与上下文退化

Transformers 依赖自注意力(self‑attention),即每个 token 都会关注所有其他 token。这导致相对于输入长度的 quadratic complexity

即使现代模型在技术上可以接受非常大的上下文窗口,仍然存在一个重要区别:

  • Not crashing 与长输入,和
  • Reasoning well 在长输入上的表现。

经验表明,随着上下文长度的增加,性能会下降,即使相关信息保持不变。模型仍然会生成流畅的文本,但其将正确信息片段连接起来的能力会恶化。这种现象通常被称为 context rot

因此,单纯扩大上下文窗口并不是一个可行的长期解决方案。

RAG:通过嵌入的外部记忆

为了避免将所有内容都塞进提示,业界趋向于使用 检索增强生成(Retrieval‑Augmented Generation,RAG)

其思路是将文档存储在外部,使用嵌入(embeddings)检索最相关的文档,然后仅将这些文档注入提示中。

一个最小的 Python 示例如下:

from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
vector_store = Chroma.from_documents(
    documents=docs,
    embedding=embeddings
)

results = vector_store.similarity_search(
    query="Why does the CI pipeline fail?",
    k=5
)

RAG 之所以受欢迎,是因为它灵活、成本相对较低且易于部署。如今,它已成为为基于 LLM 的系统添加记忆的默认方案。

为什么 RAG 本质上受限

  1. 检索 ≠ 推理 – 仅选择少量相关片段并不能保证模型能够正确地将它们组合,尤其是当答案依赖于隐含关系或跨文档的多步推理时。
  2. 静态相似度 – 嵌入向量编码的是单一的全局相似度概念,无法适应局部领域语义。那些本不应混淆的文档往往在向量空间中靠得很近。
  3. 安全性问题 – 嵌入本身并不具备固有的安全性;只要付出足够的努力,就可以重建原始文本的大部分内容,使得向量数据库不适合作为隐私保护的抽象层。

这些局限表明,RAG 虽然强大,但并不完整。

天真的微调陷阱

此时,直接在内部数据上微调模型似乎很诱人。

实际上,天真的微调几乎总是会失败。直接在小规模、专业化的数据集上训练会导致模型 过拟合,失去通用推理能力,并且忘记先前学到的知识——这种现象被称为 灾难性遗忘

其结果是模型只会记忆,却不理解。

合成数据:缺失的环节

关键的洞见在于生成能够捕获文档中知识的合成任务,而不是直接喂入原始文本。

合成知识生成

我们不再对原始文档进行训练,而是生成大量且多样的任务,这些任务描述了文档中包含的知识。这些任务可以包括问答对、解释、改写以及反事实情形。

一个简化的 Python 示例:

def generate_qa(doc):
    return {
        "instruction": f"Explain the key idea behind: {doc.title}",
        "response": doc.summary
    }

synthetic_dataset = [generate_qa(doc) for doc in internal_docs]

这种方法教授的是领域知识,而不是表层文本。令人惊讶的是,只要合成数据足够多样,即使原始数据集很小,它也能发挥作用。

Source:

在不破坏模型的情况下进行权重训练

现代系统通过使用 参数高效微调 来避免灾难性遗忘:不再更新所有权重,而是只修改一小部分有针对性的子集。

低秩适配 (LoRA)

LoRA 在选定的层中插入低秩矩阵,使模型能够以最小的改动进行适配。

from peft import LoraConfig

lora_config = LoraConfig(
    r=8,                     # 低秩矩阵的秩
    lora_alpha=16,           # 缩放因子
    target_modules=["q_proj", "v_proj"]  # 要适配的层
)

核心思想:进行小范围、局部的更新,以引导模型而不覆盖其已有知识。

其他参数高效技术

  • 前缀调优 – 在输入序列前添加可学习的 token。
  • 记忆层 – 添加外部记忆模块,用于存储任务特定信息。

所有这些方法遵循相同的原则:在保留大部分预训练权重的同时,仅学习一小套轻量级新参数,实现适应性与稳定性的平衡。

混合未来:上下文、检索与权重

没有任何一种技术能够完全取代其他技术。最有效的系统会结合这三者:

  • 上下文 – 对即时指令很有用。
  • 检索 – 对新鲜或经常变化的数据至关重要。
  • 训练到权重 – 提供检索单独无法实现的深层、连贯的领域理解。

未来的核心设计问题不在于是否在私有知识上训练模型,而在于 哪些 知识应该存放在权重中,哪些应该在推理时处理。

Conclusion

RAG 是一种务实且强大的解决方案,它将继续成为 LLM 生态系统的一部分。然而,在对专门知识进行深度推理时,它从根本上受到限制。

随着训练技术变得更高效,将知识训练进权重将不再是研究好奇心——它将成为一种工程决策。

从长远来看,最有价值的 LLM 系统不会由它们使用的基础模型决定,而是由 它们所学的内容教学的严谨程度 决定。

Back to Blog

相关文章

阅读更多 »

构建可靠的 RAG 系统

封面图片:Building Reliable RAG Systems https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-...

第4部分 — 检索即系统

为什么大多数实用的 GenAI 系统是检索中心的——大型语言模型(LLMs)是基于静态数据进行训练的,这导致:- 知识陈旧 - 缺失领域……