1. RAG 的动机

LLM 的核心局限

知识截止 (Knowledge Cutoff)

预训练数据有明确的时间边界。GPT-4 的知识截止于 2023 年 4 月,对于最新信息、实时股价、最近发表的论文等无法准确回答。这限制了模型在时效性要求高的领域的应用。

幻觉问题 (Hallucination)

模型会生成看似合理但完全虚构的信息。因为模型本质是一个统计文本预测器,没有真实的知识库或事实检查机制。在知识库外的话题上,模型倾向于编造答案而不是表示不知道。

无法访问私有数据 (No Private Data Access)

企业的内部文档、数据库、CRM 系统、专有知识库等都不在模型的训练数据中。模型无法直接查询或检索这些私有信息,限制了在企业应用中的可用性。

上下文窗口限制 (Context Window Limit)

虽然现代 LLM 的上下文窗口在扩大 (例如 GPT-4 Turbo 128K),但仍有上限。处理超大规模文本库时,需要智能检索而非直接注入全部数据。

RAG 的核心思想

RAG (Retrieval-Augmented Generation) 的核心思想:

用户查询 检索相关文档 注入 Context LLM 生成答案

不依赖模型的参数知识,而是动态检索外部知识库中的相关信息,让模型基于真实、最新的上下文生成答案。

RAG 的三个演进阶段

演进阶段 核心特点 优点 缺点 适用场景
Naive RAG 分块 → 嵌入 → 相似度搜索 → LLM 实现简单,流程清晰 检索精度低,易丢失上下文 快速原型,小规模场景
Advanced RAG 查询优化 + 精排 + 重排 + 上下文压缩 检索和生成质量显著提升 系统复杂度增加,计算成本提高 生产环境,对质量要求高
Modular RAG 模块化设计,支持条件路由和动态组装 灵活性强,可针对性优化每个模块 需要大量标注数据和实验 超大规模应用,特殊业务需求

2. RAG 完整架构

两大阶段:索引 + 查询

RAG 系统架构:索引阶段 + 查询阶段 索引阶段 (Offline) Documents Chunking (分块策略) Embedding (向量化) Vector Store (HNSW, IVF, ...) 元数据存储 查询阶段 (Online) User Query Query Embed Retriever (ANN Search) Top-K Docs Reranker (精排) Context Build LLM (生成) Answer 迭代反馈与评估

索引阶段 (Indexing): 离线预处理,一次性执行。将原始文档分块、向量化,存储到向量数据库中以支持快速检索。

查询阶段 (Query): 在线执行,每次用户查询时触发。将用户查询转化为向量,检索相关文档,重排精排,构建提示词,调用 LLM 生成最终答案。

3. 文本嵌入 (Embedding) 详解

嵌入模型的演进

2013
Word2Vec
Skip-gram 和 CBOW 模型。每个词映射到固定维度的向量空间,能捕捉基本的词义关系。局限:单词级别,不能处理词序和长距离语义。
2018
ELMo / BERT 嵌入
上下文化的词嵌入。BERT 能捕捉句子和文档级别的语义,但需要微调。ELMo 基于 LSTM,计算复杂度较高。
2019
Sentence-BERT (SBERT)
引入句子级对比学习损失函数,直接训练产生可比较的句子向量。大幅降低计算成本,成为 RAG 的标准选择。
2021-现在
现代嵌入模型
OpenAI text-embedding-3, BGE (BAAI), E5-mistral, Cohere, GTE, Jina Embeddings 等。在各种下游任务上优化,多语言支持,不同维度选项,特殊用途(长文本、多粒度等)。

对比学习训练原理

现代嵌入模型大多基于对比学习 (Contrastive Learning)

InfoNCE Loss 函数:

L = -log(exp(sim(q, p+) / τ) / Σ exp(sim(q, p_i) / τ))

其中:

  • q - 查询句子的嵌入向量
  • p+ - 正样本(相关文本)的嵌入向量
  • p_i - 负样本(无关文本)的嵌入向量
  • sim(·,·) - 相似度函数(通常是余弦相似度)
  • τ - 温度参数,控制相似度分布的锐度

训练目标: 最小化正样本与查询的距离,最大化负样本与查询的距离。通过大量正负样本对的对比,模型学会了在向量空间中捕捉语义相似性。

主流嵌入模型对比

模型 维度 训练数据规模 特点 适用场景
OpenAI text-embedding-3-small 1536 大规模多语言数据 商业模型,性能稳定,降维友好 通用 RAG,企业应用
OpenAI text-embedding-3-large 3072 大规模多语言数据 更强的表达力,成本更高 高精度需求,知识密集任务
BGE-M3-Embedding 1024 多语言(包括中文) 开源,多粒度(token, chunk, doc),混合搜索 中文 RAG,多粒度检索
E5-mistral-7b-instruct 1024 大规模英文数据 基于 Mistral,指令可微调,开源可部署 私有部署,特定领域微调
Cohere embed-v3 可配置 (64-4096) 专有数据集 动态维度,支持短文本和长文本 灵活的成本控制,多任务
GTE (Alibaba) 1024 中文优化 面向中文优化,开源 中文文档检索
Jina Embeddings v3 可变 (可达 8192) 长文本优化 支持超长上下文 (8K tokens),云原生 长文档检索,法律文书等

高级嵌入技术

Hard Negative Mining(难负样本挖掘)

在对比学习中,不是所有的负样本都同等重要。"难负样本"是那些与查询在语义上相似但标签不同的样本。通过优先使用难负样本,模型的区分能力显著提升。

实现: 在训练中,使用 BM25 或之前模型的检索结果识别难负样本,优先在批次中包含它们。

Matryoshka Representation Learning(俄罗斯套娃表示)

模型在训练时,同时优化多个不同维度的表示。允许在推理时根据需求选择向量维度,权衡精度与成本。例如,text-embedding-3-small 在全 1536 维度和截断后的 256 维度上都能表现良好。

优势: 灵活的性能-成本权衡,降低存储和计算成本而几乎不损失精度。

相似度计算:余弦相似度

在高维向量空间中,余弦相似度是检索最常用的相似度度量:

cos(A, B) = (A · B) / (||A|| × ||B||)

计算两个向量的夹角的余弦值。结果在 [-1, 1] 之间,值越大表示越相似。

面试考点:

  • 对比学习中 InfoNCE loss 的直观理解
  • 什么是硬负样本挖掘?为什么重要?
  • 不同嵌入模型的选择标准是什么?
  • Matryoshka Representation 如何实现成本优化?

4. 向量数据库

核心问题:高维近似最近邻搜索 (ANN)

向量数据库的根本问题:给定一个查询向量 q,从数百万个向量中快速找到最相似的 K 个向量。精确最近邻搜索的时间复杂度是 O(N),这对于大规模数据不可接受。因此需要 近似最近邻搜索 (ANN),在精度和速度之间找到平衡。

主流 ANN 算法详解

HNSW (Hierarchical Navigable Small World)

思路: 受复杂网络理论启发,构建一个多层的小世界网络结构,在高层稀疏导航,逐层到达目标区域。

构建过程:

  • 为每个新插入的向量随机选择一个层级 (layer)
  • 在该层级及更高层级上,找到最近的 M 个向量作为邻接点
  • 连接新向量与这些邻接点,形成图的边

查询过程:

  • 从最高层的任意点开始(通常是入口点)
  • 在该层贪心搜索,找到最近邻
  • 下降到下一层,从上层找到的最近邻继续贪心搜索
  • 重复直到到达第 0 层,返回 K-NN

性能: 查询时间复杂度 O(log N),构建复杂度 O(N log N)

IVF (Inverted File Index)

思路: 先用 K-means 将向量空间分成 K 个聚类簇,每个簇由其聚类中心代表。查询时,找最近的聚类中心,然后只在相关簇内搜索。

构建过程:

  • 使用 K-means 算法将全部向量分成 K 个簇
  • 为每个簇维护一个倒排表 (inverted list),记录属于该簇的向量
  • 保存每个簇的聚类中心向量

查询过程:

  • 计算查询向量到所有聚类中心的距离
  • 选择最近的 nprobe 个簇(通常 nprobe = 1 到 10)
  • 在这些簇内的向量中进行线性搜索或进一步优化

性能: 当 nprobe 较小时速度快,但精度依赖于簇质量

Product Quantization (PQ)

思路: 将高维向量分成多个子段,每个子段独立量化。大幅减小存储空间同时保留相似度计算能力。

工作原理:

  • 将 D 维向量分成 m 段,每段 d 维
  • 对每段独立进行 K-means 量化,产生 256 个聚类中心
  • 原向量用 m 个字节表示 (每字节是段的聚类索引)
  • 查询时,用段级距离近似计算完整距离

优势: 存储减少 100-1000 倍,距离计算仍然快速

ScaNN (Scalable Nearest Neighbors) - Google

创新点: 各向异性向量量化 (Anisotropic Vector Quantization)。在量化时考虑各个方向的不同重要性,比等向量化的 PQ 更精确。

特点: Google 内部使用,在 TIMIT 等标准数据集上性能最优

主流向量数据库对比

数据库 架构 ANN 算法 部署方式 特点 适用场景
Pinecone 托管云服务 HNSW + 优化 Serverless 完全托管,开箱即用,支持元数据过滤 快速原型,小中型企业
Weaviate 分布式,模块化 HNSW 自托管 + 云 开源,混合搜索 (dense + sparse),GraphQL API 混合搜索需求,自有基础设施
Qdrant Rust 实现,高性能 HNSW 自托管 + Qdrant Cloud 低延迟,高吞吐,成熟的 API 高性能需求,大规模检索
Milvus 分布式,可扩展 HNSW, IVF, DiskANN Kubernetes 友好 开源,支持多种 ANN,GPU 加速 超大规模企业,云原生
ChromaDB 嵌入式 + 服务器 HNSW Python 库或服务 轻量级,零配置,内置嵌入模型 快速原型,学习项目
pgvector PostgreSQL 扩展 IVFFlat, HNSW PostgreSQL 插件 与关系数据库无缝集成,SQL 查询 已有 PostgreSQL,混合业务
FAISS 库(非数据库) IVF, PQ, HNSW 等 本地库 Facebook 开源,多 GPU 支持,研究友好 研究,离线批处理

面试考点:

  • HNSW 的基本原理和查询复杂度?
  • IVF 和 HNSW 的区别与权衡?
  • Product Quantization 如何减小内存占用?
  • 如何为不同场景选择合适的向量数据库?

5. 分块策略 (Chunking)

为什么需要分块?

嵌入模型的长度限制: 大多数嵌入模型有最大输入长度限制(如 BERT 的 512 tokens,text-embedding-3 的 8191 tokens)。超过长度的文本需要被切分。
小块的语义精度: 较小的文本块 (如 256-512 tokens) 相比长文本有更明确的语义中心,检索精度更高。长文本可能包含多个不相关的话题。
降低存储和计算成本: 小块可以更高效地索引和检索,减少向量数据库的存储占用和查询时间。
提示词窗口管理: LLM 的输入长度有限,需要选择最相关的文本块放入提示词中,而不是整个文档。

常见分块策略

1. 固定大小分块 (Fixed Size)

最简单的方法:按固定字符数或 token 数切分文本。

chunk_size = 512, overlap = 50

优点: 实现简单,计算快

缺点: 可能在句子中间或语义边界处切断,降低检索质量

2. 递归字符分块 (Recursive Character Split)

LangChain 默认方法。按照层级分隔符 (如 "\n\n", "\n", " ", "") 递归切分,尽量保持语义完整性。

separators = ["\n\n", "\n", " ", ""]
递归选择分隔符直到块大小合适

优点: 保持段落和句子的完整性

缺点: 对格式不规范的文本效果差,仍需要调参

3. 语义分块 (Semantic Chunking)

基于嵌入相似度检测语义边界。计算相邻句子的嵌入相似度,当相似度下降到阈值以下时,认为找到了语义边界。

优点: 语义感知,分块质量最高

缺点: 计算成本高(需要嵌入每个句子),推理时间长

工具: llamaindex, langchain 都有语义分块的实现

4. 文档结构感知分块 (Document-Aware Chunking)

利用文档的结构信息(标题、段落、章节、表格等)进行分块,保留层级关系。

实现: 先解析 Markdown 或 HTML,按标题层级组织,然后在叶子章节级别做分块

优点: 保留文档上下文,支持层级查询

缺点: 需要针对特定格式的解析器

5. 父子分块 (Parent-Child Chunking)

创建两个层级的块:小块用于向量检索,大块作为最终的上下文注入。检索时返回小块ID,但将对应的大块注入提示词。

优点: 兼顾检索精度(小块) 和上下文丰富度(大块)

缺点: 需要额外的映射管理

6. Late Chunking (Jina AI)

先对整个长文档进行嵌入,然后基于已计算的嵌入进行分块,而非先分块再嵌入。

优点: 充分利用嵌入模型的长上下文能力,避免分块导致的信息丢失

缺点: 嵌入成本高,需要支持长上下文的模型

分块参数选择

参数 典型值 影响因素 调优方向
Chunk Size 256-1024 tokens 嵌入模型限制,文本粒度需求 更小 → 精度高但覆盖面小;更大 → 上下文丰富但语义分散
Chunk Overlap 10-20% (of chunk size) 文本连贯性需求,上下文边界问题 更大 → 减少边界截断问题但增加冗余;更小 → 节省成本
Strategy Recursive / Semantic 文本特性,质量要求,计算预算 快速原型用 Recursive;关键应用用 Semantic

面试考点:

  • 为什么需要分块?
  • 如何选择分块大小和重叠?
  • 什么是语义分块?优缺点?
  • 父子分块模式的优势?

6. 检索策略

检索方式对比

稠密检索 (Dense Retrieval)

使用向量相似度搜索。查询和文档都转化为向量,计算向量相似度,返回最相似的 K 个文档。

优点: 捕捉语义相似性,跨语言检索

缺点: 需要额外的嵌入计算和向量存储

稀疏检索 (Sparse Retrieval) - BM25

经典的信息检索方法,基于 TF-IDF 和词的统计特性。计算查询词和文档词的加权匹配分数。

BM25 公式:

score(q, d) = Σ IDF(q_i) * (f(q_i, d) * (k1 + 1)) / (f(q_i, d) + k1 * (1 - b + b * |d| / avgdl))

其中 f(q_i, d) 是词 q_i 在文档 d 中的频率,|d| 是文档长度

优点: 快速、可解释、精确匹配,不需要嵌入

缺点: 无法理解语义,依赖关键词匹配

混合搜索 (Hybrid Search)

结合稠密和稀疏检索的优势。同时执行向量搜索和 BM25 搜索,然后融合结果。

融合方法:

  • 加权组合: score = w * dense_score + (1-w) * sparse_score
  • 倒数排名融合 (RRF): score = Σ 1/(k + rank_i) 其中 k 通常为 60

优点: 综合了精确匹配和语义匹配,性能最优

多向量检索 (Multi-Vector) - ColBERT

不是为整个文本生成单个向量,而是为每个词生成一个向量。查询的每个词与文档的所有词向量进行匹配。

sim(q, d) = Σ_i max_j (q_i · d_j)

MaxSim:对于每个查询词,找到与文档中最相似的词,求和

优点: 介于词级和文档级之间,精度高

缺点: 计算和存储成本高

面试考点:

  • BM25 算法的原理和参数含义?
  • 密集检索 vs 稀疏检索的权衡?
  • 混合搜索如何实现和融合结果?
  • ColBERT 的多向量方法有什么优势?

7. 高级 RAG 技术

查询优化

查询改写 (Query Rewriting)

用 LLM 改进用户的原始查询,使其更容易被检索系统理解。例如,将 "我怎样才能..." 改写为 "方法:..."。

实现: 一个简单的 LLM 调用,给定用户查询和一些示例,返回改写后的查询

假设性文档嵌入 (HyDE)

不直接用用户查询检索,而是先让 LLM 生成一份假设性的相关文档,然后用这个假设文档的嵌入进行检索。

直观理解: 假设性文档通常包含查询中暗示的关键信息和上下文,比用户简短的查询更容易匹配真实文档。

多查询 (Multi-Query)

LLM 生成用户查询的多个语言变体或相关查询,然后分别进行检索,最后合并结果。

优点: 覆盖多个角度的表述方式,提高召回率

Step-Back Query

将用户的具体查询抽象化为更高层次的问题。例如,从 "COVID-19 对中国经济的影响" 抽象到 "大规模传染病对经济的影响",以检索更相关的背景信息。

检索后处理

重排 (Reranking)

初步检索返回 Top-K 文档后,使用交叉编码器 (Cross-Encoder) 对这些文档进行精排。

方法对比:

  • Bi-encoder (检索用): 分别编码查询和文档,计算向量相似度。快但精度有限。
  • Cross-encoder (重排用): 联合编码 (query, document) 对,直接预测相关性分数。精确但计算成本高。

流程: 密集检索 (Fast, 快速返回候选) → 交叉编码器重排 (Slow, 精确排序)

工具: Cohere Rerank, BGE-reranker, ColBERT 等

上下文压缩 (Contextual Compression)

从检索到的文档中提取最相关的片段,而不是返回整个文档。减少输入给 LLM 的文本量,降低成本同时提高相关性。

Lost in the Middle Problem

研究表明,当多个文档被拼接到 LLM 的提示词中时,中间的文档往往被忽视。LLM 倾向于关注开头和结尾的文档。

解决方案: 将最重要的相关文档放在提示词的开头或结尾,而不是中间。

高级架构模式

递归检索 (Recursive Retrieval)

多轮检索,逐步细化。初次检索返回粗粒度结果后,基于中间生成的内容,进行更精细的第二轮检索。

纠正性 RAG (Corrective RAG, CRAG)

检索后评估检索文档的相关性:

  • 如果相关性高 → 直接用于生成
  • 如果相关性低 → 降级到 web 搜索或其他知识源

优点: 自适应地处理检索失败的情况

自适应 RAG (Self-RAG)

模型在生成过程中自己决定是否需要检索。对于能从参数知识中回答的问题,跳过检索;对于需要外部知识的问题,触发检索。

实现: 使用特殊 token (如 [RETRIEVE]) 标记检索点,模型学会何时生成这个 token

适应性 RAG (Adaptive RAG)

根据查询复杂度或类型选择不同的检索策略:

  • 简单查询 → Naive RAG (快速)
  • 复杂查询 → Advanced RAG + 多轮检索
  • 事实性查询 → 混合搜索
  • 推理性查询 → 知识图谱 + 检索
高级 RAG 流程示例:CRAG User Query Query Rewrite Retrieval (初步检索) Relevance Check (评估相关性) 相关? YES Generate Answer NO Web Search (降级处理) Final Answer

8. GraphRAG (Microsoft)

核心思想

GraphRAG 不仅检索相关文档,而是从文档中构建知识图谱 (Knowledge Graph),利用图结构的全局视角来回答问题。特别适合需要综合多个信息源的复杂问题。

工作流程

1

实体和关系提取

使用 LLM (如 GPT-4) 从文本中提取实体和它们之间的关系。例如,从 "张三是阿里巴巴的 CTO" 中提取实体 (张三, 阿里巴巴) 和关系 (任职)。

2

知识图谱构建

将提取的实体和关系组织成有向图。每个实体是节点,每个关系是边,包含关系的类型和属性。

3

社区检测

使用 Leiden 算法(比 Louvain 更优)对图进行社区检测,找到紧密相关的实体簇。每个社区代表一个领域或话题。

4

自底向上的社区摘要

对每个社区及其子社区,使用 LLM 生成摘要。形成多层次的摘要树,从叶子社区的详细摘要到根社区的高层概括。

5

查询路由与搜索

全局查询 (Global): 并行查询所有社区摘要,获得数据集的全局视角。
本地查询 (Local): 基于查询内容精准定位相关社区,返回详细信息。

全局查询 vs 本地查询

查询类型 处理方式 特点 适用问题类型
全局查询 (Global) Map: 并行查询所有社区
Reduce: 汇总聚合结果
综合整个数据集,获得全景视图 宏观分析,趋势总结,跨领域综合
本地查询 (Local) 定位相关社区,深入探索细节 精确到特定话题,信息密集 微观分析,特定实体追踪,关系探索

GraphRAG 的优势与局限

优势

  • 全局视角:能综合多个信息源的关键观点
  • 关系理解:显式建模实体和关系,支持复杂推理
  • 可解释性:知识图谱提供清晰的推理链
  • 长文档处理:通过社区分解,能处理很长的文档集合

局限

  • 构建成本高:需要 LLM 多次调用进行提取和摘要
  • 提取准确性:LLM 提取的实体和关系可能不完整或有误
  • 复杂性:系统复杂,难以调试和优化
  • 适应性:对于高度动态的数据或特定领域知识,效果可能一般

LightRAG

LightRAG 是 GraphRAG 的轻量级替代方案,降低了构建和查询的成本,同时保持了图结构的优势。相比 GraphRAG 的多层社区和复杂摘要,LightRAG 使用更简化的图结构和查询策略。

9. Function Calling / Tool Use

什么是 Function Calling?

Function Calling 让 LLM 有能力调用外部函数或工具,而不仅仅生成文本。模型能理解何时需要调用工具、调用哪个工具、传递什么参数,然后应用程序执行函数并将结果返回给模型。

OpenAI Function Calling

定义函数模式

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a location",
    "parameters": {
      "type": "object",
      "properties": {
        "location": {
          "type": "string",
          "description": "The city and state, e.g. San Francisco, CA"
        },
        "unit": {
          "type": "string",
          "enum": ["celsius", "fahrenheit"],
          "description": "Temperature unit"
        }
      },
      "required": ["location"]
    }
  }
}

模型返回 tool_calls

{
  "id": "chatcmpl-xxx",
  "choices": [{
    "message": {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_xyz",
          "type": "function",
          "function": {
            "name": "get_weather",
            "arguments": "{\"location\": \"San Francisco, CA\", \"unit\": \"celsius\"}"
          }
        }
      ]
    }
  }]
}

并行函数调用

# 一个 API 调用可以同时调用多个函数
# 模型返回多个 tool_calls,应用程序并行执行
tool_calls = response.choices[0].message.tool_calls
results = [execute_function(tc.function.name, tc.function.arguments) for tc in tool_calls]

Anthropic Tool Use (Claude)

工具定义

tools = [
    {
        "name": "get_weather",
        "description": "Get weather for a location",
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {"type": "string"},
                "unit": {"enum": ["celsius", "fahrenheit"]}
            },
            "required": ["location"]
        }
    }
]

response = client.messages.create(
    model="claude-opus",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "What's the weather in NYC?"}]
)

处理工具使用

# 检查响应中是否有工具调用
for block in response.content:
    if block.type == "tool_use":
        tool_name = block.name
        tool_input = block.input
        tool_use_id = block.id

        # 执行工具
        result = execute_tool(tool_name, tool_input)

        # 将结果返回模型
        messages.append({
            "role": "user",
            "content": [
                {
                    "type": "tool_result",
                    "tool_use_id": tool_use_id,
                    "content": str(result)
                }
            ]
        })

执行流程

Function Calling 执行流程 User Query LLM 分析 需要工具? 返回 tool_calls (函数+参数) 应用执行 函数调用 执行细节 序列执行 (Serial) 一个接一个调用函数 适合有依赖关系的操作 并行执行 (Parallel) 同时调用多个独立函数 提高效率,降低延迟 将函数结果返回 LLM LLM 生成 最终答案

面试考点:

  • Function Calling 的工作原理?
  • OpenAI 和 Anthropic 的工具定义格式区别?
  • 如何设计好的函数模式?
  • 并行函数调用的优势和应用场景?

10. MCP (Model Context Protocol)

什么是 MCP?

MCP 是 Anthropic 在 2024 年 11 月推出的开放标准,用于统一 LLM 与外部工具、数据源、应用的连接方式。类似于"LLM 应用的 USB 标准",使得工具开发者和应用开发者可以独立工作,通过 MCP 标准进行集成。

MCP 的三大能力

Tools (工具/函数)

让 LLM 可以调用的函数。类似 Function Calling,但以标准化的方式定义和执行。

示例: 查询数据库、调用 API、执行计算、文件操作

Resources (资源/数据)

LLM 可以访问的数据源或上下文。允许应用向 LLM 提供动态的、上下文相关的信息。

示例: 文件内容、数据库查询结果、用户会话数据、实时数据流

Prompts (提示模板)

可复用的提示词模板,可以包含参数和动态内容。允许统一管理和版本控制提示词。

示例: 代码审查提示、内容生成模板、问题分类提示

MCP 架构

MCP 架构:Client - Server 模式 Client (LLM Application) • Claude • 应用逻辑 JSON-RPC over stdio/HTTP MCP Server (Tool/Data Provider) Tools | Resources | Prompts 传输方式 stdio 本地进程通信 低延迟,同机器 SSE Server-Sent Events 单向推送,事件流 HTTP REST API 远程服务器,标准协议 生态示例 GitHub (代码审查) | PostgreSQL (数据库查询) | Slack (消息发送) | Linear (任务管理) | 1000+ MCP servers

MCP vs Function Calling

特性 MCP Function Calling (OpenAI/Anthropic)
定位 开放标准协议 模型 API 功能
范围 Tools + Resources + Prompts 仅 Tools
传输 stdio/HTTP/SSE HTTP (API 调用)
适用 复杂的多工具系统,需要数据上下文 简单函数调用,单个 API 调用
学习曲线 较陡,需要理解协议 较平,易于上手

MCP 的发展潜力

  • 生态扩展: Anthropic 宣布超过 1000 个开源 MCP servers 已经上线
  • 跨平台支持: 不仅支持 Claude,也在与其他 LLM 厂商合作
  • 统一接口: 将成为 LLM 应用与外部系统连接的事实标准
  • 企业应用: 为企业安全地集成 LLM 提供了标准化的方式

面试考点:

  • MCP 是什么?与 Function Calling 的区别?
  • MCP 的三大能力(Tools, Resources, Prompts)分别是什么?
  • MCP 的传输方式有哪些?各自适用场景?
  • 如何开发一个 MCP Server?

11. RAG 评估

评估的多个层级

RAG 系统评估金字塔 端到端评估 Answer Correctness 生成阶段评估 Faithfulness, Answer Relevancy 检索阶段评估 Precision@K, Recall@K, MRR

组件级评估指标

检索 (Retrieval) 指标

Precision@K 前 K 个检索结果中,有多少是相关的 Precision@5 = 相关文档数 / 5
Recall@K 所有相关文档中,前 K 个结果覆盖了多少 Recall@5 = 检索到的相关数 / 总相关数
MRR (Mean Reciprocal Rank) 第一个相关结果的位置倒数的平均 MRR = 平均(1/rank_of_first_relevant)
NDCG (Normalized Discounted Cumulative Gain) 考虑结果排序和相关程度的加权指标 评估排序质量,范围 [0,1]

生成 (Generation) 指标

Faithfulness 生成的答案是否忠实于检索到的文档内容 评估幻觉程度,通常用 LLM 自动评估
Answer Relevancy 生成的答案是否回答了用户的问题 衡量答案与查询的相关性
Hallucination Rate 答案中完全虚构(无根据)的内容比例 越低越好,理想值接近 0

RAGAS 框架

RAGAS (Retrieval-Augmented Generation Assessment) 是一个开源框架,专门用于自动化 RAG 系统评估。它提供了一套无需人工标注的自动化指标。

Faithfulness

衡量生成答案中有多少内容可以从检索的上下文中推导出来。使用 LLM 检测答案中的声称,并验证其是否能从上下文支持。

计算: 可被上下文支持的声称比例

范围: [0, 1],越高越好

Context Relevancy (Context Precision)

检索到的上下文中,有多少句子对回答问题是必要的。低相关性表示检索中有许多噪声。

计算: 必要上下文的比例

范围: [0, 1],越高越好

Answer Relevancy

生成答案与用户问题的相关程度。使用 LLM 将答案改写成问题,比较改写问题与原问题的相似度。

计算: 基于向量相似度的相关性评分

范围: [0, 1],越高越好

Context Recall

检索到的所有上下文中,回答问题所需的信息占比。评估检索的完整性。

计算: 支持性证据的覆盖比例

范围: [0, 1],越高越好

RAGAS 使用示例

from ragas.metrics import (
    answer_relevancy, faithfulness, context_precision, context_recall
)
from ragas import evaluate

# 定义数据集:[(question, answer, contexts), ...]
dataset = [
    {
        "question": "What is AI?",
        "answer": "AI is artificial intelligence...",
        "contexts": ["AI stands for Artificial Intelligence..."]
    }
]

# 评估
results = evaluate(
    dataset=dataset,
    metrics=[answer_relevancy, faithfulness, context_precision, context_recall]
)
print(results)

评估的实践建议

  • 不依赖单一指标: 综合考虑检索、生成、端到端的多个指标
  • 建立基准数据集: 针对应用领域创建金标数据集,进行对标评估
  • 定期监控: 在生产环境中持续收集样本,定期评估系统性能
  • 人工评估: 虽然自动评估方便,但人工评估仍然是最可靠的方式
  • A/B 测试: 比较不同配置的 RAG 系统性能

面试考点:

  • 如何评估 RAG 系统?主要指标有哪些?
  • RAGAS 框架的四个核心指标分别衡量什么?
  • 检索精度和生成质量的权衡?
  • 如何在生产环境中持续评估和优化 RAG 系统?

12. 面试高频问题

Q1: 什么是 RAG?RAG 解决了什么问题?

核心要点: RAG = Retrieval-Augmented Generation,通过检索外部知识库的相关文档,将其作为上下文注入给 LLM,让模型基于真实、最新的信息生成答案。解决知识截止、幻觉、私有数据访问问题。

Q2: Naive RAG vs Advanced RAG 有什么区别?

核心要点: Naive RAG 流程简单(分块 → 嵌入 → 检索 → 生成),但检索精度低。Advanced RAG 添加了查询优化、重排、上下文压缩等技术,显著提升了质量。Modular RAG 进一步支持模块化和条件路由,允许对不同类型查询采用不同策略。

Q3: 如何选择嵌入模型?

核心要点: 考虑维度 (成本/精度权衡)、训练数据 (语言和领域覆盖)、微调能力、成本预算。通用场景用 text-embedding-3-small,中文优化用 BGE-M3,需要长文本支持用 Jina。优先考虑开源模型便于私有部署和微调。

Q4: HNSW 和 IVF 算法的区别?各自何时使用?

核心要点: HNSW 是多层图结构,查询复杂度 O(log N),精度高但内存占用大。IVF 是聚类+倒排表,查询速度受 nprobe 影响,内存占用小。大规模、对精度要求高用 HNSW;成本敏感、接受精度略微下降用 IVF;超大规模考虑 PQ 量化。

Q5: 分块大小和重叠应该如何选择?

核心要点: chunk_size 通常 256-1024 tokens(更小 → 精度高但上下文少;更大 → 上下文丰富但语义分散)。overlap 通常 10-20%(保持连贯性,减少边界截断)。最好通过 RAGAS 等框架在真实数据上实验,而不是凭经验选择。

Q6: 什么是混合搜索?为什么它比单一方法更好?

核心要点: 混合搜索结合了稠密检索(语义相似)和 BM25(精确词匹配)。稠密检索容易漏掉关键词精确匹配,BM25 无法理解语义。混合搜索通过 RRF 或加权融合两者,兼顾精确性和语义理解,通常比单一方法性能更优。

Q7: 重排 (Reranking) 的作用和成本权衡?

核心要点: 重排使用交叉编码器对候选文档精排,显著提高相关性。但计算成本高 (对每个候选计算相关性)。实践中常用两阶段:bi-encoder 快速检索返回 Top-K,cross-encoder 重排 Top-K。为成本考虑,只对 Top-K 做重排,而不是整个文档库。

Q8: GraphRAG 相比传统 RAG 的优势和劣势?

核心要点: GraphRAG 通过知识图谱+社区检测,提供全局视角,特别适合综合多源信息的复杂问题。优势:全局视角、关系建模、可解释性。劣势:构建成本高、提取准确性依赖 LLM、系统复杂、调试困难。适合知识密集、需要关系理解的场景。

Q9: 什么是 MCP?与 Function Calling 有什么区别?

核心要点: MCP (Model Context Protocol) 是 Anthropic 推出的开放标准,统一 LLM 与外部工具、数据的连接方式。范围比 Function Calling 更广(Tools + Resources + Prompts)。Function Calling 仅限工具调用,MCP 还能提供动态上下文和提示模板。MCP 是协议标准,Function Calling 是模型 API 功能。

Q10: 如何评估一个 RAG 系统的质量?

核心要点: 多层级评估:(1) 检索评估 - Precision@K, Recall@K, NDCG;(2) 生成评估 - Faithfulness, Answer Relevancy;(3) 端到端 - Answer Correctness。使用 RAGAS 框架自动化评估。建立基准数据集,定期人工抽样审核,A/B 对比不同配置。优先追求 Faithfulness(减少幻觉),再追求 Answer Relevancy(回答准确度)。

← 提示工程 AI Agent →