LangChain 面试八股文
共勉
来源:综合多个技术博客和面试资料整理(博客园、CSDN、卡码笔记等) 整理时间:2026-06-22 总题数:20 道高频面试题,含完整答案、深入解析、常见追问、代码示例
目录
- Graph 结构三要素是什么?职责边界怎么划分?
- 什么是 Conditional Edge?和普通 Edge 有什么区别?
- 什么是 LangChain?它的核心设计理念是什么?
- 什么是 LCEL?它有什么优势?
- 什么是 RAG?完整链路是什么?
- LangChain 中 Memory 是如何工作的?
- 什么是 LangChain Agent?和 Chain 有什么区别?
- LangChain 的整体架构设计包括哪几层?
- LLMChain、SequentialChain 有何异同?
- 如何在 LangChain 中集成自定义工具?
- LangChain 如何处理错误与重试?
- RAG 的幻觉怎么处理?
- 纯向量检索有什么问题?为什么需要混合检索?
- Rerank 是什么?为什么检索之后还要重排序?
- Chunk 怎么切?切大了切小了各有什么问题?
- Embedding 模型怎么选?中文场景选什么?
- LangChain 与 LangGraph 的关系是什么?
- LangGraph 如何编排多个 Agent?
- 什么是 Agentic RAG?和普通 RAG 有什么区别?
- RAG 检索效果不好怎么优化?
一、Graph 结构三要素是什么?职责边界怎么划分?
问题
LangGraph 里的 StateGraph 是怎么运转的?Node、Edge、State 各自的职责边界在哪?
标准答案
Graph 结构由 Node(执行单元)、Edge(控制流)、State(共享状态) 三要素组成。
| 要素 | 职责 | 类比 |
|---|---|---|
| Node | 接收当前 State,执行具体逻辑,返回更新后的 State | 工厂里的工人,只干一件活 |
| Edge | 决定 Graph 的走向:顺序执行、条件分支、循环 | 传送带 + 分拣员 |
| State | 存储所有关键信息,每个 Node 返回更新而非直接修改 | 共享的工作台记录本 |
深入解析
Node 不是简单的函数封装——在架构层面,它是一个执行单元,有明确的输入输出契约,还要考虑重试、超时、错误处理等机制。
Edge 条件路由的能力让 Agent 具备了"判断力":
python复制
graph.add_conditional_edges(
start_node="review",
condition=review_condition,
mapping={
True: END,
False: "write"
}
)
def review_condition(state) -> str:
if state["is_approved"]:
return END
else:
return "write"
State 的不可变性保证状态流转的可追溯性,是现代框架的核心设计。
常见追问
Q: State 设计不当会导致什么问题? A:字段臃肿 → 每次执行传递大量冗余数据;混入临时变量 → 不同 Node 间产生隐式依赖。
Q: Node 粒度怎么划分? A:太粗(意图识别+槽位填充+回答生成写在一个 Node) → 难以复用和调试;太细(每个 API 调用一个 Node) → 结构复杂、State 链路过长。建议按职责划分。
二、什么是 Conditional Edge?和普通 Edge 有什么区别?
问题
LangGraph 中 Conditional Edge 是什么?它解决了什么问题?
标准答案
普通 Edge 在 graph.compile() 时确定目标节点,是编译期决策。 Conditional Edge 的目标节点由 condition 函数在运行时根据当前 State 决定,是运行时决策。
深入解析 — 编译期 vs 运行时
python复制
# 普通 Edge:编译期固定
graph.add_edge("node_a", "node_b") # 永远从 A 到 B
# Conditional Edge:运行时动态
graph.add_conditional_edges(
"router",
lambda state: "pass" if state["score"] > 0.5 else "fail",
{"pass": "approve_node", "fail": "reject_node"}
)
复杂分支场景示例:内容审核 Agent,三个子检查(色情/暴力/广告),任一拒绝则拒绝:
python复制
def moderation_condition(state) -> str:
if state["porn_check"] == "fail" or state["violence_check"] == "fail":
return END
if state["ad_check"] == "fail":
return "manual_review_node"
return "publish_node"
常见追问
Q: condition 函数里能不能调用工具? A:理论上可以,但工程上不推荐。condition 职责应保持单一:读取 State → 做判断 → 返回节点名。
Q: 循环路径上如何设置终止条件? A:1. 在 condition 里确保终止条件一定能触发;2. 在 graph.compile(max_steps=10) 设最大循环次数;3. 捕获超限异常做降级处理。
三、什么是 LangChain?它的核心设计理念是什么?
问题
请解释什么是 LangChain,它的核心价值是什么?
标准答案(30秒面试版)
LangChain 是一个用于开发由大语言模型驱动的应用程序的框架。它的核心设计理念是通过**“可组合性”**将多个模块链接在一起,构建复杂而强大的应用。就像 React 用于构建用户界面一样,LangChain 是用于构建大模型应用界面的工具链。
核心价值:
- 降低开发门槛:提供现成的 Chain、Agent、Memory 等组件
- 增强大模型能力:通过检索增强、工具调用拓展应用边界
- 提升开发灵活性:支持多模型集成、多数据源对接
6 大核心概念
| 概念 | 作用 |
|---|---|
| Models | 与各类 LLM 交互的抽象层(LLM + ChatModel + Embedding) |
| Prompts | 提示词模板管理,动态生成,Few-shot |
| Indexes | 文档加载 → 切分 → 向量化 → 检索 |
| Memory | 对话历史管理,状态持久化 |
| Chains | 组件串联,LCEL 声明式构建 |
| Agents | 由 LLM 驱动,动态决定工具调用步骤 |
四、什么是 LCEL?它有什么优势?
问题
请解释 LCEL 是什么,以及它的优势。
标准答案
LCEL(LangChain Expression Language)是一种声明式的、可组合的语法,用 | 管道符将组件串联。
优势:
- 统一接口:所有组件实现 Runnable 接口,统一 invoke/batch/stream
- 可组合性:管道符串联,代码简洁
- 自动优化:支持并行执行、流式输出、异步调用
- 类型安全:更好的类型提示
代码示例
python复制
from langchain.chat_models import init_chat_model
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
model = init_chat_model("openai:gpt-4o-mini")
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个专业的大模型应用开发助手。"),
("human", "请用通俗语言解释:{topic}")
])
# LCEL 链式调用
chain = prompt | model | StrOutputParser()
answer = chain.invoke({"topic": "LangChain 是什么"})
Runnable 接口提供的调用方式
| 方法 | 说明 |
|---|---|
invoke |
单次调用 |
batch |
批量调用 |
stream |
流式输出 |
astream |
异步流式 |
with_retry |
自动重试 |
with_fallbacks |
降级备用 |
五、什么是 RAG?完整链路是什么?
问题
什么是 RAG?在 LangChain 中如何实现检索增强生成?
标准答案
RAG(Retrieval-Augmented Generation)就是一句话:在 LLM 生成回答前,先从外部知识库检索相关信息,把检索结果塞进 Prompt,让 LLM 基于事实回答。
LLM 的三大知识缺陷
- 知识截止:训练数据有截止日期,昨天的事不知道
- 私有数据无法触达:公司内部文档、客户数据从未见过
- 容易幻觉:不确定时编造看似合理但错误的信息
RAG 七步链路
code复制
Query → 文档处理 → Chunking → Embedding → 检索 → Rerank → 生成
| 步骤 | 做什么 | 关键决策 |
|---|---|---|
| 文档处理 | 解析 PDF/Word/Markdown,提取文本 | PDF 表格怎么处理?要不要 OCR? |
| Chunking | 把长文档切成小块 | 切多大?overlap 多少? |
| Embedding | 把文本块转成向量 | 用什么模型?维度多少? |
| 检索 | 根据问题检索最相关文本块 | 纯向量还是混合检索?Top-K 多少? |
| Rerank | 对检索结果重排序 | 用什么 Rerank 模型? |
| 生成 | 检索结果 + 问题喂给 LLM | Prompt 怎么写?幻觉怎么约束? |
代码示例
python复制
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=30)
docs = splitter.create_documents(texts)
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
六、LangChain 中 Memory 是如何工作的?
问题
LangChain 中的 Memory 有哪些类型?短期历史和长期记忆怎么区分?
标准答案
Memory 保存对话状态,让模型理解之前聊过什么。为什么不能把全部历史塞进 prompt?三个原因:上下文窗口有限、Token 成本高、旧信息干扰。
记忆类型
| 类型 | 特点 | 适用场景 |
|---|---|---|
| ConversationBufferMemory | 直接保存全部对话历史 | 短期简单对话 |
| ConversationSummaryMemory | 自动摘要历史对话 | 长对话,节省 Token |
| ConversationBufferWindowMemory | 只保留最近 k 轮 | Token 预算有限 |
| VectorStoreRetrieverMemory | 向量检索历史 | 长期跨会话记忆 |
| EntityMemory | 跟踪特定实体信息 | 需要记住人物/事物 |
| ConversationSummaryBufferMemory | 摘要 + 完整混合 | 综合场景 |
工程优化手段
- 窗口裁剪:只保留最近 N 轮
- 摘要压缩:对历史做摘要
- 向量检索记忆:按需检索历史
- 过期淘汰:自动清理过期对话
短期 vs 长期记忆
| 类型 | 内容 | 判断标准 |
|---|---|---|
| 短期历史 | 最近几轮消息、临时工具结果 | 不稳定、很快过期 |
| 长期记忆 | 用户偏好、项目背景、常用术语 | 稳定、高频复用 |
七、什么是 LangChain Agent?和 Chain 有什么区别?
问题
什么是 LangChain Agent?它和普通 Chain 有什么区别?
标准答案
普通 Chain:输入进来,模型直接生成输出(线性流程)。 Agent:先判断任务需要什么工具 → 调用工具 → 观察工具结果 → 继续决策 → 完成或停止。
Agent 核心组件
| 组件 | 作用 |
|---|---|
| LLM | 提供推理和决策能力 |
| Tools | 连接外部世界的接口(搜索、数据库、API 等) |
| Prompt | 告诉 Agent 规则、输出格式、约束 |
| Memory | 保存对话历史和任务状态 |
| Executor | 执行控制器,驱动循环 |
协作流程
code复制
用户输入 → Agent(理解意图,选择工具)
↓
LLM(生成工具调用)
↓
Tools(执行工具)
↓
Memory(更新状态)
↓
返回用户
Agent 类型对比
| Agent 类型 | 特点 | 适用场景 |
|---|---|---|
| Zero-shot ReAct | 不需示例,直接推理和行动 | 通用任务 |
| ReAct Docstore | 专门文档检索 | 文档问答 |
| Self-Ask-with-Search | 自我提问并搜索 | 多步搜索任务 |
| Conversational | 支持多轮对话 | 对话型应用 |
LangChain Agent vs 原生 Agent
| 特性 | LangChain Agent | 原生 Agent (OpenAI Function Calling) |
|---|---|---|
| 复杂性 | 高,框架封装 | 低,直接调用 |
| 工具生态 | ✅ 丰富,内置大量工具 | ❌ 有限,需自行实现 |
| 扩展性 | ✅ 模块化,易于扩展 | ❌ 需自定义 |
| 性能 | 有框架开销 | 轻量高效 |
| 适用场景 | 快速构建复杂 Agent | 简单工具调用、低延迟场景 |
八、LangChain 的整体架构设计包括哪几层?
问题
LangChain 的整体架构设计包括哪几层,分别起什么作用?
标准答案
LangChain 整体架构可划分为 基础层、核心层、应用层 三大层级:
| 层级 | 包含内容 | 作用 |
|---|---|---|
| 基础层 | 模型接口、外部工具集成 | 对接各类 LLM(云端/本地),统一调用接口 |
| 核心层 | Prompts、Chains、Memory、Agents、Tools | 提供可组合的核心组件和标准化接口 |
| 应用层 | 文档问答、智能客服、数据分析助手等 | 基于核心层构建具体应用 |
基础层:既支持 OpenAI、Google PaLM 等云端 API 模型,也兼容 Llama、ChatGLM 等本地部署模型。
核心层:通过 LCEL 将各组件串联,提供统一的 Runnable 接口。
应用层:RAG 知识库问答、SQL Agent、数据分析助手等。
九、LLMChain、SequentialChain 有何异同?
问题
LLMChain、SequentialChain 和 SimpleSequentialChain 有哪些异同?
标准答案
| Chain 类型 | 特点 | 输入/输出 | 适用场景 |
|---|---|---|---|
| LLMChain | 最基础,直接调用 LLM | 单一输入 → 单一输出 | 简单问答、文本生成 |
| SimpleSequentialChain | 顺序执行,前一个输出自动成为下一个输入 | 单输入/单输出,自动传递 | 简单多步串联 |
| SequentialChain | 顺序执行,可指定多个输入/输出 | 多输入/多输出,需显式映射 | 复杂多步任务 |
代码示例
python复制
# SimpleSequentialChain:自动传递
chain1 = LLMChain(llm=llm, prompt=prompt1)
chain2 = LLMChain(llm=llm, prompt=prompt2)
simple_chain = SimpleSequentialChain(chains=[chain1, chain2])
# SequentialChain:显式映射
chain1 = LLMChain(llm=llm, prompt=prompt1, output_key="step1_result")
chain2 = LLMChain(llm=llm, prompt=prompt2, output_key="step2_result")
seq_chain = SequentialChain(
chains=[chain1, chain2],
input_variables=["input"],
output_variables=["step1_result", "step2_result"]
)
十、如何在 LangChain 中集成自定义工具?
问题
如何在 LangChain 中集成自定义工具?
标准答案
集成自定义工具有四个步骤:
- 定义工具函数:实现具体功能、定义输入输出格式、处理错误
- 创建 Tool 对象:用
Tool类包装函数,定义名称和描述 - 注册到 Agent:将工具添加到工具列表,在 Agent 初始化时传入
- 测试工具:单独测试 + 集成测试
代码示例
python复制
from langchain.agents import Tool
def search_function(query: str) -> str:
"""调用搜索引擎"""
return search_api(query)
tools = [
Tool(
name="Search",
func=search_function,
description="搜索工具,输入搜索关键词返回结果"
),
Tool(
name="Calculator",
func=calculator_function,
description="数学计算工具,输入数学表达式返回计算结果"
)
]
agent = initialize_agent(
tools=tools,
llm=llm,
agent="zero-shot-react-description"
)
工具设计要点
- 工具名称要清晰,让模型能区分
- 工具描述要详细,包含输入格式和使用场景
- 参数定义要精确(使用 Pydantic 做 Schema 校验)
- 错误处理要完善(返回友好错误信息而非抛异常)
十一、LangChain 如何处理错误与重试?
问题
LangChain 中如何处理错误、重试和降级?
标准答案
LangChain 调用链路很长:用户输入 → 输入验证 → LLM 调用 → 工具调用 → 输出解析 → 返回结果。每一步都可能出错。
三种错误处理机制
1. with_retry 自动重试
python复制
from langchain_core.runnables import Runnable
model_with_retry = model.with_retry(
retry_if_exception_type=(RateLimitError, TimeoutError),
wait_exponential_jitter=True,
stop_after_attempt=3
)
2. with_fallbacks 降级备用
python复制
primary_chain = prompt | claude_model | output_parser
fallback_chain = prompt | gpt4_model | output_parser
chain_with_fallback = primary_chain.with_fallbacks(
fallbacks=[fallback_chain]
)
3. 自定义异常处理
python复制
class RetryOutputParser(BaseOutputParser):
"""解析失败时自动重试"""
def parse(self, text: str):
try:
return self._parse(text)
except OutputParserException:
return self._retry_with_fix(text)
常见错误类型
| 错误类型 | 解决方案 |
|---|---|
| LLM API 超时/限流 (429) | with_retry + 指数退避 |
| 工具调用格式不对 | 输出 Parser 校验 + 重试 |
| 模型输出非期望格式 | with_fallbacks 降级 |
| 网络抖动 | with_retry 自动重试 |
十二、RAG 的幻觉怎么处理?
问题
RAG 检索到了正确信息,LLM 还是编造了不存在的内容,怎么办?
标准答案
幻觉是 RAG 项目最大的工程挑战,面试必问。
幻觉的两种类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 内在幻觉 | 和检索结果矛盾 | 检索说 91%,LLM 说 95% |
| 外在幻觉 | 生成了检索结果没有的内容 | 检索只提 A,LLM 编了 B |
六种处理策略
1. Prompt 约束
python复制
prompt = """
你是一个基于检索结果回答问题的AI助手。
请严格按照以下规则:
1. 只使用提供的参考资料来回答问题
2. 如果资料中没有相关信息,请回答"无法确定"
3. 不要编造任何信息
参考资料:{context}
问题:{question}
"""
2. 输出自校验
python复制
VERIFICATION_PROMPT = """
请检查以下回答是否每一条都能在参考资料中找到依据。
对于每条声明,标注:✅ 有依据 / ❌ 无依据 / ⚠️ 部分依据
回答:{answer}
参考资料:{context}
"""
3. 引用标注:要求 LLM 标注每条信息的来源 chunk
4. 温度调低:temperature 设 0.1-0.3,降低随机性
5. 检索-生成对齐:生成后把回答和检索结果做相似度对比
6. 兜底回答:检索结果相似度低于阈值时,直接返回"未找到相关信息"
十三、纯向量检索有什么问题?为什么需要混合检索?
问题
纯向量检索有什么问题?为什么需要混合检索?
标准答案
纯向量检索的三个致命问题
- 精确匹配不行:搜"RFC 7231"可能返回"HTTP 协议规范"
- 专业术语召回差:"K8s HPA 配置"和"Kubernetes 自动扩缩容"向量距离很远
- 专有名词遗漏:产品名、人名、缩写容易丢失
混合检索 = 向量检索 + 关键词检索
code复制
向量检索(语义 + 模糊匹配)→ http协议、性能优化
关键词检索(精确匹配)→ RFC 7231、HPA 配置
↓
RRF 合并排名
↓
最终结果
RRF(Reciprocal Rank Fusion)合并策略
python复制
def rrf_merge(vector_results, bm25_results, k=60):
scores = {}
for rank, doc in enumerate(vector_results):
scores[doc.id] = scores.get(doc.id, 0) + 1 / (k + rank + 1)
for rank, doc in enumerate(bm25_results):
scores[doc.id] = scores.get(doc.id, 0) + 1 / (k + rank + 1)
return sorted(scores.items(), key=lambda x: x[1], reverse=True)
k 通常设 60,排名越靠前贡献分数越高。RRF 不需要调权重,更稳健。
面试核心点
能说清楚纯向量检索的三个问题,以及混合检索为什么能解决、合并策略用 RRF,这就是面试官想听的深度。
十四、Rerank 是什么?为什么检索之后还要重排序?
问题
你已经用了混合检索,为什么还要 Rerank?
标准答案
检索是粗筛,Rerank 是精排。
| 维度 | 检索 | Rerank |
|---|---|---|
| 模型 | Bi-Encoder | Cross-Encoder |
| 速度 | 快,可预计算 | 慢,需逐对计算 |
| 精度 | 近似相关 | 精确相关 |
| 数据处理 | 百万级 → Top-20 | Top-20 → Top-5 |
Bi-Encoder vs Cross-Encoder
向量检索(Bi-Encoder):问题和文档分别编码成向量,算相似度。互不知道对方存在,只能算"大概相关"。
Rerank(Cross-Encoder):把问题和文档拼在一起送进模型,模型同时看到双方内容,做更精确的相关性判断。代价是慢,只能对少量候选做精排。
效果数据
| 指标 | 检索后(无 Rerank) | Rerank 后 |
|---|---|---|
| Top-5 召回率 | 71% | 89% |
| Top-3 准确率 | 65% | 84% |
常用 Rerank 模型
| 模型 | 特点 |
|---|---|
| BGE-Reranker (bge-reranker-v2-m3) | 中文效果好,开源免费 |
| Cohere Rerank | API 调用,英文为主 |
| bce-reranker-base_v1 | 中文场景,轻量级 |
十五、Chunk 怎么切?切大了切小了各有什么问题?
问题
你们 Chunk 策略怎么设计的?chunk_size 设多少?为什么?
标准答案
切大了 → 信息稀释:相关片段被无关内容淹没,相似度降低 切小了 → 上下文丢失:断章取义,LLM 无法理解完整含义
三种主流 Chunk 策略
① 固定长度切分:每 512 token 切一块。简单但不顾语义边界。
② 递归切分(生产环境最常用):
python复制
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=200,
separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""]
)
③ 语义切分:用 Embedding 计算相邻句子的语义相似度,在语义断点处切分。效果好但计算量大。
Overlap 的作用
相邻 chunk 之间重叠一部分文字,避免关键信息正好在切割点被截断。通常设 chunk_size 的 10%-20%。
不同文档类型的处理策略
| 文档类型 | 处理策略 |
|---|---|
| Markdown | 按标题层级切分,保留层级信息 |
| 先解析表格和图片,再按段落 | |
| 代码 | 按函数/类切分,保留完整代码块 |
| FAQ | 每个问答对作为一个 chunk |
十六、Embedding 模型怎么选?中文场景选什么?
问题
你们用什么 Embedding 模型?为什么选它?
标准答案
选型看三个维度:语言支持、向量维度、检索效果。
中文场景主流模型
| 模型 | 维度 | 特点 |
|---|---|---|
| bge-large-zh-v1.5 | 1024 | 中文效果最好,开源,本地部署 |
| bge-m3 | 1024 | 多语言,支持稠密+稀疏+多向量三种检索 |
| text-embedding-3-large (OpenAI) | 3072 | 效果好但 API 调用有成本 |
| text-embedding-3-small (OpenAI) | 1536 | 便宜,英文场景首选 |
维度越高越好吗?
不是。维度高 → 表达能力强但存储和检索成本也高。1024 维是当前性价比最好的选择,3072 维效果提升有限但存储翻 3 倍。
面试答法
“中文场景选 bge-large-zh,因为 MTEB 中文榜单排名靠前,开源可本地部署。英文场景或对延迟不敏感,OpenAI 的 embedding 更方便。”
十七、LangChain 与 LangGraph 的关系是什么?
问题
LangChain 和 LangGraph 有什么区别?它们是怎么配合的?
标准答案
| 方面 | LangChain | LangGraph |
|---|---|---|
| 核心能力 | 封装单个 Agent 的能力 | 多 Agent 工作流编排 |
| 类比 | 造"干活的人"的模具 | 定"干活的规矩"的流水线 |
| 多 Agent 编排 | 勉强能,用嵌套,没有可视化 | 核心功能,支持分支/循环/并行 |
| 状态管理 | 简单链式传递 | 有向图 + StateGraph 状态机 |
简单说:LangChain 造 Agent,LangGraph 编排 Agent。
第二层:LangGraph 的核心定位
LangGraph 将智能体及其交互抽象为"图"(Graph),其中节点代表智能体或功能,边定义控制流和数据流。支持:
- 分支(condition-based routing)
- 循环(retry、iterative refinement)
- 汇合(多 Agent 写入共享状态)
- 条件路由(根据执行结果动态决定后续流程)
第三层:生产环境的典型分工
code复制
LangChain
├─ 定义 Agent(ReAct、Plan-and-Execute)
├─ 定义 Tools(搜索、数据库、API)
└─ 定义 Memory(对话历史、向量记忆)
LangGraph
├─ StateGraph 定义工作流拓扑
├─ Node 添加 Agent 节点
├─ Edge 定义流转逻辑
└─ Conditional Edge 实现分支决策
十八、LangGraph 如何编排多个 Agent?
问题
LangGraph 如何编排多个 Agent?比如 Agent A/B/C 怎么协作?
标准答案
用 LangGraph 可以像"画流程图"一样定义协作逻辑。核心是:将每个 Agent 作为 Node 加入 StateGraph,用 Edge 定义流转规则。
示例:智能数据分析助手
假设需要 3 个 Agent 协作:
- Agent A:判断问题类型(查数据?画图?写报告?)
- Agent B:数据查询 Agent
- Agent C:可视化 Agent
python复制
from langgraph.graph import StateGraph, END
workflow = StateGraph(AgentState)
# 添加 Agent 节点
workflow.add_node("classifier", agent_a) # 判断问题类型
workflow.add_node("query", agent_b) # 数据查询
workflow.add_node("visualize", agent_c) # 数据可视化
# 设置入口
workflow.set_entry_point("classifier")
# 条件路由:根据分类结果走不同分支
workflow.add_conditional_edges(
"classifier",
lambda state: state["question_type"],
{
"query": "query",
"visualize": "visualize",
"report": "report"
}
)
workflow.add_edge("query", END)
workflow.add_edge("visualize", END)
app = workflow.compile()
app.invoke({"question": "帮我查下本月销售额并画个柱状图"})
LangGraph 实现的编排能力
| 模式 | 说明 | 适用场景 |
|---|---|---|
| 顺序编排 | Agent A → Agent B → Agent C | 流水线处理 |
| 条件分支 | 不同结果走不同 Agent | 路由、分类 |
| 循环 | 条件不满足时重复执行 | 反思、重试 |
| 并行 | 多个 Agent 同时执行 | 多维度分析 |
| 汇合 | 多 Agent 结果合并 | 投票、汇总 |
多 Agent 架构模式
1. 监督者模式(Supervisor)
code复制
用户 → Supervisor Agent
├── Research Agent
├── Code Agent
└── QA Agent
2. 分层团队(Hierarchical Teams)
code复制
Team Leader
├── 子团队 A
│ ├── Agent A1
│ └── Agent A2
└── 子团队 B
├── Agent B1
└── Agent B2
3. 协作型多智能体 通过共享的消息暂存区通信,每个 Agent 能查看其他 Agent 的工作。
十九、什么是 Agentic RAG?和普通 RAG 有什么区别?
问题
你了解 Agentic RAG 吗?它和普通 RAG 有什么区别?
标准答案
普通 RAG 的局限
普通 RAG 是固定流程:用户问 → 检索一次 → 生成回答。如果第一次检索结果不好,不会自己纠正。
Agentic RAG:让 RAG 自己决定怎么检索
| 维度 | 普通 RAG | Agentic RAG |
|---|---|---|
| 检索次数 | 固定 1 次 | 动态,LLM 决定 |
| 检索策略 | 固定 pipeline | LLM 自主选择 |
| 结果不满意 | 直接生成 | 换策略重新检索 |
| 复杂问题 | 容易答偏 | 拆解子问题分步检索 |
| Token 消耗 | 低 | 高(多次推理) |
Agentic RAG 工作流程
code复制
用户问题 → Agent 规划:需要检索什么?
→ 第一次检索
→ Agent 判断:结果够不够?
→ 不够 → 换个 query 再检索
→ 够了 → 生成回答
面试核心判断力
Agentic RAG 适合复杂知识问答场景(法律、医疗、金融),简单问答用普通 RAG 就够了,别过度设计。
二十、RAG 检索效果不好怎么优化?
问题
你们 RAG 项目的检索准确率是多少?效果不好怎么优化的?
标准答案
从链路的每一步找问题:
优化思路
| 阶段 | 问题 | 优化方向 |
|---|---|---|
| 文档处理 | PDF 表格提取不准 | 专业表格提取工具 + OCR |
| Chunk | chunk_size 不合理 | 按文档类型调参,设置 overlap |
| 检索 | 纯向量召回差 | 混合检索 + Rerank |
| 生成 | 幻觉 | Prompt 约束 + 自校验 |
四种高级优化策略
1. Query 改写
code复制
原始问题:怎么调优?
改写后:RAG 系统中向量检索准确率低,有哪些优化方法?
2. 多路召回 同一问题用多种方式检索:原问题、改写问题、提取关键词、拆分子问题,最后合并。
3. Parent-Child 检索
- 检索时用小 chunk(精确匹配)
- 返回时用大 chunk(保留上下文)
- 每个小 chunk 关联一个父 chunk,命中后返回父 chunk 完整内容
4. 上下文窗口扩展 检索到一个 chunk 后,把它前后的 chunk 也带上。
面试加分
能说出实际用过的优化策略和量化效果,比如:
- “加了 Rerank 后 Top-5 召回率从 71% 提到 89%”
- “混合检索比纯向量在专业术语场景下准确率提升 25%”
附录:大厂真实面试追问汇总
检索策略类
Q:混合检索权重怎么调?向量和 BM25 各占多少? A:两种做法。一是手动调权重(向量 0.7 + BM25 0.3);二是用 RRF 合并,更稳健。生产环境推荐 RRF。
Q:Top-K 设多少?设大了设小了各有什么问题? A:设小了(K=3)可能漏掉相关文档;设大了(K=20)太多无关信息干扰。通常 K=5-10 是平衡点。
Q:用户问题很模糊,检索效果差,怎么办? A:Query 改写 + 多路召回 + Agent 追问确认。
工程落地类
Q:RAG 系统端到端延迟怎么优化? A:vLLM 推理、KV Cache 复用、流式输出、Prompt 压缩、HNSW 索引优化(50ms 以下)。
Q:文档更新了,向量索引怎么更新? A:全量重建(日级)、增量更新(实时)、双写(零停机切换)。
Q:Token 成本怎么控制? A:Prompt 压缩 + 上下文窗口管理 + 模型路由(简单问题用小模型)+ 缓存。
场景设计类
Q:设计一个面向 10 万用户的 RAG 知识库系统,怎么设计? A:从五个维度展开:
- 数据层:文档解析 → Chunk → Embedding → 向量库 + ES 双写
- 检索层:混合检索 + Rerank,Top-20 检索 + Top-5 精排
- 生成层:vLLM 部署 + Prompt 模板 + 幻觉约束
- 工程层:Redis 缓存、异步处理、监控
- 安全层:文档权限隔离、Prompt Injection 防御、敏感信息过滤
总结
本文整理了 20 道 LangChain/LangGraph/RAG 面试高频题,覆盖:
| 模块 | 题数 | 核心知识点 |
|---|---|---|
| LangGraph 核心 | 2 题 | Node/Edge/State、Conditional Edge |
| LangChain 基础 | 7 题 | 核心概念、LCEL、Agent、Memory、Chain 类型 |
| RAG 专题 | 6 题 | 完整链路、幻觉处理、混合检索、Rerank、Chunk、Embedding |
| LangGraph 编排 | 2 题 | LangChain vs LangGraph、多 Agent 协作 |
| 高级优化 | 3 题 | Agentic RAG、检索优化、大厂面试追问 |
每道题都包含标准答案、深入解析和常见追问,建议结合自己的项目经验,把"踩过的坑"变成面试加分项。
PS:本文八股皆为QClaw整合转载,并非本人自创,本人仅把控八股相关性与质量。
更多推荐
所有评论(0)