Towards Data Science

RAG vs Fine-Tuning Explained: What They Actually Do and When to Use Each

8.5内容质量

TL;DR · AI 摘要

RAG与微调解决不同问题,非竞争关系,应根据具体需求选择。RAG通过检索增强生成,微调通过参数调整适应领域,各有适用场景。

核心要点

  • RAG通过检索外部信息增强模型响应,无需修改模型结构
  • 微调通过调整模型参数适应特定领域,但成本较高
  • 选择RAG或微调应基于数据量、成本和效果需求,无绝对优劣

结构提纲

按章节快速跳转。

  1. 指出RAG微调的对比讨论是技术选型的核心问题

  2. 详细说明RAG通过检索增强生成的完整工作流程

  3. 解释微调通过参数调整适应特定领域的技术原理

  4. 比较两者在成本、效果和适用场景的差异

  5. 明确RAG适合知识密集型任务,微调适合参数敏感型任务

  6. 强调两者互补性,无绝对优劣

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • RAG vs 微调
    • RAG机制
      • 检索增强生成
      • 无需修改模型
    • 微调机制
      • 参数调整
      • 领域适应
    • 对比分析
      • 成本差异
      • 效果差异

金句 / Highlights

值得收藏与分享的关键句。

#RAG#微调#LLM#AI应用
打开原文

RAG 与微调解析:它们实际的作用及使用场景 | Towards Data Science

大型语言模型

RAG 与微调解析:它们实际的作用及使用场景

两种技术,两种不同的问题,以及为什么这个问题其实并不是“哪一种更胜一筹”

Maria Mouschoutzi

2026年7月12日

11分钟阅读

分享

作者使用ChatGPT Images 2.0生成的图片

在过去一年左右的时间里,我写了很多关于RAG的内容,从《使用ChatGPT API和LangChain的RAG旅行者指南》开始,然后探讨了与RAG和AI相关的各种主题,如分块、混合搜索、重排序、上下文检索,以及关于检索质量评估的三部分系列文章。换句话说,我们在RAG方面已经覆盖了很多内容。

我们没有明确讨论的另一个主要技术是,当人们想要为特定领域改进LLM应用时,通常会采用的微调技术。特别是,我们还没有讨论当将这两种技术并列比较并试图确定实际需要哪一种时会发生什么。

如果你在网上搜索“RAG vs 微调”,你会发现很多内容将这视为一场有胜负的比赛。对一些人来说,RAG胜出是因为设置成本更低,对另一些人来说,微调胜出是因为能产生更好的结果,等等。这种表述的问题在于,它本质上具有误导性,因为RAG和微调并不是相互竞争的技术,而是解决AI应用不同层级不同问题的技术。理解每种技术实际的作用是做出良好决策的前提。

那么,让我们一起来看看!

🍨 DataCream 是一份关于AI、数据和科技的简报。如果你对这些主题感兴趣,请在这里订阅!

RAG是什么以及它实际做了什么?

如果你已经阅读了这个系列,你已经对RAG有了扎实的直觉。但让我们再明确一次,因为与后续微调的比较中,精确的定义非常重要。

因此,RAG(检索增强生成)是一种技术,它通过在推理时检索相关外部信息并将其注入提示中,来增强LLM的响应。模型本身没有任何改变。改变的是它作为输入看到的内容。

流程大致如下:

  • 首先,外部文档(我们想要利用的知识库)被处理成向量嵌入并存储在向量数据库中。
  • 当用户提交查询时,查询也会被转换为嵌入,然后从数据库中检索出语义上最相似的文档片段。
  • 这些片段随后与用户的查询一起传递给LLM,这样模型就可以基于特定检索到的上下文生成响应。

就这样。

以下是使用OpenAI API的最小RAG示例:

code
from openai import OpenAI
import numpy as np

client = OpenAI(api_key="your_api_key")

# 我们的微型知识库
documents = [
    "pialgorithms 是一个由AI驱动的文档管理平台。",
    "pialgorithms 允许团队搜索、提取和自动化文档工作流程。",
    "pialgorithms 于希腊雅典成立。",
]

# 嵌入知识库
def embed(texts):
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=texts
    )
    return [r.embedding for r in response.data]

doc_embeddings = embed(documents)

将用户查询嵌入并检索最相关的内容块

query = "Where is pialgorithms based?" query_embedding = embed([query])[0]

余弦相似度

def cosine_similarity(a, b): return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

similarities = [cosine_similarity(query_embedding, doc_emb) for doc_emb in doc_embeddings] best_match = documents[np.argmax(similarities)]

将检索到的上下文注入提示

response = client.chat.completions.create( model="gpt-4o-mini", messages=[ { "role": "system", "content": f"仅使用以下上下文回答用户的问题:\n\n{best_match}" }, { "role": "user", "content": query } ] )

print(response.choices[0].message.content)

pialgorithms 位于希腊雅典。

code

让我们花点时间理解这里真正发生的事情。当然,模型本身从训练数据中完全不知道 pialgorithms 的信息,但因为我们检索到了正确的文档片段并将其注入提示中,模型就能够准确回答。这些知识来自模型外部,在查询时动态提供,而模型本身保持不变。

这就是 RAG 的核心机制:它让模型能够访问从未训练过的外部知识,并在推理时动态获取这些知识。

根据其工作原理,RAG 在特定类型的任务中表现优异,例如:

- 回答关于模型从未见过的文档、知识库或数据的问题
- 在无需重新训练的情况下保持最新,因为知识库可以随时独立更新
- 提供可追溯、可引用的答案,因为你可以明确知道检索了哪个文档片段
- 安全处理私有或专有信息,而不会将这些信息包含在模型中

另一方面,RAG 无法做到以下事情:它不会改变模型的行为方式、语气、推理风格或任务表现。如果模型本身倾向于冗长,RAG 不会让它更简洁。如果它在特定输出格式上有困难,RAG 也不会解决这个问题。

## 什么是微调,它实际上做了什么?

微调是将预训练模型在新的、特定任务的数据集上继续训练的过程,在此过程中更新模型的权重。换句话说,虽然 RAG 改变了模型的输入,但微调改变了模型本身。

更具体地说,像 GPT-4o-mini 这样的基础模型是在大规模通用数据集上预训练的。微调会使用该模型,并在特定于我们具体使用场景的示例上运行额外的、较短的训练循环。这些示例通常以输入-输出对的形式存在。通过这种方式,模型的权重会被调整,使其生成的输出更接近这些示例对。

以下是使用 OpenAI API 进行微调任务的示例:

from openai import OpenAI import json

client = OpenAI(api_key="your_api_key")

code

# 第 1 步:将训练数据准备为 JSONL 文件
# 每个示例都是包含预期输出的对话
training_examples = [
    {
        "messages": [
            {"role": "system", "content": "你是一个简洁的技术助手。始终用一句话回答。"},
            {"role": "user", "content": "什么是向量数据库?"},
            {"role": "assistant", "content": "向量数据库以高维数值向量的形式存储和检索数据,从而实现快速的语义相似性搜索。"}
        ]
    },
    {
        "messages": [
            {"role": "system", "content": "你是一个简洁的技术助手。始终用一句话回答。"},
            {"role": "user", "content": "RAG 中的分块处理是什么?"},
            {"role": "assistant", "content": "分块处理是在将文档嵌入模型之前将其拆分为更小片段的过程,这样可以确保它们符合模型上下文限制并提高检索精度。"}
        ]
    },
    # 实际应用中建议至少准备 50-100 个示例
]

# 保存为 JSONL 文件
with open("training_data.jsonl", "w") as f:
    for example in training_examples:
        f.write(json.dumps(example) + "\n")

# 上传训练文件
with open("training_data.jsonl", "rb") as f:
    training_file = client.files.create(file=f, purpose="fine-tune")

# 创建微调任务
fine_tune_job = client.fine_tuning.jobs.create(
    training_file=training_file.id,
    model="gpt-4o-mini-2024-07-18"
)
print(fine_tune_job.id)

微调任务完成后,OpenAI 会返回一个唯一模型标识符,格式为 ft:base-model:your-org:your-suffix:unique-id 。这个模型现在会作为独立模型存在于你的 OpenAI 账户中,与基础模型 gpt-4o-mini 完全分离。

在打印输出时,我们会得到类似以下格式的微调模型标识符:

ft:gpt-4o-mini-2024-07-18:your-org:your-suffix:abc123

我们可以通过在 model 参数中传递这个标识符,像调用其他模型一样调用它:

code
# 任务完成后使用微调模型
response = client.chat.completions.create(
    model="ft:gpt-4o-mini-2024-07-18:your-org:your-suffix:abc123",
    messages=[
        {"role": "user", "content": "什么是提示缓存?"}
    ]
)
print(response.choices[0].message.content)

区别在于这个模型已经内化了我们训练它的行为:在我们的示例中,它现在会始终以简洁的一句话进行回应,而无需我们在每个系统提示中都明确要求。这就是微调真正擅长的领域:保持格式一致性、特定语气、遵循特定输出结构,或在特定任务类型上提升表现。本质上,这就是微调的作用。

注意微调对模型吸收特定信息的影响是有限的。与直觉可能认为的相反,即使在公司文档上对模型进行微调,也不会让模型“学会”这些信息并可靠地回答相关问题。虽然模型可能会从训练示例中记住一些具体事实,但这种记忆是脆弱且不可靠的。最可能的结果是模型会对训练示例中的主题产生幻觉,而不是准确回忆这些示例中的具体细节。因此,如果需要知识检索功能,RAG 是更合适的工具,而不是微调。

更具体地说,微调在以下方面表现良好:

  • 教导模型输出一致的格式、语气或风格
  • 提升特定狭窄任务类型的性能(例如始终生成有效的 JSON、始终以三个要点进行总结等)
  • 通过将指令整合到模型中,减少对冗长重复系统提示的需求
  • 使模型适应特定领域的语言或术语,从而理解并使用正确的词汇

然而,微调在以下方面表现欠佳:

  • 添加可被模型可靠回忆的准确事实知识
  • 保持模型与变化信息的同步
  • 提供可追溯、可引用的答案

那么何时使用哪种方法,或者两者都使用?

现在我们已经了解每种技术的实际作用,“RAG 与微调”的问题就变得容易回答了,因为在大多数情况下,这根本不是一个非此即彼的问题。

RAG 和微调在 AI 应用的不同层级上运作。RAG 在知识层级运作,意味着它控制模型可以访问的信息。另一方面,微调在行为层级运作,意味着它定义模型处理提供信息并生成响应的方式。这两个层级相互独立,这意味着根据你的目标,你可以选择使用 RAG、微调,或者两者结合使用。

因此,这里有一个实用的决策框架来决定使用哪种方法:

在实际生产系统中,同时使用 RAG 和微调的场景是最常见的。最简单的方法是:用微调处理行为,用 RAG 处理知识。

例如,假设我们正在为一个软件产品构建客户支持助手,需要它:

  • 始终以与我们软件品牌一致的特定语气和格式进行回应
  • 对产品文档有准确且最新的知识

对于这样的任务,我们需要同时使用 RAG 和微调。具体来说,微调会通过让模型从理想客户支持响应示例中学习,教导它正确的语气、适当的细节程度和正确的输出格式,从而满足第一个需求。第二个需求则由 RAG 来实现:在推理阶段,从产品文档中检索并注入最相关的信息到提示中,使模型能够基于文档提供可靠答案。

因此,在实践中,我们可以通过像调用其他模型一样调用微调后的模型,同时将检索到的上下文注入系统提示中(正如在标准 RAG 流程中所做的那样),来同时结合使用微调和 RAG。

code
# 将微调模型与RAG结合使用
response = client.chat.completions.create(
    model="ft:gpt-4o-mini-2024-07-18:your-org:support-style:abc123",  # 为语气/格式进行微调
    messages=[
        {
            "role": "system",
            "content": f"你是pialgorithms的客服助手。"
                       f"仅使用以下文档进行回答:\n\n{retrieved_context}"  # RAG上下文
        },
        {
            "role": "user",
            "content": user_question
        }
    ]
)

微调让模型掌握如何恰当回应,而RAG告诉模型该说什么内容。因此,这不是"微调与RAG谁更优"的问题,而是两者相辅相成、各司其职的关系。

我的思考

我认为RAG与微调之争最有趣的地方在于,人们经常将其框架为"哪种技术更好"的讨论,而实际上更有价值的问题是:你真正要解决的是什么问题?

RAG和微调分别应对基础LLM的不同失效模式。当基础模型因知识缺失而失效时,这是知识层面的问题,RAG能解决这个痛点。当基础模型因行为不一致或输出格式错误而失效时,这是行为层面的问题,微调能解决这个痛点。如果模型同时存在这两种问题,你确实需要两者结合使用。

✨ 感谢阅读!✨

如果你读到这里,可能会发现pialgorithms很有用:这是我们正在构建的平台,帮助团队在一个安全的地方管理组织知识。

喜欢这篇文章?来我的💌 Substack和💼 LinkedIn关注我

所有图片均由作者创作,除非另有说明。

作者信息

查看Maria Mouschoutzi的所有文章

人工智能

,

深度解析

微调

Python

Rag

分享本文

  • 在Facebook上分享
  • 在LinkedIn上分享
  • 在X上分享

Towards Data Science是社区出版物。提交你的见解以触达全球受众,并通过TDS作者支付计划获得收益。

将href更新为你的实际投稿链接

为TDS写作

✦ 结束CTA ✦

code