LlamaIndex
如果说 LangGraph 更像“状态流与工作流编排框架”,那 LlamaIndex 更像:
围绕知识和文档组织展开的框架。
它特别适合的不是“多角色协作”本身,而是:
- 文档进来以后怎么整理
- 怎么切块
- 怎么索引
- 怎么检索
- 怎么变成问答入口
学习目标
- 理解 LlamaIndex 的核心抽象对象
- 理解它为什么特别适合知识和文档场景
- 看懂 Document -> Node -> Index -> Retriever -> Query Engine 这条 链
- 建立什么时候该优先考虑 LlamaIndex 的判断
一、为什么很多 LLM 项目其实首先是“知识系统项目”?
1.1 不是所有系统都在解决对话问题
很多真实 LLM 应用的核心,其实不是聊天,而是:
- 企业知识库问答
- 文档检索
- 研究资料整合
- 报告辅助生成
这些任务的共同点是:
知识本身的组织方式,直接决定系统质量。
1.2 这正是 LlamaIndex 最有价值的地方
它不是只问“怎么调模型”,而是在问:
- 文档怎么进系统
- 信息怎么切分
- 检索结构怎么搭
- 查询怎么组织
所以一个非常实用的理解是:
LlamaIndex 更像知识系统框架,而不是纯工作流框架。
二、先把几个最重要的概念分清
2.1 Document
最原始的知识单元。
例如:
- 一篇文章
- 一份 PDF
- 一段网页内容
2.2 Node
Document 被切分后的更小单位。
在很多知识系统里,真正拿去做检索的往往不是整篇文档,而是更细粒度的 node。
2.3 Index
把这些 node 组织成可查询结构的方式。
2.4 Retriever
负责根据用户查询,把相关 node 找回来。
2.5 Query Engine
把“查询 -> 检索 -> 组织结果”整成更完整的一层。
一句话先记:
文档是原料,节点是切好的原料,索引是仓储结构,检索器负责找货,查询引擎负责把货拿出来给用户。
三、先用纯 Python 走一遍这条链
3.1 文档 -> 节点
documents = [
{"id": "doc1", "text": "课程购买后 7 天内且学习进度低于 20% 可退款。"},
{"id": "doc2", "text": "完成所有项目并通过测试后可获得证书。"}
]
nodes = []
for doc in documents:
nodes.append({
"doc_id": doc["id"],
"text": doc["text"]
})
print(nodes)
这个例子虽然简单,但已经表达了一个核心思想:
原始文档通常不会直接拿来问答,而是先变成更适合索引和检索的知识单元。
四、为什么“文档摄取”是知识系统的第一步?
4.1 原始文档通常很脏
真实文档可能包含:
- 页眉页脚
- 重复段落
- 表格噪声
- 很长的大段落
如果不先处理好,后面的检索往往会一起变差。
4.2 所以知识系统最常见的第一步不是“调模型”
而是:
- 读文档
- 清洗
- 切分
- 加元数据
这就是为什么 LlamaIndex 这种框架会特别强调 ingest。
五、索引和检索为什么是它的中心?
5.1 因为知识应用最怕“文档在那,但系统找不到”
如果:
- 文档很多
- 节点很多
- 问题表达很灵活
那没有好的索引和检索层,后面模型再强也会被拖累。
5.2 一个最小检索示例
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
node_texts = [node["text"] for node in nodes]
vectorizer = TfidfVectorizer(token_pattern=r"(?u)\\b\\w+\\b")
index_matrix = vectorizer.fit_transform(node_texts)
def retrieve(query):
query_vec = vectorizer.transform([query])
scores = cosine_similarity(query_vec, index_matrix)[0]
best_idx = scores.argmax()
return nodes[best_idx]
print(retrieve("退款政策是什么"))
5.3 这段代码真正对应的抽象是什么?
它其实已经对应到:
- node
- index
- retriever
也就是说,LlamaIndex 的很多价值,本质上都是在把这条知识链组织得更系统。
六、Query Engine 为什么值得单独抽出来?
6.1 因为问答不只等于“返回一个最像的段落”
实际系统里,你通常还要决定:
- 返回几条
- 是否要汇总
- 是否要带来源
- 是否要进一步调用模型
这时“查询引擎”就比“单个 retriever”更像一个系统层抽象。
6.2 一个极简 Query Engine 示例
def query_engine(query):
node = retrieve(query)
return {
"answer": node["text"],
"source": node["doc_id"]
}
print(query_engine("退款政策是什么"))
这个例子在教你:
检索只是中间层,最终还需要有一层把结果组织成面向用户的查询接口。
七、LlamaIndex 和 LangGraph 的差别,最核心的一句是什么?
如果要非常粗暴地总结,可以记成:
- LangGraph 更偏“任务状态怎么流”
- LlamaIndex 更偏“知识怎么组织”
当然现实里可以混搭,但它们的第一关注点确实不同。
所以如果你的项目本质上是:
- 文档问答
- 知识库助手
- RAG 主线
那么 LlamaIndex 这类抽象通常就会更顺手。
八、什么时候 LlamaIndex 不一定是重点?
如果你的系统更偏:
- 多 Agent 协作
- 复杂回路
- 显式状态机
那 LlamaIndex 可能就不是“主框架”,而更像知识层组件。
所以不要把它看成“万能 Agent 框架”,而要看成:
在知识和检索问题上特别顺手的一种框架。
九、初学者最常踩的坑
9.1 只看模型,不看文档摄取
很多知识系统问题,其实都出在文档入口。
9.2 觉得索引做好了就等于问答系统完成了
索引只是中间层,不是产品终点。
9.3 不知道它和工作流型框架的边界
这样很容易期待它去解决并不属于它最强项的问题。
小结
这一节最重要的不是记住 LlamaIndex 的接口,而是理解:
LlamaIndex 的价值,在于把文档知识从原始文本一路组织成可检索、可引用、可查询的结构。
一旦你把它看成“知识组织框架”而不是“万能框架”,很多判断就会清楚很多。
练习
- 用自己的话解释 Document、Node、Index、Retriever、Query Engine 各自像什么。
- 想一想:为什么说文档摄取质量会直接影响后面的检索效果?
- 用自己的知识库数据再造 3 条节点,重新跑一遍检索示例。
- 说明:如果系统主线是多 Agent 协作而不是知识检索,为什么 LlamaIndex 不一定应该做“总框架”?