从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})

发现问题

在实际开发中遇到的问题:

  1. 代码复杂 - 简单的RAG需要写很多代码
  2. 功能重复 - 很多功能需要自己实现
  3. 性能不稳定 - 查询时间波动大
  4. 维护困难 - 代码改动影响范围大

转向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)

第六部分:关键收获

技术收获

  1. 框架选择很重要 - 选对框架能减少50%的代码
  2. 性能差异明显 - 同样的任务,框架选择影响21%的性能
  3. 代码简洁性 - LlamaIndex代码量少3倍
  4. 自动化程度 - LlamaIndex自动处理很多细节

实战经验

  1. 配置很关键 - 必须配置Settings全局参数
  2. 持久化很重要 - 索引保存后加载速度快10倍
  3. 响应格式要统一 - API返回格式要一致
  4. 性能测试很必要 - 实测数据比理论分析更有说服力

第七部分:下一步学习计划

📚 本文定位

这是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实现
  • ⏳ 理解位置编码和多头注意力

📖 推荐学习方式

  1. 理论 + 实战 - 每周都有代码示例
  2. 循序渐进 - 从简单到复杂
  3. 项目驱动 - 基于房产推荐系统
  4. 性能对比 - 每个技术都有实测数据

总结

核心要点

  1. 框架选择 - LlamaIndex更适合RAG系统
  2. 代码简洁 - LlamaIndex代码量少3倍
  3. 性能优势 - LlamaIndex平均快21%

关键数据

指标 LangChain LlamaIndex
代码行数 15-20行 5行
平均查询时间 11.45秒 9.06秒
性能优势 - 快21%

下一步

  • 📖 阅读Week 2后半部分:Transformer原理与Self-Attention
  • 💻 实践Embedding模型优化
  • 🔍 学习向量数据库调优

这是Week 2的前半部分。下篇将更新Transformer原理和Self-Attention手写实现! 🚀

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐