LangChain 与 LlamaIndex
难度:⭐⭐ | 高频指数:🔥🔥🔥 | 应用岗相关度:★★★
面试回答
常见问法
- LangChain 和 LlamaIndex 各自定位是什么,怎么选?
- 你们项目里用了框架吗?踩过哪些坑?
- 为什么很多团队用着用着就开始”去框架化”?
- LangChain 的 Chain / Agent / Tool 这套抽象在生产上有什么问题?
- LlamaIndex 在 RAG 场景上比 LangChain 强在哪?
- 如果让你重新搭一套,会基于哪个框架,还是直接裸写?
回答
两者都是 LLM 应用层框架,但定位不一样。
LangChain 是通用编排框架,覆盖 Prompt、Chain、Agent、Tool、Memory、Callback 这一整套,目标是任何 LLM 应用都能搭起来。 LlamaIndex 是 RAG 专用框架,从一开始就围绕”数据接入 + 索引 + 检索”做深,对文档解析、Chunk 策略、检索器组合更专业。
工程上的关键认知是:框架的价值集中在原型阶段。一周内出第一版能跑的应用,框架能省下大量样板代码;但一旦上了线,开始追性能、追可调试、追定制化,框架的抽象层会逐步变成阻碍——这也是为什么很多团队最终都走向”框架灵感 + 自研落地”的混合形态。
面试时要表现出的判断力是:会用框架不等于理解系统,框架能屏蔽掉的复杂度才是面试官想问的部分。
追问
- Chain 和 Agent 的区别是什么?什么场景该用哪个?
- LlamaIndex 的 Node / Index / Retriever 三层抽象怎么对应到 RAG 流程?
- 框架的 Callback / Trace 机制为什么在线上经常不够用?
- 流式输出(streaming)在两个框架里支持得怎么样?
- 如果要把 LangChain Agent 替换成自研 Loop,最难的部分是什么?
- 你怎么评估”该不该上框架”这个决策?
原理展开
1. 两个框架的出身和定位
LangChain 起步早(2022 年底),赶上了 ChatGPT 爆发,定位就是”LLM 应用的瑞士军刀”,目标覆盖所有场景——Prompt 拼装、链式调用、工具调用、Agent、Memory、Eval、Callback 全做。
LlamaIndex 几乎同期出现(最初叫 GPT Index),定位窄得多:就是要把企业里那些 PDF、Confluence、Notion、数据库内容接入 LLM。围绕这一件事做深,所以它的强项是文档解析器、分层索引、检索器组合、Query Engine。
两边后来都在扩——LangChain 补 RAG,LlamaIndex 补 Agent——但底子和品味是不一样的:LangChain 偏”通用抽象”,LlamaIndex 偏”垂直深度”。
2. LangChain 的核心抽象
# 典型 LangChain 链路
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain.agents import initialize_agent, Tool
prompt = PromptTemplate.from_template("回答问题:{q}")
chain = LLMChain(llm=llm, prompt=prompt)
agent = initialize_agent(
tools=[Tool(name="search", func=web_search, description="...")],
llm=llm,
agent="zero-shot-react-description",
)
几个关键概念:
- Chain:把多个调用串成流水线,输入输出契约固定
- Agent:让 LLM 自己决定下一步调什么 Tool,循环到结束条件
- Tool:可被 Agent 调用的外部能力,统一接口
- Memory:把历史对话或中间状态持久化在 Chain 里
- Callback:在 Chain/Agent 各生命周期点注入观测和钩子
设计上偏 OOP,模块层数多,每一层都做了通用抽象。上手快,但深入定制时常常要继承重写。
3. LlamaIndex 的核心抽象
# 典型 LlamaIndex RAG
from llama_index import VectorStoreIndex, SimpleDirectoryReader
docs = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine(similarity_top_k=5)
response = query_engine.query("公司的差旅报销政策是什么?")
围绕 RAG 三层抽象:
- Node:文档切片后的最小检索单元,带 metadata
- Index:组织 Node 的结构,可以是向量索引、关键词索引、树索引、知识图谱索引
- Retriever / QueryEngine:检索 + 生成的组合
它的强项不在于这套抽象本身——抽象其实跟自己写 RAG 没差太多——而在于周边生态:100+ 文档解析器、20+ 索引类型、各种高级检索策略(HyDE、子查询、路由)开箱即用。
4. 两个框架重合的部分和差异
| 维度 | LangChain | LlamaIndex |
|---|---|---|
| Agent / Tool | 完整生态,是核心卖点 | 后来补的,相对薄 |
| RAG | 有,但抽象偏底层 | 核心场景,封装最深 |
| 文档解析 | 接第三方为主 | 自家 LlamaParse 是头部 |
| Prompt 管理 | 模板 + Hub | 较弱 |
| Memory | 多种实现(buffer / summary / vector) | 偏简单 |
| Callback / 观测 | 自带 + LangSmith | 自带 + 接 Phoenix / OpenTelemetry |
| 抽象厚度 | 厚(学习曲线陡) | 薄 + 垂直深 |
简单记:Agent / 通用编排选 LangChain,纯 RAG 选 LlamaIndex,两者都能搭,但各自最舒服的赛道不一样。
5. 为什么团队用着用着会”去框架化”
这个问题面试很爱问,因为能看出实战深度。常见原因有三类:
调试链路太深。 框架把多层 wrap 套起来后,一个 Prompt 真正发给模型时长什么样、Tool 调用为什么没触发、为什么 retry 了三次——经常要打开框架源码翻三四层才能看清。Trace 工具能缓解一部分,但本质上还是抽象成本。
定制困难。 比如想给 Agent 加一个”调用前先做 PII 脱敏”的钩子,框架的 Callback 接口可能不够灵活;想换一个奇怪的 Tool 调用协议,可能要重写一整个 Agent 类型。框架抽象总是基于”大家都这么做”的假设,业务一旦稍微偏,就要逆着抽象走。
性能边角料藏太深。 重试策略、batch、流式合并、token 用量统计、并行调用,框架的实现可能不是你团队需要的形态。一旦要严格控成本或控延迟,自己写一遍反而清爽。
6. 框架抽象的代价
抽象不是免费的,代价主要有:
- 理解成本:要先理解框架的”心智模型”才能写出符合它的代码
- 隐藏调用链:一行代码背后可能跑了 5 次 LLM 调用 + 3 次重试
- 版本不稳定:LangChain 在 0.x → 1.x 阶段反复破坏式升级,迁移痛苦
- 性能上限:框架内部的串行/同步实现,要并行化经常得自己绕
- 定制粒度:钩子点有限,要插入业务逻辑往往得继承重写
工程上的判断标准是:如果框架抽象帮你省的代码 < 它带来的理解和定制成本,就该考虑去框架化。
7. 选型时怎么判断
按”项目阶段 × 团队规模 × 定制需求”三个维度判断:
原型 / 小团队 / 定制少 → 直接上框架,能跑就行
PoC 转生产 / 性能敏感 → 框架做底层,关键链路改写
长期项目 / 大团队 / 重定制 → 拆框架,留概念不留代码
实战里我倾向于:
- 第一周用框架快速跑通,验证业务流程
- 进入第二迭代时识别热点链路(最高频、最难调试、最性能敏感的那部分)
- 把热点链路下沉成自研代码,框架只在边缘场景保留
8. “半自研”通常长什么样
很多团队最后落地的形态是这样的:
- Prompt 管理:自己写 template + 版本管理,不用框架 PromptTemplate
- LLM 调用层:直接调 OpenAI / Anthropic / vLLM SDK,自己加重试、限流、缓存、token 统计
- RAG 检索层:参考 LlamaIndex 的设计,但用自己的 Retriever 接口,方便定制
- Agent Loop:自己写一个 30 行的 while 循环,比框架 Agent 简单且可控
- Trace:直接接 OpenTelemetry / LangFuse,不依赖框架自带 callback
保留的是设计灵感,丢掉的是抽象层。 这套做法的代价是初期慢,收益是后期可控、可调试、可演进。
对比总结
| 场景 | 推荐 |
|---|---|
| 一周内出 demo / 内部工具 | LangChain(最全) |
| 企业知识库 / 文档问答 | LlamaIndex |
| 复杂 Agent + 多工具 | LangChain(Agent 生态强) |
| 长期生产系统 | 半自研(参考两者设计,自己写) |
| 学习 RAG 各种模式 | LlamaIndex(实现最干净) |
| 学习 Agent 模式 | LangChain(样例最多) |
易错点
- 把”会用框架”等同于”理解 LLM 系统”——面试官真正想问的是抽象背后的机制
- 混淆 Chain 和 Agent——Chain 是固定流水线,Agent 是 LLM 自己决策下一步
- 以为 LlamaIndex 只能做 RAG——它现在也能做 Agent,只是不是主战场
- 不区分原型阶段和生产阶段——框架在两个阶段的 ROI 完全不同
- 过度信任框架的默认实现——比如 LangChain 默认重试、默认 Chunk 大小、默认 prompt 都不一定适合你的场景
- 小看版本升级成本——LangChain 历史上多次破坏式升级,绑死大版本要慎重
记忆技巧
记三组锚点就够:
- 定位差异:LangChain = 通用编排 / Agent 强;LlamaIndex = RAG 垂直 / 文档解析强
- 核心抽象:LangChain = Chain / Agent / Tool;LlamaIndex = Node / Index / Retriever
- 生产去化:原型上、生产下;保留设计,丢掉抽象
面试速答版
LangChain 和 LlamaIndex 都是 LLM 应用层框架,但定位不同——LangChain 偏通用编排,覆盖 Chain、Agent、Tool、Memory 全栈;LlamaIndex 围绕 RAG 做深,强项是文档接入、索引、检索器组合。
工程上,框架的价值集中在原型阶段,能快速出第一版;但生产系统里抽象会变成阻碍——调试链路深、定制困难、性能边角料藏太深,所以很多团队最后都走向”借鉴框架设计 + 自研关键链路”的形态。
选型判断:原型期用框架,生产期看团队和定制需求,热点链路尽量自己掌控。
面试加分版
如果想多讲一层,可以补:
- 观测能力是框架真正的护城河:LangSmith / LlamaIndex Observability 提供的 Trace 体验,比自己接 OTel 要省事很多——这是即使去框架化也很难放弃的部分
- 抽象的代价随业务复杂度非线性增长:简单场景框架是减法,复杂场景框架是加法
- 框架的最大风险是”看起来好像懂了”——能跑通不等于知道为什么跑通,面试时被追问内部机制经常露馅