1.1 langgraph面试题汇总.

面试中,RAG 的考察早已不是"背定义"就能过关的了。面试官更看重的是你对检索、生成、评估 全链路的理解,以及遇到实际问题时的优化思路

下面我按基础概念 → 检索优化 → 生成与评估 → 工程实践四个维度,梳理高频考点并配上可运行的代码案例。


一、基础概念篇(必考开场题)

Q1:RAG 和 SFT(微调)的本质区别是什么?

面试官追问:你们项目为什么选 RAG 而不是微调?

核心答题框架

维度 RAG SFT(监督微调)
知识存储 外挂向量库(非参数记忆) 固化进模型参数(参数记忆)
知识更新 换库即更新,秒级生效 需重新训练,成本高
幻觉控制 强制基于检索资料回答 依赖模型记忆,易幻觉
适用场景 知识高频变化、需溯源 固定风格/格式、低延迟

加分回答 :> "我们采用 RAG-First 策略,先跑通 RAG 验证想法;如果发现模型语感或输出格式不达标,再用 SFT 打补丁优化风格。一个是查资料,一个是背答案,现在业务需求变得比翻书还快,查资料更划算。"


二、检索优化篇(核心高频区)

Q2:如何解决"检索噪声"和"漏召"问题?

面试官最常问的就是 "检索结果不准怎么办" 。核心思路是混合检索 + 重排序

代码案例:混合检索(BM25 + 向量检索 + RRF 融合)

python 复制代码
import numpy as np
from sentence_transformers import SentenceTransformer
from rank_bm25 import BM25Okapi
import jieba

# 1. 准备文档库
documents = [
    "RAG是检索增强生成,结合检索和生成解决幻觉问题",
    "BM25是经典的关键词检索算法,适合精确匹配",
    "向量检索通过Embedding实现语义搜索,适合模糊查询",
    "混合检索结合BM25和向量检索,取长补短"
]

# 2. 中文分词(BM25需要)
tokenized_docs = [list(jieba.cut(doc)) for doc in documents]
bm25 = BM25Okapi(tokenized_docs)

# 3. 向量检索(用Embedding模型)
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')  # 支持中文
doc_embeddings = model.encode(documents)
query = "怎么解决RAG的检索不准问题"
query_embedding = model.encode([query])[0]

# 4. 分别执行两种检索
# BM25关键词检索
tokenized_query = list(jieba.cut(query))
bm25_scores = bm25.get_scores(tokenized_query)  # 每个文档的BM25分数

# 向量语义检索(余弦相似度)
cosine_sims = np.dot(doc_embeddings, query_embedding) / (
    np.linalg.norm(doc_embeddings, axis=1) * np.linalg.norm(query_embedding)
)

# 5. RRF(Reciprocal Rank Fusion)融合排序
def rrf_fusion(bm25_scores, vec_scores, k=60):
    """RRF融合:将排名转化为倒数分数求和"""
    # 获取排名(分数越高排名越靠前)
    bm25_rank = np.argsort(-bm25_scores)
    vec_rank = np.argsort(-vec_scores)
    
    rrf_scores = np.zeros(len(bm25_scores))
    for rank, idx in enumerate(bm25_rank):
        rrf_scores[idx] += 1 / (k + rank + 1)
    for rank, idx in enumerate(vec_rank):
        rrf_scores[idx] += 1 / (k + rank + 1)
    return rrf_scores

final_scores = rrf_fusion(bm25_scores, cosine_sims)
best_idx = np.argmax(final_scores)
print(f"最佳匹配文档:{documents[best_idx]}")

为什么这样回答加分 :混合检索解决了纯向量检索对精确术语召回率不足的问题------某金融客服系统实践显示,混合检索使问题解决率从 68% 提升至 89%。


Q3:文档分块(Chunking)策略怎么选?

面试官追问:chunk_size 设多大?为什么?

核心答题框架

策略 做法 优缺点
固定大小分块 按 token 数硬切(如 512) 简单但可能截断语义
重叠分块 固定长度 + 20% 重叠 保留上下文连续性
递归分割 \n\n\n 层级切 LangChain 默认,语义较完整
语义分块 基于句子 Embedding 相似度合并 效果好但计算开销大
父子块 小块检索,返回父块上下文 兼顾精度和上下文长度

代码案例:LangChain 递归分割器

python 复制代码
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 递归分割:按层级分隔符切割,保证语义完整性
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,           # 每块约500字符
    chunk_overlap=50,         # 重叠50字符,防止跨块信息丢失
    separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""]
)

chunks = text_splitter.split_text(long_document)
print(f"切分为 {len(chunks)} 个片段")

加分回答 :> "chunk_size 没有万能值,我一般建一个离线评测集,在不同 chunk_size 下测 Recall@K,找到业务最优参数。过小(<256 tokens)会导致上下文断裂,过大(>2048 tokens)会使检索延迟增加 300%。"


Q4:查询改写(Query Rewriting)怎么做?

用户问得模糊时,检索效果会很差。HyDE(Hypothetical Document Embeddings) 是高频考点------让 LLM 先"想象"一份理想答案,再用这个答案去检索。

代码案例:HyDE 查询改写

python 复制代码
from openai import OpenAI

client = OpenAI()

def hyde_rewrite(query: str) -> str:
    """HyDE:让LLM生成假设性答案,再用答案去检索"""
    prompt = f"""请针对以下问题,写一段假设性的标准答案(不需要很長,100字左右):
    
问题:{query}

假设答案:"""

    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3
    )
    hypothetical_answer = response.choices[0].message.content
    return hypothetical_answer

# 原始query:"RAG怎么优化"
rewritten = hyde_rewrite("RAG怎么优化")
# 用 rewritten 去做向量检索,而非直接用原始 query

三、评估篇(体现系统思维)

Q5:如何系统评估 RAG 系统的效果?

面试官追问:你不能只说"感觉还行",要量化。

核心答题框架 :分三层评估:

层级 评估什么 核心指标
检索层 该召回的有没有召回到 Hit@K (命中率)、MRR(平均倒数排名)
生成层 答案对不对、有没有幻觉 Faithfulness (忠实度)、Answer RelevancyContext Recall
端到端层 用户最终体验 任务完成率、点踩率、转人工率

代码案例:用 RAGAS 做自动化评估

python 复制代码
from ragas import evaluate
from ragas.metrics import (
    faithfulness,      # 忠实度:答案是否基于检索上下文
    answer_relevancy,  # 答案相关性
    context_recall,    # 上下文召回率
)
from datasets import Dataset

# 准备评估数据(每条包含:question, answer, contexts, ground_truth)
test_data = Dataset.from_dict({
    "question": ["RAG和微调有什么区别?"],
    "answer": ["RAG是检索增强生成,通过外挂知识库让模型查资料回答..."],
    "contexts": [["RAG全称Retrieval-Augmented Generation,是一种结合检索和生成的技术..."]],
    "ground_truth": ["RAG检索外部知识,微调修改模型参数"]
})

# 运行评估
result = evaluate(
    dataset=test_data,
    metrics=[faithfulness, answer_relevancy, context_recall]
)
print(result)

加分回答 :> "我一般建立 离线+人工+在线 三层闭环:离线跑分做版本对比 → 小流量人工抽查 → 线上 A/B 验证 → 数据回流再优化。只靠人工看,没法规模化迭代。"


四、工程实践篇(拉开差距)

Q6:如何设计高并发 RAG 服务?

面试官追问:10万 QPS 怎么扛?

核心方案

  • 缓存层:Redis 缓存热门 query 结果,FAISS IVF_PQ 索引加速向量检索
  • 异步处理:Kafka 消息队列削峰填谷
  • 弹性扩展:Kubernetes 自动扩缩容

Q7:RAG 出现幻觉怎么办?

多层防御

  1. 置信度过滤:设置答案置信度阈值(>0.85)
  2. 证据链验证:要求输出必须包含 ≥3 个文档引用
  3. Prompt 约束 :强制"必须基于提供的参考资料回答,若资料中没有相关信息,请直接说'不知道'"

五、面试避坑总结

常见扣分点 正确做法
只会背"加载→分块→嵌入→检索→生成" 讲清楚每一步的取舍为什么这么做
说"我用 LangChain 搭的"就停了 补充向量数据库选型 (Milvus/Chroma/FAISS)和选型理由
评估只说"看用户反馈" 分层讲 Hit@K、MRR、Faithfulness 等具体指标
不考虑工程落地 主动提缓存、异步、降级等高并发方案

掌握以上 7 个核心问题 + 配套代码 ,足以应对绝大多数 RAG 面试场景。面试时切记:不要背答案,要讲"取舍" ------面试官想听的是你在不同场景下为什么选 A 不选 B