当前位置: 首页 > news >正文

基于 LangChain + 通义千问 + bge-large 中文 Embedding 搭建一个RAG问答示例

文章目录

    • LangChain介绍
    • RAG简介
    • embedding模型权重下载代码
    • 核心代码实现
    • 代码解析
      • 1. 环境配置与依赖
      • 2. 模型设置
      • 3. 数据处理流程
      • 4. 提示模板设计
      • 5. 链(Chain)的编排
    • 使用方法

最近我尝试使用LangChain框架结合阿里云的通义千问模型构建了一个简单的RAG(检索增强生成)应用,在这里记录一下实现过程和关键代码解析。

LangChain介绍

LangChain 是一个用于构建基于大型语言模型(LLM)应用程序的流行开源框架。它提供模块化组件和工具链,简化了将 LLM 集成到实际应用中的流程,支持开发问答系统、聊天机器人、自动化代理等场景。其它流行的框架还有LlamaIndex,它可以和LangChain进行结合开发。
LangChain详细文档:https://python.langchain.com/docs/introduction/

RAG简介

RAG是一种将检索与生成相结合的AI应用架构,通过先检索相关知识再生成回答的方式,既能利用大模型的生成能力,又能保证回答的准确性和时效性。主要流程包括:

  1. 加载并处理文档数据
  2. 将文档向量化并存储
  3. 根据用户问题检索相关文档片段
  4. 结合检索到的信息生成回答

embedding模型权重下载代码

运行下面的代码即可将embedding模型的权重下载到本地,以供调用。

from modelscope import snapshot_downloadmodel_dir = snapshot_download(model_id='BAAI/bge-large-zh-v1.5',cache_dir=r'E:\project\agent_learn\RAG_LangChain\model_dir'
)

这里简单介绍下该embedding模型,BAAI/bge-large-zh-v1.5 是由北京智源人工智能研究院(BAAI)开发的中文文本嵌入模型,属于 BGE(BAAI General Embedding)系列模型之一。该模型专注于生成高质量的中文文本向量表示,适用于检索、聚类、语义匹配等自然语言处理任务。这个模型在中文语料库上的效果十分好,如果大家的主要业务是在英文文档领域,可以尝试国外的英文embedding模型,这里就不再详细介绍。

核心代码实现

下面是完整的实现代码:

from operator import itemgetter
from pathlib import Pathfrom langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_community.document_loaders import DirectoryLoader, TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_openai import ChatOpenAI
from langchain_chroma import Chroma
import os
from dotenv import load_dotenv# 加载环境变量
load_dotenv()  # 加载 .env 文件
api_key = os.getenv("QWEN_API_KEY")# 1. 设置模型
# 使用通义千问模型,通过兼容OpenAI的接口调用
llm = ChatOpenAI(model="qwen-max-latest", api_key=api_key, base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)# 使用本地的BGE中文嵌入模型
embedding_model = HuggingFaceEmbeddings(model_name=r"E:\project\agent_learn\RAG_LangChain\model_dir\BAAI\bge-large-zh-v1___5"
)# 2. 设置数据处理(加载、分块、存储、检索)
file_dir = Path('my_knowledge')
# 滑动窗口分块,块大小500字符,重叠100字符
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
# 使用Chroma作为向量数据库
vector_store = Chroma(embedding_function=embedding_model, persist_directory="./chroma_db")
# 创建检索器,每次检索5个最相关的片段
retriever = vector_store.as_retriever(search_kwargs={"k": 5})# 定义提示模板
prompt_template = PromptTemplate.from_template("""
请根据以下提供的上下文信息来回答问题。
如果上下文信息不足以回答问题,请直接说“根据提供的信息无法回答”。
如果回答时使用了上下文中的信息。在回答后输出使用了哪些上下文。
上下文信息:
{context}
-------------
问题:{question} """)# 3. 编排"链"
chain = ({ "question": RunnablePassthrough()}| RunnablePassthrough.assign(context=itemgetter("question") | retriever)| prompt_template| llm| StrOutputParser()
)if __name__ == '__main__':# 4. 初始化知识库(首次运行时取消注释)docs = DirectoryLoader(str(file_dir), loader_cls=TextLoader, loader_kwargs={"encoding": "utf-8"}).load()   # 加载文档docs = text_splitter.split_documents(docs)   # 切分文档vector_store.add_documents(docs)    # 存储文档# 测试问题print(chain.invoke("韩立是谁"))

代码解析

1. 环境配置与依赖

代码中使用了python-dotenv库来加载环境变量,将敏感的API密钥存储在.env文件中,避免硬编码。需要安装的主要依赖包括:

  • langchain及其相关组件
  • HuggingFace相关库
  • Chroma向量数据库
  • 通义千问API访问密钥

2. 模型设置

这里有两个关键模型:

  • 大语言模型LLM:使用通义千问的qwen-max-latest模型,通过兼容OpenAI的接口进行调用
  • 嵌入(embedding)模型:使用本地部署的BGE中文嵌入模型,适合处理中文文本

3. 数据处理流程

  1. 文档加载:从my_knowledge目录加载文本文件
  2. 文档分块:使用RecursiveCharacterTextSplitter进行分块,采用滑动窗口策略,保留上下文关联
  3. 向量存储:使用Chroma作为向量数据库,存储文档向量
  4. 检索设置:配置检索器,每次返回最相关的5个文档片段

4. 提示模板设计

提示模板中特别强调了:

  • 必须基于提供的上下文回答
  • 信息不足时的处理方式
  • 需要注明使用了哪些上下文

这种设计有助于提高回答的可追溯性和可靠性。

5. 链(Chain)的编排

LangChain的链机制将整个流程串联起来:

  1. 接收用户问题
  2. 根据问题检索相关上下文
  3. 将问题和上下文传入提示模板
  4. 调用大模型生成回答
  5. 解析输出结果

使用方法

  1. 准备.env文件,添加QWEN_API_KEY="你的通义千问API密钥"
  2. my_knowledge目录下放置相关文档
  3. 首次运行后,可以把 初始化知识库 注释掉,运行一次即可。
  4. 后续运行可直接调用chain.invoke("你的问题")获取回答

这个简单的RAG应用可以根据自己的需求进行扩展,比如添加更复杂的文档加载器、优化分块策略或增强提示工程等。

http://www.xdnf.cn/news/1239715.html

相关文章:

  • FastAPI入门:安全性
  • 第12届蓝桥杯Scratch图形化【省赛】初级组 2021年4月24日
  • MySQL学习之MVCC多版本并发控制
  • python常用数据类型
  • 13.Redis 的级联复制
  • 03.一键编译安装Redis脚本
  • sqli-labs:Less-23关卡详细解析
  • 【运维基础】Linux 硬盘分区管理
  • 数据集相关类代码回顾理解 | StratifiedShuffleSplit\transforms.ToTensor\Counter
  • Corrosion2靶机练习笔记
  • 选择排序原理与C语言实现详解
  • 第15届蓝桥杯Scratch图形化国赛初/中级组2024年9月7日真题
  • 【LeetCode刷题指南】--对称二叉树,另一颗树的子树
  • 【量化交易】日内交易有效特征因子
  • Socket编程——TCP协议
  • 智慧社区(六)——社区居民人脸识别功能实现详解:从腾讯 API 集成到模拟验证
  • CMake 命令行参数完全指南(2)
  • C++入门自学Day5-- C/C++内存管理(续)
  • 控制建模matlab练习08:根轨迹
  • 【图像处理基石】如何使用deepseek进行图像质量的分析?
  • pycharm上如何添加conda环境
  • 当Windows远程桌面出现“身份验证错误。要求的函数不受支持”的问题
  • [硬件电路-150]:数字电路 - 数字电路与模拟电路的异同
  • Ollama模型库模型下载慢完美解决(全平台)
  • 算法讲解--最大连续1的个数
  • RSA 解密逻辑
  • 【从零开始学习Redis】初识Redis
  • 第13章 文件输入/输出
  • 网关与路由器的区别
  • 【MySQL】MySQL中锁有哪些?