Python----大模型( langchain部署简单rag应用)

一、RetrievalQA 链实现

  1. 加载本地文本文件并分割处理

  2. 使用嵌入模型将文本转换为向量表示

  3. 构建向量数据库(FAISS)实现高效相似性检索

  4. 结合检索结果和大语言模型生成回答

特点 说明 优势体现
模块化封装 LangChain提供标准化组件 快速搭建原型系统
自动化流程 内置文档处理、检索、生成流水线 减少开发工作量
中文优化 使用bge-zh嵌入模型 中文语义理解更准确
本地化部署 模型和API均在本地运行 数据隐私有保障

导入依赖模块

from langchain_community.vectorstores import FAISS  # 导入FAISS向量存储库 - 用于高效存储和检索向量化文档
from langchain_huggingface import HuggingFaceEmbeddings  # 导入Hugging Face嵌入模型 - 用于将文本转换为向量表示
from langchain_community.document_loaders import TextLoader  # 导入文本加载器 - 用于加载本地文本文件
from langchain.text_splitter import RecursiveCharacterTextSplitter  # 导入递归字符文本分割器 - 用于将长文本分割为适合处理的片段
from langchain_openai import ChatOpenAI  # 导入ChatOpenAI模型 - 提供语言模型能力
# from langchain.chains import RetrievalQA  # 导入RetrievalQA链
from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

初始化语言模型

# 使用 OpenAI API 的 ChatOpenAI 模型
chat_model = ChatOpenAI(
    api_key='EMPTY',  # 设置为'EMPTY'因为使用本地部署的API
    base_url='http://127.0.0.1:10222/v1',  # 本地API服务的地址和端口
    model='Qwen2.5-7B-Instruct'  # 使用的具体模型名称(通义千问2.5的7B指令微调版)
)

加载和预处理文本数据

# 加载文本文件 "黑悟空.txt",编码格式为 'utf-8'
loader = TextLoader("黑悟空.txt", encoding='utf-8')
docs = loader.load()  # 将文件内容加载到变量 docs 中

# 把文本分割成 200 字一组的切片,每组之间有 20 字重叠
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,  # 每个文本块的最大长度(字符数)
    chunk_overlap=20  # 相邻文本块之间的重叠字符数(避免信息割裂)
)
chunks = text_splitter.split_documents(docs)  # 将文档分割成多个小块

初始化嵌入模型

# 初始化嵌入模型,使用预训练的语言模型 'bge-large-zh-v1___5'
embedding = HuggingFaceEmbeddings(
    model_name='/home/AI_big_model/models/AI-ModelScope/bge-large-zh-v1___5'  # 本地模型路径
)

构建向量数据库

# 构建 FAISS 向量存储和对应的 retriever
vs = FAISS.from_documents(chunks, embedding)  # 将文本块转换为向量并存储在FAISS中
retriever = vs.as_retriever()  # 创建一个检索器用于从向量存储中获取相关信息

配置问答系统提示模板

# 创建一个系统消息,用于定义机器人的角色
system_message = SystemMessagePromptTemplate.from_template(
    "根据以下已知信息回答用户问题。\n 已知信息{context}"  # 系统提示词,指导模型基于给定上下文回答
)

# 创建一个人类消息,用于接收用户的输入
human_message = HumanMessagePromptTemplate.from_template(
    "用户问题:{question}"  # 用户问题模板
)

# 将这些模板结合成一个完整的聊天提示
chat_prompt = ChatPromptTemplate.from_messages([
    system_message,
    human_message,
])

# 定义链的类型参数,包括使用的提示模板
chain_type_kwargs = {"prompt": chat_prompt}

构建问答链

# 创建一个问答链,将语言模型、检索器和提示模板结合起来
qa = RetrievalQA.from_chain_type(
    llm=chat_model,  # 使用的语言模型(之前初始化的Qwen2.5)
    chain_type="stuff",  # 处理检索结果的方式("stuff"表示简单拼接所有相关文档)
    retriever=retriever,  # 之前创建的检索器
    chain_type_kwargs=chain_type_kwargs  # 包含提示模板的配置
)

执行问答

# 用户的问题
user_question = "黑熊精自称为?"
# 使用检索器获取与问题相关的文档
related_docs = retriever.invoke(user_question)
print(related_docs)  # 打印检索到的相关文档

# 使用问答链来回答问题 "黑熊精自称为?" 并打印结果
print(qa.invoke(user_question))

完整代码

from langchain_community.vectorstores import FAISS  # 导入FAISS向量存储库
from langchain_huggingface import HuggingFaceEmbeddings  # 导入Hugging Face嵌入模型
from langchain_community.document_loaders import TextLoader  # 导入文本加载器
from langchain.text_splitter import RecursiveCharacterTextSplitter  # 导入递归字符文本分割器
from langchain_openai import ChatOpenAI  # 导入ChatOpenAI模型

# 使用 OpenAI API 的 ChatOpenAI 模型
chat_model = ChatOpenAI(
    api_key='EMPTY',
    base_url='http://127.0.0.1:10222/v1',
    model='Qwen2.5-7B-Instruct'
)

# 加载文本文件 "黑悟空.txt",编码格式为 'utf-8'
loader = TextLoader("黑悟空.txt", encoding='utf-8')
docs = loader.load()  # 将文件内容加载到变量 docs 中

# 把文本分割成 200 字一组的切片,每组之间有 20 字重叠
text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
chunks = text_splitter.split_documents(docs)  # 将文档分割成多个小块

# 初始化嵌入模型,使用预训练的语言模型 'bge-large-zh-v1___5'
embedding = HuggingFaceEmbeddings(model_name='/home/AI_big_model/models/AI-ModelScope/bge-large-zh-v1___5')

# 构建 FAISS 向量存储和对应的 retriever
vs = FAISS.from_documents(chunks, embedding)  # 将文本块转换为向量并存储在FAISS中

retriever = vs.as_retriever()  # 创建一个检索器用于从向量存储中获取相关信息

# from langchain.chains import RetrievalQA  # 导入RetrievalQA链
from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

# 创建一个系统消息,用于定义机器人的角色
system_message = SystemMessagePromptTemplate.from_template(
    "根据以下已知信息回答用户问题。\n 已知信息{context}"
)

# 创建一个人类消息,用于接收用户的输入
human_message = HumanMessagePromptTemplate.from_template(
    "用户问题:{question}"
)

# 将这些模板结合成一个完整的聊天提示
chat_prompt = ChatPromptTemplate.from_messages([
    system_message,
    human_message,
])

# 定义链的类型参数,包括使用的提示模板
chain_type_kwargs = {"prompt": chat_prompt}

# 创建一个问答链,将语言模型、检索器和提示模板结合起来
# chat_model:生成回答的语言模型,    stuff:所有检索到的文档内容合并成一个大文本块,然后传递给语言模型。
# retriever: 之前创建的一个 FAISS 检索器实例。它的作用是从 FAISS 向量存储中找到与用户问题最相关的文档或文本块。这些相关的文档会被传递给语言模型以生成回答。
# chain_type_kwargs 是一个字典,包含了用于配置问答链的一些关键参数。
qa = RetrievalQA.from_chain_type(llm=chat_model, chain_type="stuff", retriever=retriever, chain_type_kwargs=chain_type_kwargs)


# 用户的问题
user_question = "黑熊精自称为?"
# 使用检索器获取与问题相关的文档
related_docs = retriever.invoke(user_question)
print(related_docs)

# 使用问答链来回答问题 "黑熊精自称为?" 并打印结果
print(qa.invoke(user_question))


二、管道式(LECL)实现

  1. 加载本地文本文件并进行分块处理

  2. 使用嵌入模型将文本块转换为向量表示

  3. 构建向量数据库(FAISS)实现高效检索

  4. 结合检索结果和大语言模型生成回答

组件 作用 重要参数/说明
TextLoader 加载本地文本文件 encoding='utf-8'确保中文正确读取
RecursiveCharacterTextSplitter 智能文本分割 chunk_size=200控制文本块大小
HuggingFaceEmbeddings 文本向量化 bge-large-zh-v1是优秀的中文嵌入模型
FAISS 向量相似性搜索 高效的近似最近邻搜索库
ChatPromptTemplate 提示工程 定义系统角色和用户交互格式
RunnablePassthrough 数据传递 保持原始输入不变传递给下一步
StrOutputParser 输出标准化 确保输出格式统一

# 导入必要的库和模块
from langchain_openai import ChatOpenAI  # 导入OpenAI聊天模型接口
from langchain_community.document_loaders import TextLoader  # 导入文本加载器
from langchain_text_splitters import RecursiveCharacterTextSplitter  # 导入递归文本分割器
from langchain_huggingface import HuggingFaceEmbeddings  # 导入HuggingFace嵌入模型
from langchain_community.vectorstores import FAISS  # 导入FAISS向量数据库
from langchain.prompts import (  # 导入提示模板相关类
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate
)
from langchain_core.output_parsers import StrOutputParser  # 导入字符串输出解析器
from langchain_core.runnables import RunnablePassthrough  # 导入可运行组件

# 初始化语言模型
chat_model = ChatOpenAI(
    api_key='EMPTY',  # 使用本地部署的API,不需要真实API key
    base_url='http://127.0.0.1:10222/v1',  # 本地API服务地址
    model='Qwen2.5-7B-Instruct'  # 使用的模型名称(通义千问2.5的7B指令微调版)
)

# 加载文本文件
loader = TextLoader("黑悟空.txt", encoding='utf-8')  # 指定文件路径和编码
docs = loader.load()  # 加载文档内容,返回Document对象列表

# 文本分块处理
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,  # 每个文本块的最大长度(字符数)
    chunk_overlap=20  # 相邻文本块之间的重叠字符数(保持上下文连贯)
)
chunks = text_splitter.split_documents(docs)  # 执行分割,返回分割后的文档块列表

# 初始化嵌入模型
embedding = HuggingFaceEmbeddings(
    model_name='/home/AI_big_model/models/AI-ModelScope/bge-large-zh-v1___5'  # 本地嵌入模型路径
)

# 构建向量数据库
vs = FAISS.from_documents(
    chunks,  # 分割后的文档块
    embedding=embedding  # 使用的嵌入模型
)

# 创建检索器
retriever = vs.as_retriever()  # 将向量存储转换为检索器接口

# 构建系统消息模板(定义AI角色)
system_message = SystemMessagePromptTemplate.from_template(
    "根据以下已知信息回答用户问题。\n 已知信息{context}"  # 系统提示词模板
)

# 构建用户消息模板(接收用户问题)
human_message = HumanMessagePromptTemplate.from_template(
    "用户问题:{question}"  # 用户问题模板
)

# 组合完整提示模板
chat_prompt = ChatPromptTemplate.from_messages([
    system_message,  # 系统消息
    human_message   # 用户消息
])

# 初始化输出解析器
output_parser = StrOutputParser()  # 将模型输出解析为字符串

# 定义文档格式化函数
def format_docs(docs):
    """将检索到的文档列表合并为单个字符串"""
    return "\n\n".join(doc.page_content for doc in docs)  # 用两个换行符连接各文档内容

# 构建RAG处理链
rag_chain = (
    # 第一步:构建包含context和question的字典
    # context通过检索器获取文档后经format_docs格式化
    # question直接传递用户输入(RunnablePassthrough)
    {"context": retriever | format_docs, "question": RunnablePassthrough()}  
    | chat_prompt  # 第二步:应用提示模板
    | chat_model   # 第三步:调用语言模型生成回答
    | output_parser  # 第四步:解析模型输出
)

# 执行问答
print(rag_chain.invoke("黑熊精自称为?"))  # 传入问题并打印回答

三、对比

对比维度 RetrievalQA 链 管道式实现
流程控制 固定三步流程:检索 → 拼接 → 生成。 高度可定制:可拆分为5+个可定制步骤。
调试能力 受限:仅能获取最终输出,难以检查中间节点。 强大:可检查每个中间节点的输出,便于精确定位问题。
定制化能力 有限:仅能修改prompt模板。 极高:支持自定义检索策略、结果后处理、多模型协作等。
扩展性 受限:通过 chain_type 选择有限的处理方式。 极高:可插入缓存层、路由逻辑、业务校验规则等。
维护成本 :由 LangChain 框架维护兼容性。 :需自行维护整个流程逻辑。
适用场景 • POC验证
• 标准问答场景
• 有限计算资源
• 生产环境
• 复杂逻辑需求
• 需要监控各环节的场景
性能优化空间 有限:仅能调整 chunk_sizetop_k 等参数。 广阔:可优化异步处理、混合检索、动态分块策略等。
错误处理 统一:通常为统一的错误输出。 分级:可自定义检索失败降级、生成重试机制等。
维度 RetrievalQA链 管道式实现
开发速度 ★★★★★ ★★★
流程透明度 ★★ ★★★★★
定制灵活性 ★★ ★★★★★
调试便利性 ★★ ★★★★★
复杂场景适应性 ★★ ★★★★★
维护成本 ★★★★★ ★★★

使用 RetrievalQA 链:

        适合快速原型开发或简单的问答系统。

        如果标准的检索和生成流程足够满足需求,这是更简单的选择。

使用管道式实现:

        适合需要高度定制或对流程有更复杂需求的场景。 

你可能感兴趣的:(大模型,Python,langchain,人工智能,python)