当前位置: 首页 > 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.dtcms.com/a/312791.html

相关文章:

  • TVS二极管数据手册解读
  • 【lucene】ByteBufferGuard
  • Android 之 MVVM架构
  • 【MySQL】MySQL中锁有哪些?
  • Flutter 函数的基本使用
  • day39 力扣198.打家劫舍 力扣213.打家劫舍II 力扣337.打家劫舍 III
  • 常见框架漏洞靶场攻略
  • Java 实现poi方式读取word文件内容
  • 力扣967:连续差相同的数字
  • Mysql1
  • Docker-03.快速入门-部署MySQL
  • python的蛋糕店管理系统
  • MySQL的创建管理表:
  • 求根到叶子节点数字之和
  • 【数据分享】南京诗歌文学地理数据集(获取方式看文末)
  • 电机结构设计与特性曲线分析:基于MATLAB和FEMM的仿真研究
  • 6. 平台总线
  • 机器学习第四课之决策树
  • Shell 脚本流程控制语句详解(四):while 循环详解
  • lua table常用函数汇总
  • Django 序列化详解:从 Model 到 JSON,全面掌握数据转换机制
  • 使用AndroidStudio调试Framework源码
  • 腾讯人脸识别
  • 数据治理:DQC(Data Quality Center,数据质量中心)概述
  • [嵌入式embed]C51单片机STC-ISP提示:正在检测目标单片机
  • 《前端无障碍设计的深层逻辑与实践路径》
  • MyBatis动态SQL精要:从<if>到<foreach>的灵活拼接之道
  • 高质量数据集|建设三大难点
  • [硬件电路-140]:模拟电路 - 信号处理电路 - 锁定放大器概述、工作原理、常见芯片、管脚定义
  • [硬件电路-133]:模拟电路 - 信号处理电路 - 电荷放大器概述、工作原理、常见芯片、管脚定义