1. 引言
随着大语言模型(LLM)的快速发展,如何让模型能够基于特定、最新的知识库进行准确、可靠的问答,成为了一个关键挑战。检索增强生成(Retrieval-Augmented Generation,RAG)技术应运而生,它通过将外部知识库检索与LLM生成能力相结合,有效解决了模型“幻觉”和知识过时的问题。
LangChain作为一个强大的LLM应用开发框架,为构建RAG系统提供了丰富的组件和便捷的接口。本文将带领你从零开始,实战构建一个基于LangChain的RAG问答机器人,涵盖从环境搭建、文档加载、文本切分、向量化存储到检索与生成的完整流程。
2. 环境准备与安装
首先,我们需要准备Python环境并安装必要的依赖库。
# 创建并激活虚拟环境(可选) python -m venv rag_env source rag_env/bin/activate # Linux/Mac # rag_env\Scripts\activate # Windows 安装核心库 pip install langchain langchain-community langchain-openai 安装文档加载与文本处理库 pip install pypdf python-docx beautifulsoup4 安装向量数据库(这里以Chroma为例) pip install chromadb 安装嵌入模型(这里以OpenAI Embeddings为例,需准备API Key) pip install openai 安装用于网页内容抓取的库(可选) pip install requests注意:使用OpenAI的模型需要配置API Key,请确保你已拥有有效的OpenAI账户并创建了API Key。
3. 核心组件与流程概述
一个典型的LangChain RAG流程包含以下几个核心步骤:
- 文档加载(Document Loaders):从PDF、Word、网页、数据库等多种来源加载原始文档。
- 文本分割(Text Splitters):将长文档切分成适合检索和模型处理的小块(Chunks)。
- 向量化(Embeddings):使用嵌入模型将文本块转换为数值向量。
- 向量存储(Vector Stores):将向量及其对应的文本块存储到向量数据库中。
- 检索器(Retrievers):根据用户问题,从向量库中检索出最相关的文本块。
- 大语言模型(LLM):将检索到的上下文和用户问题组合成提示词,交给LLM生成最终答案。
下图展示了RAG问答机器人的核心工作流程:
flowchart TD A[用户提问] --> B[检索器] C[向量数据库] --> B B --> D[检索相关文档块] D --> E[组合提示词] E --> F[大语言模型] F --> G[生成最终答案] G --> H[返回答案给用户] I[知识文档] --> J[文档加载器] J --> K[文本分割器] K --> L[嵌入模型] L --> C</code></pre> 4. 实战步骤一:加载与处理知识库 假设我们有一个名为“产品手册.pdf”的文档作为知识库。首先,我们需要加载并处理它。 from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter 1. 加载PDF文档 loader = PyPDFLoader("产品手册.pdf") documents = loader.load() 2. 初始化文本分割器 这里使用递归字符分割器,它会尝试按段落、句子等语义边界进行分割 text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, # 每个块的最大字符数 chunk_overlap=50, # 块之间的重叠字符数,有助于保持上下文连贯 separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""] # 分割符优先级 ) 3. 分割文档 chunks = text_splitter.split_documents(documents) print(f"原始文档页数: {len(documents)}") print(f"分割后的文本块数量: {len(chunks)}") print(f"第一个块的内容预览: {chunks[0].page_content[:200]}...") 5. 实战步骤二:向量化与存储 接下来,我们将文本块转换为向量,并存入向量数据库Chroma中。 from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma import os 设置OpenAI API Key(请替换成你自己的) os.environ["OPENAI_API_KEY"] = "your-openai-api-key-here" 1. 初始化嵌入模型 embeddings = OpenAIEmbeddings(model="text-embedding-3-small") 2. 创建向量存储 persist_directory指定向量数据库的持久化目录 vectorstore = Chroma.from_documents( documents=chunks, embedding=embeddings, persist_directory="./chroma_db" # 数据将保存到此目录 ) print("向量数据库创建并持久化完成!") 提示: 首次运行后,向量数据已保存到本地。后续可以直接加载已存在的数据库,无需重复处理文档: # 后续直接加载已存在的向量库 vectorstore = Chroma( persist_directory="./chroma_db", embedding_function=embeddings ) 6. 实战步骤三:构建检索与问答链 现在,我们利用构建好的向量库和LLM,组装完整的问答链。 from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate 1. 初始化LLM llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) 2. 从向量库创建检索器 search_kwargs可以控制返回的相关文档数量 retriever = vectorstore.as_retriever(search_kwargs={"k": 4}) 3. (可选)自定义提示词模板,让模型更好地利用上下文 prompt_template = """请根据以下提供的上下文信息来回答问题。如果上下文信息不足以回答问题,请直接说“根据提供的资料,我无法回答这个问题”,不要编造信息。 上下文: {context} 问题:{question} 请给出准确、清晰的答案:""" PROMPT = PromptTemplate( template=prompt_template, input_variables=["context", "question"] ) 4. 创建检索问答链 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", # 将检索到的所有文档“塞”进提示词 retriever=retriever, chain_type_kwargs={"prompt": PROMPT}, # 使用自定义提示词 return_source_documents=True # 返回检索到的源文档,便于追溯 ) 5. 进行问答测试 question = "这款产品的主要特性是什么?" result = qa_chain.invoke({"query": question}) print(f"问题:{question}") print(f"答案:{result['result']}") print("\n--- 参考来源 ---") for i, doc in enumerate(result['source_documents'][:2]): # 显示前两个来源 print(f"来源 {i+1} (页码 {doc.metadata.get('page', 'N/A')}): {doc.page_content[:150]}...") 7. 进阶优化与注意事项 7.1 提升检索质量 调整分块策略:根据文档类型(技术文档、法律条文、对话记录)调整chunk_size和chunk_overlap。 使用元数据过滤:在加载文档时保留章节、作者、日期等元数据,检索时可以进行过滤。 尝试不同的检索方法:LangChain支持相似度搜索(MMR)、自查询检索器等,可根据场景选择。 7.2 优化提示工程 在提示词中明确要求模型“基于上下文回答”,并设定拒绝回答的边界。 对于多步骤复杂问题,可以考虑使用“Map-Reduce”或“Refine”等链类型,而非简单的“stuff”。 7.3 处理长上下文与成本 大模型有上下文窗口限制,检索到的文档块总长度不能超过限制。 OpenAI API调用按Token计费,需注意检索块数量和提示词长度以控制成本。 8. 总结 本文详细介绍了使用LangChain构建RAG问答机器人的完整流程。从环境搭建、文档处理、向量化存储到最终的检索问答链,我们一步步实现了一个能够基于私有知识库进行智能问答的系统。RAG技术极大地扩展了大模型的应用边界,使其能够胜任专业、实时、准确的问答任务。 你可以在此基础上继续探索:集成更多类型的文档加载器、尝试不同的向量数据库(如FAISS, Pinecone)、接入其他LLM(如通义千问、DeepSeek),或构建一个带有历史对话记忆的聊天机器人。LangChain生态提供了无限可能。