Solo Unicorn Club logoSolo Unicorn
2,700

RAG vs Fine-tuning vs Prompt Engineering — 决策框架

RAGFine-tuningPrompt EngineeringLLM决策框架成本分析
RAG vs Fine-tuning vs Prompt Engineering — 决策框架

RAG vs Fine-tuning vs Prompt Engineering — 决策框架

开场

我做过一个 A/B 测试:同一个客服场景,分别用纯 Prompt Engineering、RAG 和 Fine-tuning 三种方案跑了两周,各处理 1,000 条真实工单。结果——Prompt Engineering 方案的客户满意度 82%,RAG 方案 89%,Fine-tuning 方案 91%。但看成本:Prompt Engineering 花了 $38,RAG 花了 $165,Fine-tuning 花了 $2,400(含训练费用)。满意度差了 9 个百分点,成本差了 63 倍。这不是谁好谁差的问题,而是什么时候用什么。

问题背景

"我有私有数据想让 LLM 用上,该怎么做?"——这是我被问得最多的问题。大部分人的第一反应是 Fine-tuning 或者 RAG,但多数情况下,几个 few-shot examples 放在 prompt 里就已经解决了 80% 的问题。

三种方案的本质区别:

  • Prompt Engineering:不改模型,只改输入。用 system prompt、few-shot examples 和指令来引导模型行为
  • RAG(Retrieval-Augmented Generation):不改模型,改上下文。运行时从外部数据源检索相关信息塞进 prompt
  • Fine-tuning:改模型本身。用你的数据训练模型的权重,让它内化特定的行为模式

核心框架:两维决策矩阵

把你的需求放到两个维度上:

X 轴:知识类型——你要模型知道的东西是什么?

  • 静态知识(产品手册、公司政策、FAQ)→ 可以放进 prompt 或通过 RAG 检索
  • 动态知识(实时价格、库存、新闻)→ 必须用 RAG,因为模型训练数据是过时的

Y 轴:行为模式——你要模型怎么做?

  • 通用行为(总结、分类、翻译)→ Prompt Engineering 够了
  • 专有行为(特定语气、专业术语、行业规范)→ 可能需要 Fine-tuning
            通用行为                    专有行为
         ┌──────────────┬──────────────┐
  静态   │  Prompt      │  Fine-tuning │
  知识   │  Engineering │  或高质量    │
         │  (最便宜)     │  Prompt      │
         ├──────────────┼──────────────┤
  动态   │  RAG         │  RAG +       │
  知识   │  (必选)       │  Fine-tuning │
         │              │  (最贵但最强) │
         └──────────────┴──────────────┘

方案一:Prompt Engineering

什么时候用:知识量小(< 8K token 能放进 prompt),行为模式可以用指令描述清楚。

from openai import OpenAI
client = OpenAI()

# 方案一:Few-shot Prompt Engineering
# 把知识和行为模式都编码在 prompt 里
SYSTEM_PROMPT = """你是 ArkTop AI 的客服。遵循以下规则:

## 退款政策
- 7 天内无条件退款
- 7-30 天需审核
- 30 天后不退款
- 年度套餐按比例退款

## 回复风格
- 简洁专业,不用敬语堆砌
- 给出明确答案,不说"请稍等"
- 涉及退款金额时必须精确到分

## 示例
用户: 我买了三天想退款
回复: 可以退。7 天内支持无条件退款,我这就帮你处理。退款将在 3 个工作日内到账。

用户: 我的年度套餐用了两个月想退
回复: 年度套餐按剩余月份比例退款。你已用 2 个月,退款金额为年费的 10/12。确认处理吗?"""

def prompt_engineering_approach(user_message: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4.1",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
        temperature=0.3,
    )
    return response.choices[0].message.content

成本:纯 API 调用费。system prompt 约 500 token,假设用 GPT-4.1,每次请求的 prompt 成本约 $0.001。

优点:零基础设施成本,迭代最快(改 prompt 就行),5 分钟上线 缺点:知识容量受上下文窗口限制,prompt 超过 3000 token 后指令遵循能力下降

方案二:RAG

什么时候用:知识量大(几百到几百万条文档),知识会定期更新,需要引用来源。

from openai import OpenAI
from qdrant_client import QdrantClient

openai_client = OpenAI()
qdrant = QdrantClient(url="http://localhost:6333")

async def rag_approach(user_question: str) -> str:
    """RAG:检索相关文档 → 喂给 LLM 生成回答"""

    # Step 1: 把用户问题变成 embedding
    embedding = openai_client.embeddings.create(
        model="text-embedding-3-small",  # $0.02/1M tokens
        input=user_question
    ).data[0].embedding

    # Step 2: 从向量库检索最相关的文档(top 5)
    results = qdrant.query_points(
        collection_name="product_docs",
        query=embedding,
        limit=5,
        score_threshold=0.75  # 相似度阈值,低于此值不返回
    )

    # Step 3: 组装上下文
    context_docs = "\n---\n".join([
        f"[来源: {r.payload['source']}]\n{r.payload['content']}"
        for r in results.points
    ])

    # Step 4: 带上下文生成回答
    response = openai_client.chat.completions.create(
        model="gpt-4.1",
        messages=[
            {"role": "system", "content": """基于提供的参考文档回答问题。
规则:
1. 只基于文档内容回答,不要编造
2. 如果文档里没有答案,明确告知
3. 引用来源文档"""},
            {"role": "user", "content": f"参考文档:\n{context_docs}\n\n问题:{user_question}"}
        ],
        temperature=0.2,  # RAG 用低温度减少幻觉
    )
    return response.choices[0].message.content

成本拆解(月均 10,000 次查询):

组件 月成本
Embedding 生成 $2.00
Vector DB (Qdrant Cloud) $45.00
LLM 生成 (GPT-4.1) $120.00
文档处理和更新 $15.00
合计 $182.00

优点:知识量几乎无上限,更新知识不需要重新训练,可以引用来源 缺点:检索质量直接影响生成质量(garbage retrieval = garbage generation),需要维护 vector store,延迟增加 200-500ms

方案三:Fine-tuning

什么时候用:需要模型内化特定的行为模式(语气、格式、推理方式),且这些模式用 prompt 描述不清楚。

from openai import OpenAI
client = OpenAI()

# Step 1: 准备训练数据(JSONL 格式)
# 至少需要 50-100 条高质量样本
training_data = [
    {
        "messages": [
            {"role": "system", "content": "你是 ArkTop AI 客服。"},
            {"role": "user", "content": "我的积分怎么没到账?"},
            {"role": "assistant", "content": "查了一下,你的积分已经在 3 月 2 日到账了,当前余额 2,450 分。如果和你预期的不一致,告诉我你觉得应该是多少,我帮你核实。"}
        ]
    },
    # ... 至少 50 条类似的样本
]

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

# Step 3: 启动 Fine-tuning 任务
job = client.fine_tuning.jobs.create(
    training_file=file.id,
    model="gpt-4.1-mini",  # 基础模型选性价比高的
    hyperparameters={
        "n_epochs": 3,          # 训练轮数
        "learning_rate_multiplier": 1.8,
    }
)
# GPT-4.1-mini fine-tuning: $3.00/1M training tokens
# 100 条样本约 50K tokens → 训练成本约 $0.15
# 但数据准备的人力成本远高于此

# Step 4: 使用 fine-tuned 模型
def finetuned_approach(user_message: str) -> str:
    response = client.chat.completions.create(
        model=f"ft:gpt-4.1-mini:arktop-ai:customer-service:xxx",
        messages=[
            {"role": "system", "content": "你是 ArkTop AI 客服。"},
            {"role": "user", "content": user_message},
        ],
        temperature=0.3,
    )
    return response.choices[0].message.content

成本拆解

项目 成本
数据准备(人力,100 条高质量样本) $500-$2,000
GPT-4.1-mini Fine-tuning(50K tokens x 3 epochs) $0.45
推理费用(和基础模型相同) 和方案一相同
每次知识更新重新训练 $500+ (含数据准备)

优点:推理速度快(不需要检索步骤),模型行为更一致,system prompt 可以很短(省 token) 缺点:数据准备成本高,每次知识更新需要重新训练,可能出现灾难性遗忘

实战经验

决策树

实际项目中我用这个决策树:

1. 知识量能放进 8K token 的 prompt 吗?
   ├── 能 → Prompt Engineering(先试这个)
   │      效果够好吗?
   │      ├── 够 → 用这个,结束
   │      └── 不够 → 下一步
   │
   └── 不能 → 下一步

2. 知识需要频繁更新吗?(每周以上)
   ├── 是 → RAG(必选)
   │      行为模式也需要定制吗?
   │      ├── 是 → RAG + Fine-tuning
   │      └── 否 → 纯 RAG
   │
   └── 否 → 下一步

3. 你有 100+ 条高质量训练样本吗?
   ├── 有 → Fine-tuning
   └── 没有 → 先用 Prompt Engineering,
              同时积累数据,够了再 Fine-tune

三种方案的性能对比(真实数据)

我在客服场景跑的对比测试,1,000 条工单/方案:

指标 Prompt Engineering RAG Fine-tuning
准确率 78% 89% 91%
客户满意度 82% 89% 91%
平均延迟 1.2s 2.1s 1.0s
两周总成本 $38 $165 $2,400
上线时间 1 天 1 周 3 周
知识更新速度 即时 分钟级 天级

混合方案:实际生产的最佳实践

2026 年大多数生产系统用的是混合方案:

async def hybrid_approach(user_question: str) -> str:
    """混合方案:Prompt Engineering + RAG,必要时 Fine-tuning"""

    # 层级 1:先检查是否命中 FAQ(纯 prompt 就能答)
    faq_match = check_faq_cache(user_question)
    if faq_match and faq_match.confidence > 0.9:
        return faq_match.answer  # 走缓存,零 API 成本

    # 层级 2:RAG 检索
    docs = await retrieve_relevant_docs(user_question)

    # 层级 3:用 fine-tuned 模型生成(如果有的话)
    model = "ft:gpt-4.1-mini:arktop:cs:xxx" if FINETUNED_AVAILABLE else "gpt-4.1"
    response = await generate_response(model, user_question, docs)
    return response

踩过的坑

坑 1:RAG 的检索质量。用了 RAG 后发现效果不好,以为是 LLM 的问题,花了两周调 prompt。后来发现根本原因是 embedding 检索把不相关的文档塞进了上下文。解决方案:把 similarity threshold 从 0.6 调到 0.78,宁缺毋滥。

坑 2:Fine-tuning 的数据质量。第一次 Fine-tuning 用了 200 条自动生成的训练数据,模型学到了"AI 味"的回复风格。后来换成 100 条人工精编的数据,效果好了一个档次。Fine-tuning 的质量取决于数据质量,而不是数据量。

坑 3:过早 Fine-tuning。一个项目刚上线就花了三周做 Fine-tuning,上线后发现业务需求变了,训练数据白准备了。教训:先用 Prompt Engineering 跑三个月,积累真实用户数据,再考虑 Fine-tuning。

总结

三条 takeaway:

  1. 80% 的需求用 Prompt Engineering 就够了——先试最简单的方案,效果不够再加码。从 $38 跳到 $2,400 之前,确认这个质量差距值这个价
  2. RAG 和 Fine-tuning 解决的是不同的问题——RAG 解决"知道什么"(knowledge),Fine-tuning 解决"怎么做"(behavior)。搞清楚你的需求是哪一种
  3. 混合方案是生产环境的标配——FAQ 缓存 + RAG 检索 + Fine-tuned 模型,分层处理。简单问题走缓存(零成本),复杂问题走 RAG(中等成本),核心场景走 Fine-tuning(高质量)

下次有人问你"该用 RAG 还是 Fine-tuning",先反问:"你有多少知识要加进去?这些知识多久更新一次?你有高质量的训练数据吗?"答案自然就出来了。

你在生产中用的是哪种方案?混合比例怎么分的?来一人独角兽俱乐部交流。