大模型优化技术实施指南

🎯 大模型优化技术实施指南

SFT 监督微调 | RLHF 强化学习 | RAG 检索增强生成


📋 目录

  1. 技术概览
  2. RAG 检索增强生成(最容易,推荐先做)
  3. SFT 监督微调(中等难度)
  4. RLHF 强化学习(最复杂)
  5. 综合应用方案

🎯 技术概览

三种技术对比

技术 难度 成本 效果 适用场景 实施时间
RAG ⭐⭐⭐⭐ 知识更新、企业文档 1-3天
SFT ⭐⭐⭐ ⭐⭐⭐⭐⭐ 特定任务、风格定制 1-2周
RLHF ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 对齐人类偏好 1-2月

技术关系图

原始大模型(Qwen2.5:7b)
    ↓
┌───────────────────────────────┐
│  第一阶段:RAG(立即可用)      │
│  - 添加外部知识库              │
│  - 不修改模型参数              │
│  - 成本低,见效快              │
└───────────────────────────────┘
    ↓
┌───────────────────────────────┐
│  第二阶段:SFT 监督微调        │
│  - 用领域数据训练              │
│  - 修改模型参数                │
│  - 提升特定能力                │
└───────────────────────────────┘
    ↓
┌───────────────────────────────┐
│  第三阶段:RLHF 强化学习       │
│  - 人类反馈优化                │
│  - 对齐价值观                  │
│  - 提升回答质量                │
└───────────────────────────────┘
    ↓
企业级定制模型

📚 RAG 检索增强生成

难度: ⭐
推荐指数: ⭐⭐⭐⭐⭐
实施时间: 1-3天
无需重新训练模型!

1.1 什么是 RAG?

RAG 不修改模型本身,而是在生成回答前先检索相关文档,然后将检索到的信息作为上下文提供给模型。

用户提问
    ↓
检索相关文档(向量相似度)
    ↓
构建增强 Prompt(问题 + 检索到的文档)
    ↓
大模型生成回答

1.2 RAG 架构(您的项目已部分实现)

// 您的项目中已有 RAG 基础
backend/src/langchain-version/chains/ragChain.js  // ✅ 已实现
backend/src/utils/vectorDB.js                     // ✅ 已实现

1.3 完整 RAG 实施方案

步骤 1:部署向量数据库

# 启动 Qdrant(已在 docker-compose.local.yml 中)
docker-compose -f docker-compose.local.yml up -d qdrant

# 验证
curl http://localhost:6333

步骤 2:准备 Embedding 模型

# 下载中文 Embedding 模型
ollama pull bge-m3

# 或使用更大的模型(更准确)
ollama pull bge-large-zh

步骤 3:文档处理与向量化

创建 backend/src/utils/rag-pipeline.js

/**
 * RAG 完整流程
 * 文档处理 → 向量化 → 存储 → 检索 → 生成
 */

import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import { QdrantClient } from '@qdrant/js-client-rest';
import axios from 'axios';

export class RAGPipeline {
  constructor(config = {}) {
    this.qdrantClient = new QdrantClient({
      url: config.qdrantUrl || 'http://localhost:6333',
    });
    this.collectionName = config.collectionName || 'documents';
    this.embeddingModel = config.embeddingModel || 'bge-m3';
    this.ollamaUrl = config.ollamaUrl || 'http://localhost:11434';
  }

  /**
   * 步骤 1:文档切片
   */
  async chunkDocument(text, metadata = {}) {
    const splitter = new RecursiveCharacterTextSplitter({
      chunkSize: 500,        // 每块 500 字符
      chunkOverlap: 100,     // 重叠 100 字符
      separators: ['\n\n', '\n', '。', '!', '?', ';', ',', ' ', ''],
    });

    const chunks = await splitter.createDocuments([text], [metadata]);
    
    console.log(`文档切分为 ${chunks.length} 个片段`);
    return chunks;
  }

  /**
   * 步骤 2:生成向量 Embedding
   */
  async generateEmbedding(text) {
    try {
      const response = await axios.post(
        `${this.ollamaUrl}/api/embeddings`,
        {
          model: this.embeddingModel,
          prompt: text,
        }
      );

      return response.data.embedding;
    } catch (error) {
      console.error('生成 Embedding 失败:', error.message);
      throw error;
    }
  }

  /**
   * 步骤 3:批量向量化
   */
  async batchEmbeddings(texts) {
    const embeddings = [];
    
    for (let i = 0; i < texts.length; i++) {
      console.log(`向量化进度: ${i + 1}/${texts.length}`);
      const embedding = await this.generateEmbedding(texts[i]);
      embeddings.push(embedding);
      
      // 避免请求过快
      await new Promise(resolve => setTimeout(resolve, 100));
    }
    
    return embeddings;
  }

  /**
   * 步骤 4:创建向量集合
   */
  async createCollection(vectorSize = 1024) {
    try {
      await this.qdrantClient.createCollection(this.collectionName, {
        vectors: {
          size: vectorSize,
          distance: 'Cosine',
        },
        optimizers_config: {
          default_segment_number: 2,
        },
        replication_factor: 1,
      });
      
      console.log(`✅ 集合 ${this.collectionName} 创建成功`);
    } catch (error) {
      if (error.message.includes('already exists')) {
        console.log(`⚠️  集合 ${this.collectionName} 已存在`);
      } else {
        throw error;
      }
    }
  }

  /**
   * 步骤 5:存储文档和向量
   */
  async storeDocuments(chunks) {
    // 确保集合存在
    await this.createCollection();

    // 提取文本
    const texts = chunks.map(chunk => chunk.pageContent);
    
    // 生成向量
    console.log('正在生成向量...');
    const embeddings = await this.batchEmbeddings(texts);

    // 准备存储的点
    const points = chunks.map((chunk, index) => ({
      id: Date.now() + index,
      vector: embeddings[index],
      payload: {
        text: chunk.pageContent,
        metadata: chunk.metadata,
        timestamp: new Date().toISOString(),
      },
    }));

    // 批量上传
    await this.qdrantClient.upsert(this.collectionName, {
      wait: true,
      points: points,
    });

    console.log(`✅ 已存储 ${points.length} 个文档片段`);
    return points.length;
  }

  /**
   * 步骤 6:检索相关文档
   */
  async search(query, topK = 5) {
    // 生成查询向量
    const queryEmbedding = await this.generateEmbedding(query);

    // 向量搜索
    const searchResult = await this.qdrantClient.search(this.collectionName, {
      vector: queryEmbedding,
      limit: topK,
      with_payload: true,
      with_vector: false,
    });

    return searchResult.map(result => ({
      text: result.payload.text,
      score: result.score,
      metadata: result.payload.metadata,
    }));
  }

  /**
   * 步骤 7:RAG 生成(检索 + 生成)
   */
  async generate(query, model = 'qwen2.5:7b') {
    // 1. 检索相关文档
    console.log('🔍 检索相关文档...');
    const documents = await this.search(query, 5);

    if (documents.length === 0) {
      console.log('⚠️  未找到相关文档,使用模型直接回答');
      return await this.directGenerate(query, model);
    }

    // 2. 构建增强 Prompt
    const context = documents
      .map((doc, index) => `[文档 ${index + 1}]\n${doc.text}`)
      .join('\n\n');

    const enhancedPrompt = `请基于以下参考文档回答问题。如果文档中没有相关信息,请说明。

参考文档:
${context}

问题:${query}

回答:`;

    // 3. 调用 LLM 生成
    console.log('💬 生成回答...');
    const response = await axios.post(
      `${this.ollamaUrl}/api/generate`,
      {
        model: model,
        prompt: enhancedPrompt,
        stream: false,
      }
    );

    return {
      answer: response.data.response,
      sources: documents,
      context: context,
    };
  }

  /**
   * 直接生成(无 RAG)
   */
  async directGenerate(query, model) {
    const response = await axios.post(
      `${this.ollamaUrl}/api/generate`,
      {
        model: model,
        prompt: query,
        stream: false,
      }
    );

    return {
      answer: response.data.response,
      sources: [],
      context: null,
    };
  }

  /**
   * 完整流程:添加文档到 RAG 系统
   */
  async addDocument(text, metadata = {}) {
    // 1. 切片
    const chunks = await this.chunkDocument(text, metadata);
    
    // 2. 向量化并存储
    const count = await this.storeDocuments(chunks);
    
    return {
      success: true,
      chunks: count,
      message: `成功添加 ${count} 个文档片段`,
    };
  }
}

// 导出便捷函数
export async function createRAGSystem(config = {}) {
  const rag = new RAGPipeline(config);
  await rag.createCollection();
  return rag;
}

步骤 4:使用示例

// scripts/test-rag.js
import { RAGPipeline } from '../backend/src/utils/rag-pipeline.js';

async function demo() {
  console.log('🚀 RAG 系统演示\n');

  // 1. 创建 RAG 实例
  const rag = new RAGPipeline({
    collectionName: 'company_docs',
  });

  // 2. 添加企业文档
  console.log('📄 添加企业文档...');
  await rag.addDocument(`
    公司年假政策:
    1. 工作满1年可享受5天年假
    2. 工作满3年可享受10天年假
    3. 工作满5年可享受15天年假
    年假必须在当年使用完毕,不可跨年。
  `, { type: 'policy', category: 'hr' });

  await rag.addDocument(`
    公司产品价格表:
    - 基础版:¥99/月
    - 专业版:¥299/月
    - 企业版:¥999/月
    所有版本均支持7天免费试用。
  `, { type: 'pricing', category: 'product' });

  // 3. 测试查询
  console.log('\n💬 测试 RAG 查询...\n');

  const result1 = await rag.generate('工作3年有几天年假?');
  console.log('问题:工作3年有几天年假?');
  console.log('回答:', result1.answer);
  console.log('来源:', result1.sources.length, '个文档片段\n');

  const result2 = await rag.generate('专业版多少钱?');
  console.log('问题:专业版多少钱?');
  console.log('回答:', result2.answer);
  console.log('来源:', result2.sources.length, '个文档片段\n');
}

demo();

步骤 5:集成到 API

// backend/src/routes/rag-enhanced.js
import express from 'express';
import { RAGPipeline } from '../utils/rag-pipeline.js';

const router = express.Router();

// 创建 RAG 实例(单例)
const rag = new RAGPipeline({
  collectionName: 'knowledge_base',
});

/**
 * POST /api/rag/query
 * RAG 查询
 */
router.post('/query', async (req, res) => {
  try {
    const { query } = req.body;
    
    if (!query) {
      return res.status(400).json({ error: '请提供查询内容' });
    }

    const result = await rag.generate(query);

    res.json({
      success: true,
      answer: result.answer,
      sources: result.sources,
    });
  } catch (error) {
    console.error('RAG 查询错误:', error);
    res.status(500).json({ error: '查询失败' });
  }
});

/**
 * POST /api/rag/add-document
 * 添加文档
 */
router.post('/add-document', async (req, res) => {
  try {
    const { text, metadata = {} } = req.body;
    
    if (!text) {
      return res.status(400).json({ error: '请提供文档内容' });
    }

    const result = await rag.addDocument(text, metadata);

    res.json(result);
  } catch (error) {
    console.error('添加文档错误:', error);
    res.status(500).json({ error: '添加文档失败' });
  }
});

export default router;

1.4 RAG 优化技巧

优化 1:混合检索(向量 + 关键词)

async searchHybrid(query, topK = 5) {
  // 1. 向量检索
  const vectorResults = await this.search(query, topK);
  
  // 2. 关键词检索
  const keywordResults = await this.keywordSearch(query, topK);
  
  // 3. 结果合并和重排序
  const combined = this.mergeResults(vectorResults, keywordResults);
  
  return combined.slice(0, topK);
}

优化 2:重排序(Reranking)

async rerank(query, documents) {
  // 使用更强的模型对检索结果重新排序
  const scores = [];
  
  for (const doc of documents) {
    const prompt = `
评分任务:评估文档与问题的相关性(0-10分)

问题:${query}
文档:${doc.text}

相关性评分(只输出数字):`;

    const response = await callLLM(prompt);
    scores.push(parseFloat(response) || 0);
  }
  
  // 按分数排序
  return documents
    .map((doc, i) => ({ ...doc, rerankScore: scores[i] }))
    .sort((a, b) => b.rerankScore - a.rerankScore);
}

优化 3:自适应检索

async adaptiveRAG(query) {
  // 1. 判断是否需要检索
  const needRetrieval = await this.needsRetrieval(query);
  
  if (!needRetrieval) {
    return await this.directGenerate(query);
  }
  
  // 2. 动态调整检索数量
  const complexity = this.assessComplexity(query);
  const topK = complexity === 'high' ? 10 : 5;
  
  // 3. RAG 生成
  return await this.generate(query, topK);
}

🎓 SFT 监督微调

难度: ⭐⭐⭐
推荐指数: ⭐⭐⭐⭐⭐
实施时间: 1-2周
需要准备训练数据!

2.1 什么是 SFT?

SFT(Supervised Fine-Tuning)是用特定领域的标注数据重新训练模型,使其适应特定任务。

预训练模型(通用能力)
    ↓
+ 领域数据(问答对)
    ↓
微调训练
    ↓
定制模型(领域专家)

2.2 SFT 适用场景

场景 是否需要 SFT 建议
企业客服 准备常见问答对
医疗咨询 使用专业数据
法律顾问 法律条文 + 案例
代码生成 ⚠️ 考虑使用专用模型
通用对话 无需微调,RAG 即可

2.3 数据准备

数据格式(Alpaca 格式)

[
  {
    "instruction": "什么是机器学习?",
    "input": "",
    "output": "机器学习是人工智能的一个分支,它使计算机能够在没有明确编程的情况下从数据中学习。主要包括监督学习、无监督学习和强化学习三种类型..."
  },
  {
    "instruction": "解释{concept}的概念",
    "input": "神经网络",
    "output": "神经网络是一种模仿人脑神经元工作方式的计算模型..."
  }
]

数据收集方式

  1. 现有数据整理

    • 客服聊天记录
    • 专业文档
    • FAQ 数据库
  2. 人工标注

    • 雇佣领域专家
    • 使用标注工具
    • 质量审核
  3. 模型生成(数据增强)

    # 使用强大的模型生成训练数据
    prompt = f"生成10个关于{topic}的问答对"
    

2.4 使用 Ollama + Unsloth 微调

方案 A:Unsloth(推荐,快速)

# 安装 Unsloth
pip install "unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git"
pip install --no-deps xformers trl peft accelerate bitsandbytes

# 微调脚本

创建 scripts/finetune-sft.py

"""
SFT 监督微调脚本
使用 Unsloth 加速微调
"""

from unsloth import FastLanguageModel
import torch
from datasets import load_dataset
from trl import SFTTrainer
from transformers import TrainingArguments

# 1. 加载模型
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/qwen2-7b-bnb-4bit",  # 4-bit 量化模型
    max_seq_length = 2048,
    dtype = None,
    load_in_4bit = True,
)

# 2. 准备 LoRA 微调配置
model = FastLanguageModel.get_peft_model(
    model,
    r = 16,                    # LoRA rank
    target_modules = [         # 要微调的层
        "q_proj", "k_proj", "v_proj",
        "o_proj", "gate_proj", "up_proj", "down_proj"
    ],
    lora_alpha = 16,
    lora_dropout = 0,
    bias = "none",
    use_gradient_checkpointing = True,
    random_state = 3407,
)

# 3. 加载训练数据
dataset = load_dataset("json", data_files="training_data.json", split="train")

# 4. 定义 Prompt 模板
alpaca_prompt = """Below is an instruction that describes a task. Write a response that appropriately completes the request.

### Instruction:
{}

### Input:
{}

### Response:
{}"""

def formatting_prompts_func(examples):
    instructions = examples["instruction"]
    inputs       = examples["input"]
    outputs      = examples["output"]
    texts = []
    for instruction, input, output in zip(instructions, inputs, outputs):
        text = alpaca_prompt.format(instruction, input, output) + tokenizer.eos_token
        texts.append(text)
    return { "text" : texts, }

# 应用格式化
dataset = dataset.map(
    formatting_prompts_func,
    batched = True,
)

# 5. 配置训练参数
trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = dataset,
    dataset_text_field = "text",
    max_seq_length = 2048,
    dataset_num_proc = 2,
    packing = False,
    args = TrainingArguments(
        per_device_train_batch_size = 2,
        gradient_accumulation_steps = 4,
        warmup_steps = 5,
        max_steps = 60,              # 调整为实际需要的步数
        learning_rate = 2e-4,
        fp16 = not torch.cuda.is_bf16_supported(),
        bf16 = torch.cuda.is_bf16_supported(),
        logging_steps = 1,
        optim = "adamw_8bit",
        weight_decay = 0.01,
        lr_scheduler_type = "linear",
        seed = 3407,
        output_dir = "outputs",
    ),
)

# 6. 开始训练
trainer_stats = trainer.train()

# 7. 保存微调后的模型
model.save_pretrained("qwen2-7b-finetuned")
tokenizer.save_pretrained("qwen2-7b-finetuned")

# 8. 导出为 Ollama 格式(可选)
# model.save_pretrained_gguf("qwen2-7b-finetuned-gguf", tokenizer)

print("✅ 微调完成!")

运行微调

# 准备训练数据
# 创建 training_data.json

# 运行微调(需要 GPU)
python scripts/finetune-sft.py

# 预计时间:
# - 1000 样本,RTX 3090:~1小时
# - 10000 样本,RTX 3090:~10小时

导入 Ollama

# 方法 1:创建 Modelfile
cat > Modelfile << 'EOF'
FROM ./qwen2-7b-finetuned

TEMPLATE """{{ .System }}
{{ .Prompt }}"""

PARAMETER stop "<|endoftext|>"
EOF

# 导入模型
ollama create qwen2-finetuned -f Modelfile

# 测试
ollama run qwen2-finetuned "测试微调效果"

2.5 SFT 最佳实践

1. 数据质量 > 数据数量

❌ 10000 条低质量数据
✅ 1000 条高质量数据

2. 数据多样性

{
  "style_diversity": ["正式", "口语", "技术"],
  "length_diversity": ["简短", "中等", "详细"],
  "difficulty_diversity": ["基础", "中级", "高级"]
}

3. 过拟合检测

# 每 100 步验证一次
if step % 100 == 0:
    val_loss = evaluate(model, val_dataset)
    if val_loss > best_val_loss:
        print("⚠️  过拟合,停止训练")
        break

🤖 RLHF 强化学习

难度: ⭐⭐⭐⭐⭐
推荐指数: ⭐⭐⭐
实施时间: 1-2月
需要大量人工反馈!

3.1 什么是 RLHF?

RLHF(Reinforcement Learning from Human Feedback)通过人类反馈来优化模型的输出,使其更符合人类偏好。

SFT 微调模型
    ↓
生成多个候选回答
    ↓
人类排序(哪个回答更好?)
    ↓
训练 Reward Model(奖励模型)
    ↓
PPO 强化学习优化
    ↓
对齐人类偏好的模型

3.2 RLHF 三阶段

阶段 1:SFT 基础模型

# 首先需要一个 SFT 微调后的模型
base_model = load_model("qwen2-7b-sft")

阶段 2:训练 Reward Model

"""
奖励模型训练
学习人类偏好
"""

from transformers import AutoModelForSequenceClassification

# 1. 准备对比数据
comparison_data = [
    {
        "prompt": "什么是AI?",
        "chosen": "AI是人工智能的缩写,指让机器具有智能行为的技术...",  # 👍 更好
        "rejected": "AI就是电脑变聪明"  # 👎 较差
    },
    # ... 更多数据
]

# 2. 加载模型
reward_model = AutoModelForSequenceClassification.from_pretrained(
    "qwen2-7b-sft",
    num_labels=1  # 输出奖励分数
)

# 3. 训练 Reward Model
for batch in comparison_data:
    chosen_score = reward_model(batch["chosen"])
    rejected_score = reward_model(batch["rejected"])
    
    # Loss:让 chosen 得分更高
    loss = -torch.log(torch.sigmoid(chosen_score - rejected_score))
    loss.backward()

阶段 3:PPO 强化学习

"""
使用 PPO 算法优化模型
"""

from trl import PPOTrainer, PPOConfig

# 1. 配置
ppo_config = PPOConfig(
    model_name="qwen2-7b-sft",
    learning_rate=1e-5,
    batch_size=128,
)

# 2. 创建 Trainer
ppo_trainer = PPOTrainer(
    config=ppo_config,
    model=base_model,
    ref_model=reference_model,  # 参考模型(防止偏离太远)
    tokenizer=tokenizer,
    reward_model=reward_model,
)

# 3. 训练循环
for epoch in range(epochs):
    for batch in dataset:
        # 生成回答
        query_tensors = batch["input_ids"]
        response_tensors = ppo_trainer.generate(query_tensors)
        
        # 计算奖励
        rewards = reward_model(response_tensors)
        
        # PPO 更新
        stats = ppo_trainer.step(query_tensors, response_tensors, rewards)

3.3 简化版 RLHF(Direct Preference Optimization - DPO)

DPO 是 RLHF 的简化版本,无需训练 Reward Model。

"""
DPO:直接偏好优化
更简单,效果接近 RLHF
"""

from trl import DPOTrainer

trainer = DPOTrainer(
    model,
    ref_model,
    beta=0.1,  # KL 散度系数
    train_dataset=preference_dataset,
    tokenizer=tokenizer,
)

trainer.train()

3.4 实施建议

对于大多数企业应用,不推荐直接使用 RLHF,原因:

  1. 成本高 - 需要大量人工标注
  2. 复杂度高 - 训练稳定性差
  3. 效果增量有限 - SFT + RAG 已足够

推荐替代方案

SFT(特定任务) + RAG(知识更新) + Prompt Engineering(行为控制)

🎯 综合应用方案

方案 1:RAG + Prompt(最简单,推荐)

// 适合 90% 的场景
async function enhancedChat(query) {
  // 1. RAG 检索知识
  const knowledge = await ragSearch(query);
  
  // 2. 精心设计的 Prompt
  const prompt = `
你是一个专业的客服助手。请基于以下知识库回答用户问题。

知识库:
${knowledge}

回答要求:
1. 准确、专业
2. 简洁明了
3. 如不确定,说明需要人工处理

用户问题:${query}

你的回答:`;

  // 3. 调用模型
  return await callLLM(prompt);
}

方案 2:RAG + SFT(推荐企业)

1. RAG 处理知识更新
   └─ 企业文档、政策、产品信息

2. SFT 微调模型风格
   └─ 公司语气、专业术语、回答模板

3. 组合使用
   └─ 知识来自 RAG,风格来自 SFT

方案 3:完整流程(大型企业)

1. RAG:知识检索
   ↓
2. SFT 模型:理解和生成
   ↓
3. 后处理:
   - 敏感词过滤
   - 格式优化
   - 事实核查
   ↓
4. 人工审核(可选)
   ↓
5. 用户反馈收集
   ↓
6. 定期 SFT 更新

📊 技术选择决策树

需要提升大模型能力?
    ↓
【问题 1】是否有企业文档/知识库?
    是 → 使用 RAG ✅
    否 → 继续
    ↓
【问题 2】是否需要特定的回答风格/格式?
    是 → 使用 SFT ✅
    否 → 使用 Prompt Engineering
    ↓
【问题 3】是否需要对齐复杂的人类偏好?
    是 → 使用 RLHF(谨慎)
    否 → SFT + RAG 足够

🛠️ 实施路线图

第 1 周:RAG(快速见效)

  • ✅ 部署 Qdrant
  • ✅ 准备企业文档
  • ✅ 实现 RAG 流程
  • ✅ 测试和优化

第 2-3 周:数据准备

  • ✅ 收集标注数据
  • ✅ 数据清洗和格式化
  • ✅ 质量审核
  • ✅ 划分训练/验证集

第 4-5 周:SFT 微调

  • ✅ 环境配置
  • ✅ 模型微调
  • ✅ 效果评估
  • ✅ 导入 Ollama

第 6-8 周:集成和优化

  • ✅ RAG + SFT 集成
  • ✅ API 开发
  • ✅ 性能优化
  • ✅ 用户测试

📈 效果评估

评估指标

指标 RAG SFT RLHF
准确性 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
实时性 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐
可解释性 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
成本 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐

测试方法

# 评估脚本
test_cases = [
    {"query": "...", "expected": "...", "type": "factual"},
    {"query": "...", "expected": "...", "type": "style"},
]

for case in test_cases:
    response = model.generate(case["query"])
    score = evaluate(response, case["expected"])
    print(f"Case: {case['type']}, Score: {score}")

💡 最佳实践

1. 从简单开始

第 1 步:RAG(1周)
第 2 步:Prompt Engineering(1周)
第 3 步:如果还不够,考虑 SFT(2周)
第 4 步:几乎不需要 RLHF

2. 持续迭代

收集用户反馈
    ↓
分析问题类型
    ↓
RAG 可以解决?→ 添加文档
SFT 可以解决?→ 添加训练数据
Prompt 可以解决?→ 优化 Prompt

3. 监控和维护

// 记录每次查询
logger.info({
  query: query,
  method: 'RAG' | 'SFT' | 'Direct',
  satisfaction: userFeedback,
  latency: responseTime,
});

// 定期分析
// 1. 哪些问题 RAG 解决不了?→ 需要 SFT
// 2. 哪些文档经常被检索?→ 重点优化
// 3. 用户满意度趋势?→ 整体效果

🎊 总结

技术优先级

  1. RAG - 立即实施,成本低效果好
  2. Prompt Engineering - 配合 RAG 使用
  3. SFT - 有明确需求时再做
  4. RLHF - 大型企业长期项目

资源需求

技术 人力 算力 数据 时间
RAG 1人 CPU 文档 1周
SFT 2-3人 GPU 标注 1月
RLHF 5+人 GPU 集群 大量反馈 3月+

预期效果

原始模型:60分
+ RAG:75分(+15分)
+ Prompt:80分(+5分)
+ SFT:85分(+5分)
+ RLHF:88分(+3分)

更新时间:2026-01-26
作者:马年行大运

🎯 从 RAG 开始,循序渐进!

posted @ 2026-01-26 16:09  XiaoZhengTou  阅读(6)  评论(0)    收藏  举报