{T}

RAG 检索增强生成

RAG(Retrieval-Augmented Generation)通过在大模型推理前检索相关知识片段,将外部知识注入上下文,从而解决模型知识截止、幻觉和领域知识不足的问题。核心流程为:问题改写 → 向量检索 → 上下文注入 → 增强生成。

核心原理

为什么需要 RAG

问题纯 LLM 表现RAG 增强后
知识截止无法回答训练数据之后的问题检索最新文档
幻觉编造不存在的事实基于真实文档生成
领域知识对私有数据一无所知检索企业知识库
可追溯性无法标注信息来源可引用原始文档

RAG 完整流程

图表渲染中…

向量检索基础

Embedding 原理

Embedding 将文本映射为高维向量空间中的点,语义相近的文本在向量空间中距离更近:

typescript
// 调用 Embedding API
async function getEmbedding(text: string): Promise<number[]> {
  const response = await fetch(`${EMBEDDING_ENDPOINT}/embeddings`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      model: 'text-embedding-3-small',
      input: text,
    }),
  });

  const data = await response.json();
  return data.data[0].embedding; // 1536维向量
}

相似度计算

算法公式适用场景
余弦相似度(\cos(\theta) = \frac{A \cdot B}{|A| |B|})文本语义匹配(最常用)
欧氏距离(\sqrt{\sum(a_i - b_i)^2})绝对距离度量
点积(A \cdot B = \sum a_i b_i)已归一化向量

主流向量数据库

数据库特点适用场景
Pinecone全托管、高性能生产环境、快速上线
Milvus开源、分布式大规模私有化部署
Chroma轻量、嵌入式原型开发、本地测试
Weaviate混合搜索(向量+关键词)需要精确匹配+语义
pgvectorPostgreSQL 扩展已有 PG 基础设施

知识库构建

文档处理流水线

图表渲染中…

分块策略

策略说明适用场景
固定大小按字符数/token 数切割通用文档
段落分割按自然段落边界切割结构化文章
语义分割按主题变化点切割长篇叙述
递归分割先按大结构再递归细分代码/技术文档
重叠窗口相邻块保留 10-20% 重叠避免上下文断裂
typescript
// 递归分块示例
function splitDocument(
  text: string,
  options: {
    chunkSize: number;      // 目标块大小
    chunkOverlap: number;   // 重叠大小
    separators: string[];   // 分隔符优先级
  }
): string[] {
  const { chunkSize, chunkOverlap, separators } = options;
  const [sep, ...restSeps] = separators;

  if (!sep || text.length <= chunkSize) return [text];

  const parts = text.split(sep);
  const chunks: string[] = [];
  let current = '';

  for (const part of parts) {
    if ((current + sep + part).length > chunkSize && current) {
      chunks.push(current.trim());
      // 保留重叠
      const overlapText = current.slice(-chunkOverlap);
      current = overlapText + sep + part;
    } else {
      current = current ? current + sep + part : part;
    }
  }
  if (current.trim()) chunks.push(current.trim());

  // 对过长的块递归使用下一级分隔符
  return chunks.flatMap((chunk) =>
    chunk.length > chunkSize
      ? splitDocument(chunk, { ...options, separators: restSeps })
      : [chunk]
  );
}

// 使用
const chunks = splitDocument(document, {
  chunkSize: 500,
  chunkOverlap: 50,
  separators: ['\n## ', '\n### ', '\n\n', '\n', '。', ' '],
});

问题改写策略

为什么需要问题改写

用户的原始问题可能:

  • 表述模糊("那个东西怎么用")
  • 包含指代("它的价格是多少")
  • 过于口语化("帮我搞一下那个登录的 bug")

改写方法

typescript
const rewritePrompt = `
你是一个查询优化器。根据对话历史和用户当前问题,生成适合知识库检索的查询。

规则:
1. 将指代词替换为具体实体
2. 补充上下文中的关键信息
3. 生成 2-3 个不同角度的检索 query
4. 保持简洁,每个 query 不超过 20 字

对话历史:
${history}

用户问题:${question}

输出 JSON:
{
  "rewritten_queries": ["query1", "query2", "query3"],
  "intent": "用户真实意图"
}
`;

多路检索融合

图表渲染中…

上下文注入与生成

Prompt 模板

typescript
function buildRAGPrompt(question: string, chunks: RetrievedChunk[]): string {
  const context = chunks
    .map((c, i) => `[${i + 1}] 来源: ${c.source}\n${c.content}`)
    .join('\n\n');

  return `
基于以下参考资料回答用户问题。

规则:
- 仅使用参考资料中的信息回答
- 如果资料不足以回答,明确说明
- 在回答中标注引用来源编号 [n]
- 保持回答简洁准确

参考资料:
${context}

用户问题:${question}
`;
}

检索质量评估

指标说明优化方向
召回率相关文档是否被检索到增加 Top-K、多路检索
精确率检索结果中相关的比例优化 Embedding 模型、Rerank
上下文利用率模型是否有效使用了检索内容优化注入格式、减少噪声
回答忠实度回答是否忠于检索内容强化"仅基于资料"指令

常见问题与陷阱

问题原因解决方案
检索不到相关内容Query 与文档表述差异大问题改写 + 同义词扩展
回答仍含幻觉模型未严格遵循上下文强化约束指令 + 降低 temperature
分块后语义断裂切割点不当使用语义分割 + 重叠窗口
检索延迟高向量库规模大使用 ANN 索引(HNSW/IVF)
多语言混合效果差Embedding 模型不支持使用多语言模型(如 BGE-M3)

参考资源