0

从0到1,LangChain+RAG全链路实战AI知识库

1egferghrt
5天前 4

获课地址:666it.top/15956/

从0到1,LangChain+RAG全链路实战AI知识库

引言:为什么需要RAG增强检索?

想象一下这样的场景:你拥有一个包含数千份内部文档、技术手册和会议纪要的企业知识库,希望员工能够像询问专家一样,用自然语言直接获取精准答案。传统的解决方案面临两难困境:如果仅靠大语言模型,它无法访问你的私有数据;如果仅靠关键词搜索,又难以理解复杂语义问题。

RAG(检索增强生成)技术的出现完美解决了这一矛盾。它结合了信息检索系统的精准性和大语言模型的生成能力,让AI不仅能"记忆"通用知识,更能"查阅"私有文档后给出专业回答。本文将带你从零开始,使用LangChain框架构建一个完整的RAG知识库系统。

一、技术原理:RAG的工作机制

核心思想

RAG的核心理念可以用一句话概括:在生成答案之前,先检索相关信息。当用户提出问题时,系统首先在知识库中检索最相关的文档片段,将这些片段作为上下文,连同原始问题一起提交给大语言模型,最终生成带有依据的回答。

工作流程分解

一个标准的RAG系统包含四个关键环节:

索引构建阶段:将原始文档切分成适当大小的文本块,通过嵌入模型转换为向量,存入向量数据库。这个过程相当于为知识库建立了一个"语义索引"。

检索阶段:将用户问题同样转换为向量,在向量数据库中搜索最相似的k个文档片段。这里的相似度计算基于向量空间的距离,能够捕捉语义层面的相关性。

增强阶段:将检索到的文档片段与原始问题组合成一个精心设计的提示模板,为模型提供充足的上下文信息。

生成阶段:大语言模型根据增强后的提示生成最终答案,同时可以要求模型给出引用来源,确保答案的可追溯性。

LangChain的角色定位

LangChain是一个专门用于构建基于大语言模型应用的开发框架,它为我们提供了:

  • 标准化的文档加载器,支持PDF、网页、数据库等数十种数据源

  • 灵活的文本分割器,可根据需求自定义分块策略

  • 统一的向量存储接口,兼容Chroma、FAISS、Pinecone等主流数据库

  • 完善的提示模板管理机制

  • 简洁的链式调用API,将上述组件串联成完整流程

二、环境准备与数据预处理

基础环境搭建

首先创建独立的Python环境并安装必要依赖:

bash
# 创建虚拟环境conda create -n rag-demo python=3.9conda activate rag-demo# 安装核心库pip install langchain langchain-community langchain-openai
pip install chromadb faiss-cpu  # 向量数据库pip install pypdf docx2txt  # 文档解析库

获取并配置大模型API

本教程以OpenAI为例,你需要准备API密钥:

python
import os
os.environ["OPENAI_API_KEY"] = "your-api-key-here"# 如果使用国内服务商,可配置代理或使用兼容OpenAI接口的国产模型os.environ["OPENAI_BASE_URL"] = "https://api.your-provider.com/v1"

文档加载与解析

LangChain的文档加载器让这一过程变得异常简单:

python
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader, TextLoader# 加载指定目录下的所有PDF文件pdf_loader = DirectoryLoader(
    './knowledge_base/', 
    glob="**/*.pdf",
    loader_cls=PyPDFLoader)# 同时加载多种格式的文档loaders = [
    DirectoryLoader('./docs/', glob="**/*.txt", loader_cls=TextLoader),
    DirectoryLoader('./docs/', glob="**/*.pdf", loader_cls=PyPDFLoader),]documents = []for loader in loaders:
    documents.extend(loader.load())print(f"成功加载 {len(documents)} 个文档")

智能文本分割

文档分割是影响检索效果的关键环节。分块过大可能导致上下文混杂,过小则可能丢失完整语义:

python
from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,        # 每个块的最大字符数
    chunk_overlap=50,      # 相邻块之间的重叠字符数
    length_function=len,
    separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""])chunks = text_splitter.split_documents(documents)print(f"文档分割为 {len(chunks)} 个文本块")

分割策略建议

  • 技术文档:以段落自然分割,chunk_size可适当增大

  • 对话记录:按轮次分割,保持对话的完整性

  • 代码示例:按函数或类分割,避免截断语法结构

三、向量化与检索系统构建

选择嵌入模型

嵌入模型的质量直接决定了检索的准确性。LangChain支持多种选择:

python
from langchain_openai import OpenAIEmbeddings# 使用OpenAI的text-embedding-ada-002模型embeddings = OpenAIEmbeddings(
    model="text-embedding-ada-002",
    disallowed_special=())# 备选方案:如果希望本地部署,可以使用HuggingFace的嵌入模型# from langchain_community.embeddings import HuggingFaceEmbeddings# embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-base-zh-v1.5")

向量数据库实战

以Chroma为例,这是一个轻量级、易用的向量数据库:

python
from langchain_community.vectorstores import Chroma# 创建向量数据库并存入文档块vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db"  # 本地持久化存储)# 后续使用时可以直接加载已有的数据库# vectorstore = Chroma(persist_directory="./chroma_db", embedding_function=embeddings)

检索器设计与优化

基础的相似度检索可能无法满足所有场景,LangChain提供了多种检索策略:

基础相似度检索:返回与问题最相似的k个文档块

python
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 4})

MMR检索:在相关性和多样性之间取得平衡,避免返回内容过于相似

python
retriever = vectorstore.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 4, "fetch_k": 20, "lambda_mult": 0.5})

带分数阈值的检索:只返回相似度超过特定阈值的文档

python
retriever = vectorstore.as_retriever(
    search_type="similarity_score_threshold",
    search_kwargs={"score_threshold": 0.5, "k": 4})

四、提示工程与生成链路构建

设计高质量的提示模板

提示模板决定了模型如何使用检索到的上下文。一个优秀的RAG提示模板应当:

python
from langchain.prompts import ChatPromptTemplate

template = """你是一个专业的知识库助手。请基于以下提供的上下文片段,准确、简洁地回答用户的问题。要求:
1. 如果上下文中包含相关信息,请基于这些信息回答
2. 如果上下文中没有足够信息,请明确告知"知识库中没有找到相关信息"
3. 引用来源时请标注对应的文档片段编号
4. 保持回答的专业性和客观性

上下文信息:
{context}

用户问题:{question}

你的回答:"""

prompt = ChatPromptTemplate.from_template(template)

构建完整的RAG链

LangChain的LCEL语法让我们能够以声明式的方式构建流程:

python
from langchain_core.runnables import RunnablePassthroughfrom langchain_openai import ChatOpenAI# 初始化大语言模型llm = ChatOpenAI(
    model="gpt-3.5-turbo",
    temperature=0.3,  # 较低的温度保证回答的确定性
    max_tokens=500)# 定义文档格式化函数def format_docs(docs):
    return "\n\n".join([f"[{i+1}] {doc.page_content}" for i, doc in enumerate(docs)])# 构建RAG链rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt    | llm)

添加会话记忆功能

真实场景中,用户往往会连续提问。为系统添加记忆能力:

python
from langchain.memory import ConversationBufferMemoryfrom langchain.chains import ConversationalRetrievalChain

memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True,
    output_key="answer")qa_chain = ConversationalRetrievalChain.from_llm(
    llm=llm,
    retriever=retriever,
    memory=memory,
    verbose=True)# 连续对话测试response1 = qa_chain.invoke({"question": "什么是RAG技术?"})response2 = qa_chain.invoke({"question": "它和传统搜索有什么区别?"})

五、系统评估与优化进阶

检索质量评估

构建评估数据集是优化的第一步:

python
# 准备测试问题及期望检索到的文档块test_queries = [
    {"query": "LangChain支持哪些向量数据库?", "relevant_docs": [3, 5, 7]},
    {"query": "如何设置文本分割的chunk_size?", "relevant_docs": [12, 13]},]# 计算检索指标def evaluate_retrieval(retriever, test_queries, k=5):
    total_precision = 0
    total_recall = 0
    
    for item in test_queries:
        retrieved_docs = retriever.get_relevant_documents(item["query"])
        retrieved_ids = [doc.metadata.get("chunk_id") for doc in retrieved_docs[:k]]
        
        relevant_ids = item["relevant_docs"]
        relevant_retrieved = set(retrieved_ids) & set(relevant_ids)
        
        precision = len(relevant_retrieved) / k
        recall = len(relevant_retrieved) / len(relevant_ids)
        
        total_precision += precision
        total_recall += recall    
    return {
        "avg_precision": total_precision / len(test_queries),
        "avg_recall": total_recall / len(test_queries)
    }

常见问题与优化策略

检索相关性不足

  • 尝试不同的嵌入模型,中文场景可考虑BGE或text2vec

  • 调整chunk_size和overlap,确保语义完整

  • 使用HyDE技术:先让模型生成假设答案,再用假设答案检索

答案生成幻觉

  • 降低temperature参数值

  • 在提示中强调"仅基于给定上下文"

  • 添加验证环节,要求模型标注信息来源

处理多文档中的矛盾信息

  • 增加检索数量k值,获取更多上下文

  • 在提示中要求模型对比不同来源

  • 考虑添加文档元数据(如更新时间、来源类型)辅助判断

系统性能优化

随着文档数量增长,检索延迟可能成为瓶颈:

python
# 1. 使用异步检索提升并发能力async def async_retrieve(queries):
    tasks = [retriever.aget_relevant_documents(q) for q in queries]
    return await asyncio.gather(*tasks)# 2. 引入缓存机制减少重复计算from langchain.cache import InMemoryCacheimport langchain
langchain.llm_cache = InMemoryCache()# 3. 考虑使用更高效的向量索引# 切换到FAISS并设置IVF索引from langchain_community.vectorstores import FAISS
vectorstore = FAISS.from_documents(chunks, embeddings)vectorstore.save_local("faiss_index")# 检索时使用nprobe参数平衡速度和精度retriever = vectorstore.as_retriever(
    search_kwargs={"k": 4, "nprobe": 10})

从工具到产品:构建生产级知识库

完成基础的RAG系统后,你可以朝着产品化方向继续探索:

多模态扩展:除了文本,增加对图片、表格、音视频的理解能力,让知识库更加丰富立体。

用户反馈闭环:收集用户对回答的评分和反馈,用于持续优化检索和生成质量。

权限管理:在企业应用中,实现基于角色的文档访问控制,确保信息安全。

流式输出:改进用户体验,实现逐字输出的流式响应。

RAG技术的魅力在于它的灵活性和可扩展性。它不是一个固定不变的方案,而是可以根据具体场景不断优化和调整的框架。从今天开始,用你手头的文档构建第一个RAG知识库,迈出从理论到实践的关键一步。当你的同事问起某个技术细节,而你的AI知识库能给出准确答案时,你会感受到技术创造的真正价值。


本站不存储任何实质资源,该帖为网盘用户发布的网盘链接介绍帖,本文内所有链接指向的云盘网盘资源,其版权归版权方所有!其实际管理权为帖子发布者所有,本站无法操作相关资源。如您认为本站任何介绍帖侵犯了您的合法版权,请发送邮件 [email protected] 进行投诉,我们将在确认本文链接指向的资源存在侵权后,立即删除相关介绍帖子!
最新回复 (0)

    暂无评论

请先登录后发表评论!

返回
请先登录后发表评论!