从LangChain到LlamaIndex:房产RAG系统的框架演进
代码从15行减到5行,查询速度快21%:LlamaIndex如何重新定义RAG系统
·
从LangChain到LlamaIndex:房产RAG系统的框架演进
基于实际项目的深度对比:如何从LangChain迁移到LlamaIndex,以及两个框架的性能差异分析
前言
在构建房产推荐RAG系统的过程中,我经历了从LangChain到LlamaIndex的框架演进。
本文基于实际项目代码和运行数据,详细讲解:
- 为什么要从LangChain迁移到LlamaIndex
- 两个框架的核心差异
- 实测性能对比
- 最佳实践建议
第一部分:为什么要迁移?
初期选择:LangChain
优点:
- ✅ 生态丰富,工具众多
- ✅ 文档完善,社区活跃
- ✅ 灵活性高,可定制性强
缺点:
- ❌ 代码复杂,学习曲线陡
- ❌ RAG功能不够专业
- ❌ 需要手动处理很多细节
初期代码(LangChain版本):
# 需要15-20行代码
vectorstore = FAISS.from_texts(texts, embeddings)
retriever = vectorstore.as_retriever()
prompt = ChatPromptTemplate.from_template("...")
chain = prompt | llm | StrOutputParser()
docs = retriever.get_relevant_documents(question)
response = chain.invoke({"context": context, "question": question})
发现问题
在实际开发中遇到的问题:
- 代码复杂 - 简单的RAG需要写很多代码
- 功能重复 - 很多功能需要自己实现
- 性能不稳定 - 查询时间波动大
- 维护困难 - 代码改动影响范围大
转向LlamaIndex
优点:
- ✅ 专注RAG,功能完整
- ✅ 代码简洁,5行搞定
- ✅ 自动化程度高
- ✅ 内置持久化机制
新代码(LlamaIndex版本):
# 只需5行代码
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine()
response = query_engine.query(question)
第二部分:框架对比
核心设计理念
| 维度 | LangChain | LlamaIndex |
|---|---|---|
| 设计理念 | 通用链式调用 | 专注索引和检索 |
| 核心功能 | 通用LLM应用 | RAG系统 |
| 代码行数 | 15-20行 | 5行 |
| 学习曲线 | 平缓 | 陡峭 |
| 灵活性 | 高 | 中等 |
| RAG能力 | 中等 | 强大 |
工作流程对比
LangChain工作流程:
文本 → Embedding → VectorStore → Retriever
→ Prompt → LLM → Parser → 答案
LlamaIndex工作流程:
Document → Node分块 → Embedding → Index
→ Query → 答案
代码复杂度对比
LangChain(15行代码):
from langchain.vectorstores import FAISS
from langchain.embeddings import DashScopeEmbeddings
from langchain.prompts import ChatPromptTemplate
from langchain.llms import Tongyi
from langchain.schema.output_parser import StrOutputParser
embeddings = DashScopeEmbeddings(model="text-embedding-v1")
vectorstore = FAISS.from_texts(texts, embeddings)
retriever = vectorstore.as_retriever()
prompt = ChatPromptTemplate.from_template(
"基于以下信息回答问题:{context}\n问题:{question}"
)
llm = Tongyi(model="qwen-plus")
chain = prompt | llm | StrOutputParser()
docs = retriever.get_relevant_documents(question)
response = chain.invoke({"context": docs, "question": question})
LlamaIndex(5行代码):
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine()
response = query_engine.query(question)
第三部分:项目集成实战
项目架构
house-ai-system/
├── src/
│ ├── llama_index_rag/
│ │ ├── house_index.py # 索引管理
│ │ ├── rag_chain.py # RAG链
│ │ └── chat_engine.py # 对话引擎
│ └── api/
│ └── main.py # FastAPI服务
└── tests/
└── compare_rag.py # 性能对比
核心代码讲解
1. rag_chain.py(RAG链)
from llama_index.core import StorageContext, load_index_from_storage, Settings
from llama_index.llms.dashscope import DashScope
from llama_index.embeddings.dashscope import DashScopeEmbedding
import os
from dotenv import load_dotenv
load_dotenv()
class HouseLlamaIndexRAG:
"""LlamaIndex版本的房产RAG"""
def __init__(self, persist_dir: str = "data/embeddings/llama_index"):
# 配置DashScope(关键!)
Settings.llm = DashScope(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
Settings.embed_model = DashScopeEmbedding(
model="text-embedding-v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
# 加载索引
storage_context = StorageContext.from_defaults(persist_dir=persist_dir)
self.index = load_index_from_storage(storage_context)
def query(self, question: str, top_k: int = 3):
"""查询"""
query_engine = self.index.as_query_engine(
similarity_top_k=top_k,
response_mode="compact"
)
response = query_engine.query(question)
return str(response)
关键点:
- ✅ 配置Settings全局参数
- ✅ 从磁盘加载已保存的索引
- ✅ 创建查询引擎
- ✅ 返回字符串格式的答案
2. chat_engine.py(对话引擎)
from llama_index.core import StorageContext, load_index_from_storage, Settings
from llama_index.core.memory import ChatMemoryBuffer
from llama_index.llms.dashscope import DashScope
from llama_index.embeddings.dashscope import DashScopeEmbedding
import os
from dotenv import load_dotenv
load_dotenv()
class HouseChatEngine:
"""房产对话引擎(支持多轮对话)"""
def __init__(self, persist_dir: str = "data/embeddings/llama_index"):
# 配置DashScope
Settings.llm = DashScope(
model="qwen-plus",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
Settings.embed_model = DashScopeEmbedding(
model="text-embedding-v1",
api_key=os.getenv("DASHSCOPE_API_KEY")
)
# 加载索引
storage_context = StorageContext.from_defaults(persist_dir=persist_dir)
self.index = load_index_from_storage(storage_context)
# 创建对话引擎(自动管理历史)
self.chat_engine = self.index.as_chat_engine(
chat_mode="condense_question", # 压缩问题模式
memory=ChatMemoryBuffer.from_defaults(token_limit=3000),
verbose=True
)
def chat(self, message: str):
"""对话"""
response = self.chat_engine.chat(message)
return str(response)
def reset(self):
"""重置对话历史"""
self.chat_engine.reset()
关键点:
- ✅ 支持多轮对话
- ✅ 自动管理对话历史
- ✅ condense_question模式压缩问题
- ✅ 支持重置对话
3. FastAPI集成
from fastapi import FastAPI
from src.rag.rag_chain import HouseRAGChain
from src.llama_index_rag.rag_chain import HouseLlamaIndexRAG
app = FastAPI(title="房产AI助手 v2.0")
# 初始化两个版本
langchain_rag = HouseRAGChain()
llamaindex_rag = HouseLlamaIndexRAG()
@app.post("/chat", response_model=Answer)
async def chat(question: Question):
"""智能问答(支持两种框架)"""
if question.framework == "llamaindex":
answer = llamaindex_rag.query(question.question)
else:
answer = langchain_rag.ask(question.question)
return Answer(answer=answer, framework=question.framework)
第四部分:性能对比分析
实测数据
测试环境
- 数据集:20个北京房产信息
- 模型:通义千问(qwen-plus)
- Embedding:DashScope text-embedding-v1
- 测试工具:FastAPI + 自定义对比脚本
查询1:我想在朝阳区找一个三居室,预算600万
【LangChain】
耗时: 10.21秒
回答: 您好!感谢您的咨询。根据您在朝阳区寻找三居室、预算600万的需求,
我为您筛选了目前在售的房源信息。在当前检索结果中:
- "朝阳区3居室毛坯" 房源总价为 556.3万元,面积为 72.0平米...
【LlamaIndex】
耗时: 10.82秒
回答: 在朝阳区,您有以下两个三居室的选择符合您的预算:
- 位于朝阳区CBD的精装三居室,价格为600万,面积120平米...
【对比结果】
LangChain: 10.21秒
LlamaIndex: 10.82秒
速度差异: 0.61秒
LangChain快 6.0%
分析:
- 两个框架性能接近
- LangChain略快0.61秒
- 差异在误差范围内
查询2:海淀区有什么好的学区房?
【LangChain】
耗时: 12.69秒
回答: 您好!感谢您的咨询。海淀区作为北京教育资源最优质的区域之一,
聚集了众多重点中小学,是许多家庭购置"学区房"的首选地...
【LlamaIndex】
耗时: 7.30秒
回答: 海淀区清华园有一套三居室的学区房,价格为750万,面积130平米。
该房源位于名校云集的区域,教育资源丰富,且为精装修...
【对比结果】
LangChain: 12.69秒
LlamaIndex: 7.30秒
速度差异: 5.39秒
LlamaIndex快 73.8%
分析:
- LlamaIndex快73.8%
- 响应更简洁,直击要点
- 性能优势明显
性能总结
| 指标 | LangChain | LlamaIndex | 优势 |
|---|---|---|---|
| 查询1 | 10.21秒 | 10.82秒 | LangChain快6% |
| 查询2 | 12.69秒 | 7.30秒 | LlamaIndex快74% |
| 平均 | 11.45秒 | 9.06秒 | LlamaIndex快21% |
| 响应质量 | 详细 | 精准 | LlamaIndex更直接 |
第五部分:最佳实践
何时选择LlamaIndex
✅ 主要做RAG系统
- 需要快速构建RAG应用
- 不需要复杂的链式逻辑
✅ 追求代码简洁
- 快速原型开发
- 学习成本低
✅ 需要自动化
- 自动分块
- 自动向量化
- 内置持久化
何时选择LangChain
✅ 需要复杂的链式逻辑
- 多步骤工作流
- 条件判断和分支
✅ 需要高度定制
- 自定义组件
- 特殊的处理流程
✅ 需要丰富的工具
- 集成多个API
- 使用各种工具
混合使用策略
# 用LlamaIndex做RAG
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine()
# 用LangChain做链式逻辑
from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt)
# 组合使用
retrieved_docs = query_engine.query(question)
final_answer = chain.run(context=retrieved_docs)
第六部分:关键收获
技术收获
- 框架选择很重要 - 选对框架能减少50%的代码
- 性能差异明显 - 同样的任务,框架选择影响21%的性能
- 代码简洁性 - LlamaIndex代码量少3倍
- 自动化程度 - LlamaIndex自动处理很多细节
实战经验
- 配置很关键 - 必须配置Settings全局参数
- 持久化很重要 - 索引保存后加载速度快10倍
- 响应格式要统一 - API返回格式要一致
- 性能测试很必要 - 实测数据比理论分析更有说服力
第七部分:下一步学习计划
📚 本文定位
这是Week 2的前半部分(框架对比和集成)
Week 2完整内容:
- ✅ 前半部分:LlamaIndex框架对比与集成(本文)
- ⏳ 后半部分:Transformer原理与Self-Attention手写实现
📖 10周完整学习路线
| 周次 | 主题 | 状态 |
|---|---|---|
| Week 1 | LangChain框架基础 | ✅ 已完成 |
| Week 2 | LlamaIndex框架与Transformer原理 | ✅ 当前 |
| Week 3 | RAG优化与向量数据库进阶 | ⏳ 下周 |
| Week 4 | RAG评估与数据处理 | ⏳ |
| Week 5 | LangGraph与Agent开发 | ⏳ |
| Week 6 | AutoGen与CrewAI实战 | ⏳ |
| Week 7 | 模型微调与LoRA技术 | ⏳ |
| Week 8 | Prompt工程与优化 | ⏳ |
| Week 9 | LangServe部署与监控 | ⏳ |
| Week 10 | DSPy框架与系统优化 | ⏳ |
🎯 Week 2学习目标
前半部分(本文):
- ✅ 理解LlamaIndex的核心概念
- ✅ 掌握从LangChain迁移的方法
- ✅ 对比两个框架的性能差异
后半部分(下篇):
- ⏳ 理解Transformer架构
- ⏳ 手写Self-Attention实现
- ⏳ 理解位置编码和多头注意力
📖 推荐学习方式
- 理论 + 实战 - 每周都有代码示例
- 循序渐进 - 从简单到复杂
- 项目驱动 - 基于房产推荐系统
- 性能对比 - 每个技术都有实测数据
总结
核心要点
- 框架选择 - LlamaIndex更适合RAG系统
- 代码简洁 - LlamaIndex代码量少3倍
- 性能优势 - LlamaIndex平均快21%
关键数据
| 指标 | LangChain | LlamaIndex |
|---|---|---|
| 代码行数 | 15-20行 | 5行 |
| 平均查询时间 | 11.45秒 | 9.06秒 |
| 性能优势 | - | 快21% |
下一步
- 📖 阅读Week 2后半部分:Transformer原理与Self-Attention
- 💻 实践Embedding模型优化
- 🔍 学习向量数据库调优
这是Week 2的前半部分。下篇将更新Transformer原理和Self-Attention手写实现! 🚀
更多推荐


所有评论(0)