1. 引言随着大语言模型LLM的快速发展如何让模型能够基于特定、最新的知识库进行准确、可靠的问答成为了一个关键挑战。检索增强生成Retrieval-Augmented GenerationRAG技术应运而生它通过将外部知识库检索与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_size500, # 每个块的最大字符数 chunk_overlap50, # 块之间的重叠字符数有助于保持上下文连贯 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(modeltext-embedding-3-small) 2. 创建向量存储 persist_directory指定向量数据库的持久化目录 vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db # 数据将保存到此目录 ) print(向量数据库创建并持久化完成) 提示 首次运行后向量数据已保存到本地。后续可以直接加载已存在的数据库无需重复处理文档 # 后续直接加载已存在的向量库 vectorstore Chroma( persist_directory./chroma_db, embedding_functionembeddings ) 6. 实战步骤三构建检索与问答链 现在我们利用构建好的向量库和LLM组装完整的问答链。 from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate 1. 初始化LLM llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) 2. 从向量库创建检索器 search_kwargs可以控制返回的相关文档数量 retriever vectorstore.as_retriever(search_kwargs{k: 4}) 3. 可选自定义提示词模板让模型更好地利用上下文 prompt_template 请根据以下提供的上下文信息来回答问题。如果上下文信息不足以回答问题请直接说“根据提供的资料我无法回答这个问题”不要编造信息。 上下文 {context} 问题{question} 请给出准确、清晰的答案 PROMPT PromptTemplate( templateprompt_template, input_variables[context, question] ) 4. 创建检索问答链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 将检索到的所有文档“塞”进提示词 retrieverretriever, chain_type_kwargs{prompt: PROMPT}, # 使用自定义提示词 return_source_documentsTrue # 返回检索到的源文档便于追溯 ) 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来源 {i1} (页码 {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生态提供了无限可能。