Python + LangChain + LlamaIndex 构建 RAG 知识库

内容分享19小时前发布
0 0 0

RAG(检索增强生成)是解决大模型知识时效性、领域专业性问题的核心方案,LangChain 擅长流程编排、LlamaIndex 专精数据索引与检索,二者结合能高效构建企业级 RAG 知识库。本文从环境搭建、数据加载、索引构建、检索增强到生成回答,完整讲解落地流程。

Python + LangChain + LlamaIndex 构建 RAG 知识库

一、核心概念与技术栈说明

第一安装核心依赖包,提议使用Python 3.9 + 版本:

# 核心依赖
pip install langchain langchain-community langchain-openai llama-index chromadb python-dotenv
# 文档解析依赖(按需安装)
pip install pypdf python-docx markdown2  # 支持PDF/Word/Markdown
# 可选:中文分词增强(针对中文场景)
pip install jieba

二、基础配置(密钥与模型初始化)

创建.env文件配置敏感信息,避免硬编码:

# OpenAI密钥(替换为自己的)
OPENAI_API_KEY=your-openai-api-key
# 可选:如果使用国内代理(如OpenAI接口代理)
OPENAI_BASE_URL=https://api.openai-proxy.com/v1

初始化大模型、Embedding模型(向量编码):

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from llama_index.core import Settings

# 加载环境变量
load_dotenv()

# 1. 配置LangChain大模型
llm_langchain = ChatOpenAI(
    model_name="gpt-3.5-turbo",
    temperature=0.1,  # 越低回答越精准
    api_key=os.getenv("OPENAI_API_KEY"),
    base_url=os.getenv("OPENAI_BASE_URL")
)

# 2. 配置LlamaIndex全局设置(复用LangChain的Embedding/LLM)
Settings.llm = llm_langchain
Settings.embed_model = OpenAIEmbeddings(
    api_key=os.getenv("OPENAI_API_KEY"),
    base_url=os.getenv("OPENAI_BASE_URL")
)
Settings.chunk_size = 512  # 文本分块大小(中文提议512-1024)
Settings.chunk_overlap = 50  # 分块重叠长度(避免上下文断裂)

Python + LangChain + LlamaIndex 构建 RAG 知识库

三、数据加载与预处理(LlamaIndex核心)

LlamaIndex提供丰富的Reader类,支持本地文档、网页、数据库等数据源,这里以本地文档(PDF/Word/Markdown)为例:

1. 加载多类型文档

from llama_index.core import SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter

# 1. 加载指定目录下的所有文档(自动识别PDF/Word/MD等)
# 文档存放路径:./docs(需提前创建,放入测试文档)
reader = SimpleDirectoryReader(
    input_dir="./docs",
    recursive=True,  # 递归读取子目录
    required_exts=[".pdf", ".docx", ".md"],  # 仅加载指定格式
)
documents = reader.load_data()
print(f"加载文档数量:{len(documents)}")

# 2. 文本分块(核心步骤:解决大模型上下文限制)
parser = SentenceSplitter(
    chunk_size=Settings.chunk_size,
    chunk_overlap=Settings.chunk_overlap,
    # 中文分词增强(可选)
    separator="。!?;,
",
)
# 将文档切分为Node(LlamaIndex的基础数据单元)
nodes = parser.get_nodes_from_documents(documents)
print(f"文档分块数量:{len(nodes)}")

2. 自定义数据加载(可选)

如果需要加载非标准格式数据(如数据库、API),可自定义Document:

from llama_index.core import Document

# 自定义文本数据
custom_text = "LangChain与LlamaIndex结合构建RAG的核心是检索精准性..."
custom_doc = Document(
    text=custom_text,
    metadata={"source": "自定义文档", "date": "2026-01-04"}  # 元数据增强检索
)
nodes.extend(parser.get_nodes_from_documents([custom_doc]))

四、构建向量索引(LlamaIndex + Chroma)

LlamaIndex支持多种索引类型,VectorStoreIndex(向量索引)是RAG的核心,结合Chroma向量数据库实现持久化存储:

1. 构建并保存索引

from llama_index.core import VectorStoreIndex
from llama_index.vector_stores.chroma import ChromaVectorStore
from chromadb.config import Settings as ChromaSettings
import chromadb

# 1. 初始化Chroma客户端(持久化存储到本地)
chroma_client = chromadb.PersistentClient(
    path="./chroma_db",  # 向量库存储路径
    settings=ChromaSettings(
        anonymized_telemetry=False,  # 关闭遥测
        is_persistent=True
    )
)
# 2. 创建/获取Chroma集合
chroma_collection = chroma_client.get_or_create_collection("rag_knowledge_base")
# 3. 将LlamaIndex与Chroma绑定
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)

# 4. 构建向量索引(将Node转为向量并存储)
index = VectorStoreIndex(
    nodes=nodes,
    vector_store=vector_store,
    embed_model=Settings.embed_model
)
# 5. 保存索引(可选,Chroma已自动持久化)
index.storage_context.persist(persist_dir="./llama_index_storage")

2. 加载已保存的索引(后续使用)

无需重复构建索引时,直接加载:

from llama_index.core import StorageContext, load_index_from_storage

# 加载Chroma向量库
chroma_client = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = chroma_client.get_collection("rag_knowledge_base")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)

# 加载LlamaIndex存储上下文
storage_context = StorageContext.from_defaults(
    vector_store=vector_store,
    persist_dir="./llama_index_storage"
)
# 加载索引
index = load_index_from_storage(storage_context=storage_context)

Python + LangChain + LlamaIndex 构建 RAG 知识库

五、构建RAG检索链(LangChain + LlamaIndex)

结合LangChain的流程编排能力与LlamaIndex的精准检索,实现“检索→格式化→生成”的完整RAG 流程:

1. LlamaIndex检索器接入LangChain

from langchain_core.retrievers import BaseRetriever
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from typing import List
from llama_index.core.query_engine import RetrieverQueryEngine

# 1. 将LlamaIndex索引转为LangChain兼容的检索器
class LlamaIndexRetriever(BaseRetriever):
    def __init__(self, index: VectorStoreIndex, top_k: int = 3):
        self.index = index
        self.top_k = top_k
        # 创建LlamaIndex检索器
        self.llama_retriever = index.as_retriever(similarity_top_k=top_k)

    def _get_relevant_documents(
        self, query: str, *, run_manager: CallbackManagerForRetrieverRun
    ) -> List:
        # 调用LlamaIndex检索,转换为LangChain Document格式
        nodes = self.llama_retriever.retrieve(query)
        langchain_docs = []
        for node in nodes:
            langchain_docs.append(
                {
                    "page_content": node.text,
                    "metadata": node.metadata
                }
            )
        return langchain_docs

# 初始化检索器(返回Top3相关文档)
retriever = LlamaIndexRetriever(index=index, top_k=3)

2. 构建LangChain RAG链

使用create_retrieval_chain实现 “检索→格式化提示词→生成回答” 的标准化流程:

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnablePassthrough
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain

# 1. 定义Prompt模板(核心:引导大模型基于检索结果回答)
prompt = ChatPromptTemplate.from_messages([
    ("system", """你是专业的知识库问答助手,仅基于提供的参考文档回答问题。
参考文档:
{context}

如果参考文档中没有相关信息,请明确说明“未找到相关答案”,不要编造内容。"""),
    MessagesPlaceholder(variable_name="chat_history"),  # 支持多轮对话
    ("user", "{input}"),
])

# 2. 创建文档合并链(将检索结果填入Prompt)
combine_docs_chain = create_stuff_documents_chain(llm_langchain, prompt)

# 3. 创建完整RAG链
rag_chain = create_retrieval_chain(
    retriever,
    combine_docs_chain
)

六、RAG问答调用与多轮对话

1. 单次问答调用

# 提问(替换为你的知识库问题)
question = "LangChain与LlamaIndex结合构建RAG的核心步骤是什么?"

# 调用RAG链
response = rag_chain.invoke({
    "input": question,
    "chat_history": []  # 首次对话无历史
})

# 输出结果
print("=== 回答 ===")
print(response["answer"])
print("
=== 参考文档 ===")
for i, doc in enumerate(response["context"], 1):
    print(f"
【参考{i}】")
    print(f"内容:{doc['page_content'][:200]}...")  # 截断显示
    print(f"来源:{doc['metadata'].get('source', '未知')}")

2. 多轮对话支持

基于chat_history维护对话上下文,实现多轮交互:

# 初始化对话历史
chat_history = []

# 第一轮对话
q1 = "RAG中的向量索引有什么作用?"
r1 = rag_chain.invoke({"input": q1, "chat_history": chat_history})
print(f"Q1: {q1}
A1: {r1['answer']}
")

# 更新对话历史
chat_history.extend([
    ("user", q1),
    ("assistant", r1["answer"])
])

# 第二轮对话(基于历史上下文)
q2 = "如何优化向量索引的检索精准性?"
r2 = rag_chain.invoke({"input": q2, "chat_history": chat_history})
print(f"Q2: {q2}
A2: {r2['answer']}")

七、进阶优化策略

1. 检索增强

混合检索:结合关键词检索(BM25)+ 向量检索,提升召回率

from llama_index.core.retrievers import BM25Retriever
from llama_index.core.retrievers import QueryFusionRetriever

# 构建BM25检索器
bm25_retriever = BM25Retriever.from_defaults(
    nodes=nodes,
    similarity_top_k=3
)
# 融合向量检索与BM25检索
fusion_retriever = QueryFusionRetriever(
    [retriever.llama_retriever, bm25_retriever],
    similarity_top_k=3,
    num_queries=1  # 生成1个扩展查询
)

元数据过滤:基于文档来源、日期等元数据缩小检索范围

# 仅检索2026年的文档
retriever.llama_retriever = index.as_retriever(
    similarity_top_k=3,
    filters={"date": ["2026-01-04"]}
)

2. 中文优化

  • 使用中文Embedding模型(如智谱 AI、百度文心)替换OpenAI Embedding
  • 优化中文分词:自定义SentenceSplitter的分隔符,结合jieba分词

3. 大模型替换

如需使用国产大模型(如通义千问、文心一言),只需替换LangChain的LLM:

# 示例:替换为通义千问
from langchain_community.chat_models import ChatTongyi

llm_langchain = ChatTongyi(
    model_name="qwen-turbo",
    temperature=0.1,
    api_key="your-tongyi-api-key"
)
Settings.llm = llm_langchain  # 更新LlamaIndex全局LLM

八、部署与运维

1. 索引更新

当知识库文档新增/修改时,重新加载文档并更新索引:

# 加载新文档
new_docs = SimpleDirectoryReader(input_dir="./new_docs").load_data()
new_nodes = parser.get_nodes_from_documents(new_docs)
# 向现有索引添加新节点
index.insert_nodes(new_nodes)

2. 性能优化

  • 调整chunk_size:中文提议 512-1024,过大会降低检索精准性,过小会丢失上下文
  • 向量库优化:Chroma可配置持久化/分片/生产环境可替换为Milvus/Pinecone
  • 缓存:对高频查询结果缓存,减少大模型调用次数

九、常见问题解决

  1. 检索结果为空:检查文档分块是否合理、Embedding模型是否匹配、查询词是否与文档相关
  2. 回答偏离知识库:优化Prompt分词模板,增加 “仅基于参考文档回答” 的强约束
  3. 中文检索效果差:替换为中文Embedding模型,优化分词规则
  4. 索引构建慢:批量处理文档,或使用GPU加速Embedding 计算

总结

基于LangChain(流程编排)+ LlamaIndex(数据索引)构建完整的RAG知识库,核心流程为:数据加载→分块→向量索引构建→检索→Prompt 格式化→大模型生成。该方案可适配本地文档、多模态数据、国产大模型,满足企业级知识库的核心需求。如需进一步扩展,可结合 API 封装、前端界面、权限控制等模块,形成完整的知识库问答系统。

Python + LangChain + LlamaIndex 构建 RAG 知识库

© 版权声明

相关文章

暂无评论

none
暂无评论...