09 · LlamaIndex:从数据侧长出来的 Agent 框架
| 仓库 | run-llama/llama_index |
| Star | 51.7k(全专题第 3) |
| 版本 | llama-index 0.14.23 / llama-index-workflows 2.23.2 |
| 语言 | Python(TS 版) |
| 许可证 | MIT |
| 层级 | Framework(Workflows 兼具部分 Runtime 能力) |
| 一句话 | 别人从「怎么编排 LLM」出发,它从「怎么把你的数据喂给 LLM」出发 |
一、它的路线和 LangChain 是镜像的
同样 5 万+ star,同样什么都能做,但两者的起点完全相反:
现在官方对自己的描述已经变成 「the leading document agent and OCR platform」 —— 文档 Agent 和 OCR 平台。这个措辞很说明问题:它没打算在通用编排上和 LangChain 死磕,而是守住「非结构化数据 → 可用上下文」这条链路。
这条链路恰恰是绝大多数企业 Agent 项目 80% 的工作量所在。
二、核心编排抽象:Workflows(事件驱动)
这是 LlamaIndex 最值得单独学的设计。它不用「图 + 边」,而用 「事件 + 步骤」:
from llama_index.core.workflow import Workflow, step
from llama_index.core.workflow.events import Event, StartEvent, StopEvent
# 自定义事件:本质是个 Pydantic 模型,用来在步骤之间传数据
class ResultEvent(Event):
data: str
class MyWorkflow(Workflow):
@step # @step 标记这是工作流的一步
async def process(self, ev: StartEvent) -> ResultEvent:
# 入参类型 StartEvent = 「我接收工作流的启动事件」
# 返回类型 ResultEvent = 「我产出这种事件」
return ResultEvent(data="processed")
@step
async def finalize(self, ev: ResultEvent) -> StopEvent:
# 这一步声明接收 ResultEvent,框架据此自动把 process 连到 finalize,
# 你从头到尾没写过一条「边」—— 这就是事件驱动和图驱动的核心差别
return StopEvent(result=ev.data) # StopEvent 表示结束,result 是最终返回值
w = MyWorkflow(timeout=60) # timeout 是整个工作流的超时(秒)
result = await w.run(input_param="value") # 参数会挂在 StartEvent 上传进第一步
关键点:连线是靠类型注解推断出来的。 process 返回 ResultEvent,finalize 接收 ResultEvent —— 框架据此知道谁接谁,你从头到尾没写过一条「边」。
和 LangGraph 的对照
| LlamaIndex Workflows | LangGraph StateGraph | |
|---|---|---|
| 连接方式 | 事件类型驱动(类型注解推断) | 显式 add_edge / 条件边 |
| 状态 | ctx.store(每次运行共享字典) | TypedDict + Reducer |
| 分支 | 一个 step 返回不同事件类型 | 条件边函数返回节点名 |
| 并行 | ctx.send_event() 扇出,ctx.collect_events() 汇合 | 多条边 + Reducer 归并 |
| 校验 | 自动图校验(起止事件存在、无死路、事件都有消费者) | 编译期校验较弱 |
| 心智 | 像消息总线 | 像流程图 |
这套设计的最大优点是重构友好:加一个新步骤只要定义一个新事件类型,不用去改一堆边的声明。缺点是流程不直观 —— 想看清「执行顺序到底是什么」,得在脑子里把事件类型连起来。
流式与状态
# 注意这里没有 await:run() 立刻返回一个 handler,工作流在后台跑
handler = w.run(...)
# 边跑边收中间事件,可以用来做进度条、把思考过程实时推给前端
async for event in handler.stream_events():
process(event)
result = await handler # 最后 await handler 拿最终结果
Context 提供三样东西:ctx.send_event() 动态发事件、ctx.collect_events() 等待特定事件、ctx.store 跨步骤共享状态。
llama-index-workflows 现在版本号是 2.23.2,独立于 llama-index-core(0.14.x)演进,仓库在 run-llama/workflows-py。这意味着你可以只用 Workflows 编排引擎,不买 LlamaIndex 全家桶 —— 这是个被低估的用法。
三、Agent 抽象:四种预置 Agent
from llama_index.llms.openai import OpenAI
from llama_index.core.agent.workflow import FunctionAgent
agent = FunctionAgent( # 用模型原生 function calling 的 Agent
tools=[multiply, add], # 普通 Python 函数即可,会自动转成工具 schema
llm=OpenAI(model="gpt-4o-mini"),
system_prompt="You are an agent that can perform basic mathematical operations using tools.",
)
# 模型会自己拆成两步:先 multiply(2,4) 得到 8,再 add(20,8) 得到 28
response = await agent.run(user_msg="What is 20+(2*4)?")
# FunctionAgent 本身就是建在 Workflow 之上的,所以它也能 stream_events()
| Agent | 策略 | 适合 |
|---|---|---|
FunctionAgent | 原生 function calling | 默认选择 |
ReActAgent | ReAct 提示词范式 | 不支持 function calling 的模型 |
CodeActAgent | 生成并执行代码 | 数据分析、计算类任务(同 smolagents 思路) |
AgentWorkflow | 多 Agent 协作编排 | 多智能体 |
注意所有 Agent 都建在 Workflows 之上 —— 和 LangChain 的 create_agent 建在 LangGraph 上 是同构的分层。
四、真正的护城河:数据侧
如果只看编排能力,LlamaIndex 未必赢过别人。但下面这些东西,别的框架都得自己拼:
| 能力 | 说明 |
|---|---|
| LlamaParse | 复杂 PDF / 表格 / 扫描件解析,处理带合并单元格的财报、图文混排论文 |
| LlamaHub | 数百个数据连接器:Notion、Slack、Confluence、Jira、S3、各类数据库 |
| 多种 Index | Vector / Summary / Tree / Keyword / Knowledge Graph / Property Graph |
| 检索后处理 | Rerank、去重、元数据过滤、Auto-merging、Sentence-window |
| 查询变换 | HyDE、子问题拆解、多步查询、路由 |
| 评测 | Faithfulness、Relevancy、Correctness 等 RAG 专用指标 |
很多团队的 Agent 项目最后卡在「PDF 里的表格解析不出来」,而不是「Agent 编排不够灵活」。
这种时候,LlamaParse + 任意编排框架,往往比「更强的编排框架 + 手写解析」更快到达可用状态。 而且 LlamaIndex 的检索模块可以单独装、单独用,接到 LangGraph 或 OpenAI Agents SDK 里当工具 —— 这是个非常实用的混搭。
五、多智能体:AgentWorkflow
AgentWorkflow 支持多个 Agent 协 作,通过 handoff 转移控制权,共享一份 Context 状态。能力大致对标 OpenAI Agents SDK 的 handoff,比 LangGraph 的任意拓扑弱,但比 CrewAI 更程序化。
六、上生产
| 维度 | 情况 |
|---|---|
| 持久化 | Workflow Context 可序列化,支持中断恢复;但成熟度不及 LangGraph checkpointer |
| HITL | 通过事件机制实现(发出 InputRequiredEvent,外部回一个 HumanResponseEvent) |
| 部署 | 纯库,自己套 FastAPI;llama_deploy 提供服务化方案 |
| 可观测性 | 集成 Arize Phoenix、LangFuse、W&B 等,本身不自带 UI |
| 商业化 | LlamaCloud(托管解析 + 索引 + 检索),开源核心免费 |
依赖管理是它相对 LangChain 的一个优点:核心 llama-index-core 很薄,集成按需装(llama-index-llms-openai、llama-index-vector-stores-qdrant……)。
七、什么时候用 / 什么时候别用
用它,如果
- 项目主体是 RAG / 文档问答 / 知识库 —— 这是它的主场,检索链路的完成度最高
- 要处理复杂 PDF、扫描件、表格 —— LlamaParse 是很实在的差异化
- 数据源很杂 —— LlamaHub 连接器省掉大量胶水代码
- 喜欢事件驱动的编排心智 —— Workflows 的类型推断连线写起来很干净
- 只想要编排引擎 —— 单独装
llama-index-workflows,不买全家桶
别用它,如果
- 项目主体是复杂 Agent 编排 —— LangGraph 的持久化、HITL、时间旅行更成熟
- 需要一眼看清执行流程 —— 事件驱动的可读性不如显式图
- 要长时任务断点续跑 —— Context 序列化能用,但不如 checkpointer 体系完整
- 团队非 Python / TS —— 没有 Java / Go / .NET 实现
八、最实际的用法:混搭
本专题里我最推荐的一种组合:
框架不是非此即彼的。 「检索用 LlamaIndex,编排用别的」是很多生产系统的实际形态,两边都用各自最强的部分。
- 官方仓库:https://github.com/run-llama/llama_index
- 文档:https://developers.llamaindex.ai/
- Workflows:https://developers.llamaindex.ai/python/workflows/ · 独立仓库 https://github.com/run-llama/workflows-py
- LlamaParse / LlamaCloud:https://www.llamaindex.ai/
- 相关:RAG 面试题汇总