2025 年 Python AI 框架横评——LangChain、LlamaIndex、Haystack 怎么选
2025 年 Python AI 框架横评——LangChain、LlamaIndex、Haystack 怎么选
适读人群:Python AI 应用开发者 | 阅读时长:约 13 分钟 | 核心价值:三个框架的真实工程体验对比,有明确推荐
2023 年初我刚开始做 AI 应用,第一个项目用的 LangChain,因为那时候几乎所有教程都在讲它。项目上线后,我花在调试框架本身上的时间比调试业务逻辑还多。
后来换了 LlamaIndex,再后来某个项目试了 Haystack。现在这三个框架我都用过真实的生产项目,可以说点不带广告味道的话了。
这篇文章不是功能清单比较,GitHub star 数、支持的 LLM 数量那些你自己去看文档。我说的是工程师真正关心的事:学习成本多高、出了问题好不好调、放到生产里稳不稳。
LangChain:功能最多,也最让我抓狂
真实体验
LangChain 是这三个里出现最早、知名度最高的,但我对它的感情最复杂。
它的问题不是功能不够,恰恰相反——它功能太多了,而且组织方式让人困惑。
拿最简单的 RAG pipeline 举例。在 LangChain 里,你需要理解 Document、DocumentLoader、TextSplitter、Embeddings、VectorStore、Retriever、Chain 这一堆概念,还要知道 LangChain Expression Language (LCEL) 的 | 管道语法。每一层抽象都有自己的配置方式,出了问题你不确定是哪一层的问题。
# LangChain LCEL 风格的 RAG(官方推荐写法)
from langchain_community.vectorstores import Qdrant
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
embeddings = OpenAIEmbeddings()
vectorstore = Qdrant.from_existing_collection(
embedding=embeddings,
collection_name="documents",
url="http://localhost:6333"
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
prompt = ChatPromptTemplate.from_template("""
基于以下上下文回答问题:
{context}
问题:{question}
""")
llm = ChatOpenAI(model="gpt-4o")
# LCEL 管道语法
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
response = chain.invoke("什么是向量数据库?")代码看起来优雅,但出了问题你会发现 debug 起来很难受。retriever 在管道里是什么类型?{"context": retriever, "question": RunnablePassthrough()} 这个字典是怎么被执行的?Stack trace 会告诉你一堆 LangChain 内部的类名,和你的业务代码隔着好几层。
版本稳定性是噩梦
这是我对 LangChain 最大的抱怨。它的更新频率极高,但 breaking change 也很频繁。
一个真实案例:我在 2023 年底写的代码,到 2024 年中升级版本时,LLMChain 被废弃了,推荐用 LCEL 重写;ConversationalRetrievalChain 也被废弃了;部分 community 集成被移到单独的包里,import 路径全变了。
一次 pip install -U langchain 可能直接让你的代码跑不起来。
# 这些在不同版本 LangChain 里都是"正确"的写法,但互不兼容
# v0.0.x 时代(已废弃)
from langchain.chains import LLMChain
from langchain.chat_models import ChatOpenAI
# v0.1.x 时代(已废弃)
from langchain_community.chat_models import ChatOpenAI
# v0.2.x+ 时代
from langchain_openai import ChatOpenAI如果你要用 LangChain,要么锁死版本,要么接受定期重写的代价。
LangChain 的真正价值
说了这么多批评,LangChain 也有它不可替代的地方:生态最丰富。
各种外部工具的集成(数据库、API、第三方服务)、各种向量存储的适配器、各种 LLM 的统一接口——这方面它是目前最完整的。如果你需要快速验证一个 POC,需要连接各种奇奇怪怪的数据源,LangChain 能帮你省很多接入时间。
LlamaIndex:RAG 场景的最佳工程体验
为什么我现在首选它
LlamaIndex 一开始叫 GPT Index,专注做数据和 LLM 的连接,特别是 RAG 相关的场景。它的抽象层次比 LangChain 更清晰,代码的可读性更好。
# LlamaIndex 的 RAG pipeline,逻辑更直观
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.vector_stores.qdrant import QdrantVectorStore
import qdrant_client
# 配置全局设置(比 LangChain 的链式配置更集中)
Settings.llm = OpenAI(model="gpt-4o")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Settings.chunk_size = 512
Settings.chunk_overlap = 50
# 连接向量存储
qclient = qdrant_client.QdrantClient(host="localhost", port=6333)
vector_store = QdrantVectorStore(client=qclient, collection_name="documents")
# 加载文档并建索引
documents = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(
documents,
vector_store=vector_store
)
# 查询
query_engine = index.as_query_engine(similarity_top_k=5)
response = query_engine.query("什么是向量数据库?")
print(response.response)
# LlamaIndex 的一个优点:可以方便地看检索到的来源
for node in response.source_nodes:
print(f"来源: {node.metadata.get('file_name')}, 相似度: {node.score:.3f}")关键优势: 源文档引用是一等公民。每次查询都能方便地获取检索到的原始文档块和相似度分数,这对于构建可解释的 RAG 系统非常重要。
高级 RAG 功能
LlamaIndex 在复杂 RAG 模式上的支持比 LangChain 更成熟:
# 混合检索:向量搜索 + 关键词搜索
from llama_index.core.retrievers import VectorIndexRetriever
from llama_index.retrievers.bm25 import BM25Retriever
from llama_index.core.retrievers import QueryFusionRetriever
vector_retriever = VectorIndexRetriever(index=index, similarity_top_k=5)
bm25_retriever = BM25Retriever.from_defaults(index=index, similarity_top_k=5)
# 融合检索器,自动去重和重排
hybrid_retriever = QueryFusionRetriever(
[vector_retriever, bm25_retriever],
similarity_top_k=5,
num_queries=1, # 不扩展查询
mode="reciprocal_rerank", # 倒数排名融合
)
# 子问题分解(复杂问题拆成子问题分别检索)
from llama_index.core.query_engine import SubQuestionQueryEngine
from llama_index.core.tools import QueryEngineTool
# 可以针对不同数据源分别建索引,然后用 SubQuestion 路由学习曲线
LlamaIndex 的概念比 LangChain 少,文档质量更稳定,新版本的 breaking change 更克制。从零开始学,LlamaIndex 大概需要 1 周能上手写生产代码,LangChain 要 2-3 周才能搞清楚各种概念之间的关系。
Haystack:被低估的工业级框架
什么是 Haystack
Haystack 是 deepset(一家德国 AI 公司)维护的框架,在中文社区知名度不高,但在欧洲企业里用得挺多。
它的核心设计思路是 Pipeline + Component:一个 Pipeline 由多个 Component 组成,每个 Component 有明确的 input 和 output 类型,整个 Pipeline 是类型安全的有向图。
# Haystack v2 的 Pipeline 设计,类型检查很严格
from haystack import Pipeline
from haystack.components.embedders import OpenAITextEmbedder, OpenAIDocumentEmbedder
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
from haystack.components.builders import PromptBuilder
from haystack.components.generators import OpenAIGenerator
from haystack.document_stores.in_memory import InMemoryDocumentStore
document_store = InMemoryDocumentStore()
# 索引 Pipeline
indexing_pipeline = Pipeline()
indexing_pipeline.add_component("embedder", OpenAIDocumentEmbedder())
indexing_pipeline.add_component("writer", DocumentWriter(document_store))
indexing_pipeline.connect("embedder.documents", "writer.documents")
# 查询 Pipeline
query_pipeline = Pipeline()
query_pipeline.add_component("embedder", OpenAITextEmbedder())
query_pipeline.add_component("retriever", InMemoryEmbeddingRetriever(document_store))
query_pipeline.add_component("prompt_builder", PromptBuilder(
template="""
基于以下文档回答问题:
{% for doc in documents %}
{{ doc.content }}
{% endfor %}
问题:{{ question }}
"""
))
query_pipeline.add_component("llm", OpenAIGenerator(model="gpt-4o"))
# 连接组件
query_pipeline.connect("embedder.embedding", "retriever.query_embedding")
query_pipeline.connect("retriever.documents", "prompt_builder.documents")
query_pipeline.connect("prompt_builder.prompt", "llm.prompt")
result = query_pipeline.run({
"embedder": {"text": "什么是向量数据库?"},
"prompt_builder": {"question": "什么是向量数据库?"}
})Haystack 的优势
类型安全:Pipeline 连接有类型检查,connect("embedder.embedding", "retriever.query_embedding") 如果类型不匹配,在 Pipeline 构建时就会报错,不是在运行时才发现。
可视化:可以把 Pipeline 导出为图,方便沟通和审查:
pipeline.show() # Jupyter 里直接展示
pipeline.draw("pipeline.png")生产稳定性:Haystack 的版本更新比 LangChain 克制得多,v2 的 API 设计很稳定,我在生产项目里跑了半年没有因为框架升级出过问题。
Haystack 的缺点
生态比 LangChain 小很多。一些比较冷门的向量数据库、LLM 提供商可能没有官方集成,要自己写 Component。对 Agent 场景的支持相对较弱,不如 LangChain 丰富。
选型建议
| 场景 | 推荐 |
|---|---|
| RAG 应用,需要快速迭代 | LlamaIndex |
| 企业级,需要类型安全和可维护性 | Haystack |
| 需要连接大量第三方系统 | LangChain |
| Agent 应用 | LangChain(或直接用 Anthropic/OpenAI SDK) |
| 初学者入门 | LlamaIndex |
我的实际选择:
- 新 RAG 项目:LlamaIndex,首选
- 需要复杂 Pipeline 可视化的企业项目:Haystack
- 需要快速接入某个特殊数据源或工具,只有 LangChain 有集成:用 LangChain 那个集成,但尽量不依赖 LangChain 的 Chain/Agent 抽象
一个不那么主流的建议:很多场景根本不需要框架。直接用 Anthropic SDK 或 OpenAI SDK + 向量数据库客户端,代码更透明,bug 更容易定位。框架的价值在于它帮你省了接入层的重复劳动,但如果你的场景不复杂,自己写几百行代码比用框架更省心。
