基于LangChain构建高效RAG问答系统:向量检索与LLM集成实战

基于LangChain构建高效RAG问答系统:向量检索与LLM集成实战

在本文中,我将详细介绍如何使用LangChain框架构建一个完整的RAG(检索增强生成)问答系统。通过向量检索获取相关上下文,并结合大语言模型,我们能够构建出一个能够基于特定知识库回答问题的智能系统。

1. 基础设置与向量检索准备

首先,我们需要导入必要的库并设置向量存储访问:

import os
from dotenv import load_dotenv
from langchain_core.output_parsers import StrOutputParser
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_redis import RedisConfig, RedisVectorStore# 加载环境变量
load_dotenv()# 定义查询问题
query = "我的生日是几月几日?"# 初始化阿里云百炼平台的向量模型
embedding = DashScopeEmbeddings(model="text-embedding-v3", dashscope_api_key=os.getenv("ALY_EMBADING_KEY"))
redis_url = "redis://localhost:6379"  # Redis数据库的连接地址# 配置Redis向量存储
config = RedisConfig(index_name="my_index2",  # 索引名称redis_url=redis_url,  # Redis数据库的连接地址
)# 创建向量存储实例和检索器
vector_store = RedisVectorStore(embedding, config=config)
retriever = vector_store.as_retriever()

这部分代码完成了以下工作:

  • 加载环境变量以安全地使用API密钥
  • 初始化阿里云文本嵌入模型
  • 配置Redis向量数据库连接
  • 创建检索器(retriever),用于执行向量相似度检索

2. 执行向量检索

接下来,我们使用检索器从向量库中获取与查询相关的文本段落:

# 执行检索,获取相关文本段落
retriever_segments = retriever.invoke(query, k=5)
print(retriever_segments)# 将检索结果整合
text = []
for segment in retriever_segments:text.append(segment.page_content)

在这段代码中:

  • retriever.invoke(query, k=5) 检索与查询语义最相关的5个文本段落
  • 我们将检索到的每个段落的文本内容提取并整合到一个列表中

3. 构建Prompt模板

我们需要设计一个提示模板,将检索到的相关信息和用户问题一起传递给大语言模型:

from langchain_core.prompts import ChatPromptTemplateprompt_template = ChatPromptTemplate.from_messages([("system", """你是一个问答机器人,你的任务是根据下述给定的已知信息回答用户的问题已知信息:{context}用户问题:{query}如果已知问题不包含用户问题的答案,或者已知信息不足以回答用户的问题,请回答"抱歉,我无法回答这个问题。"请不要输出已知信息中不包含的信息或者答案。用中文回答用户问题"""),]
)# 格式化prompt
prompt = prompt_template.invoke({"context": text, "query": query})
print(prompt.to_messages()[0].content)

这个提示模板:

  • 明确定义了AI助手的角色和任务
  • 设置了两个变量:{context}用于传入检索结果,{query}用于传入用户问题
  • 提供了清晰的回答指令,包括当信息不足时如何响应

4. 调用大语言模型获取回答

现在,我们使用LLM来生成基于上下文的回答:

from langchain_openai import ChatOpenAI# 结果解析器,直接获取纯文本回复
parser = StrOutputParser()# 初始化LLM模型接口
model = ChatOpenAI(base_url="https://openrouter.ai/api/v1", api_key=os.getenv("OPENAI_KEY"),model="qwen/qwq-32b:free")# 调用模型获取回答
result = model.invoke(prompt)
print(result)

这里我们:

  • 使用了OpenRouter平台上的通义千问模型
  • 通过model.invoke(prompt)将格式化后的提示发送给模型
  • 获取模型的文本响应

5. 构建完整的RAG链

最后,我们将把所有步骤整合成一个完整的LangChain处理链,实现端到端的RAG问答:

from operator import itemgetter# 辅助函数:收集文档内容
def collect_documents(segments):text = []for segment in segments:text.append(segment.page_content)return text# 构建完整的处理链
chain = ({"context": itemgetter("query") | retriever | collect_documents,"query": itemgetter("query")
} | prompt_template | model | parser)# 设置新的查询并执行链
query = "你能帮助史可轩处理日常事务吗"
response = chain.invoke({"query": query})
print(response)

这个链式处理流程:

  1. 接收用户查询
  2. 执行向量检索获取相关上下文
  3. 将上下文和查询组合到提示模板中
  4. 调用LLM生成回答
  5. 解析并返回最终的文本响应

详细解析链式处理

让我们解析一下这个链式处理的构建方式:

chain = ({"context": itemgetter("query") | retriever | collect_documents,"query": itemgetter("query")
} | prompt_template | model | parser)

这个链式结构使用了LangChain的管道操作符 |,实现了以下流程:

  1. itemgetter("query") 从输入字典中提取查询文本
  2. 将查询传递给 retriever 执行向量检索
  3. collect_documents 函数处理检索结果,提取文本内容
  4. 将处理后的上下文和原始查询分别作为 contextquery 传递给提示模板
  5. 提示模板格式化后的内容发送给LLM模型处理
  6. 最后通过 parser 解析LLM的响应,获取纯文本结果

总结

本文介绍了如何使用LangChain框架构建一个完整的RAG问答系统,主要包含以下步骤:

  1. 向量检索:从Redis向量数据库中检索与用户问题语义相似的文本段落
  2. 提示工程:设计合适的提示模板,将检索结果作为上下文与用户问题一起发送给模型
  3. 模型调用:利用LangChain的接口调用大语言模型生成答案
  4. 链式处理:使用LangChain的管道操作将各个组件整合成一个端到端的工作流

这种RAG架构具有很好的可解释性和可靠性,能够基于特定的知识库回答问题,避免了大语言模型"幻觉"问题,特别适合构建企业级知识问答系统、客服助手等应用。

通过向量检索提供相关上下文,我们可以让大语言模型更准确地回答特定领域的问题,同时也能降低知识更新的成本(只需更新向量库而无需重新训练模型)。这种方案在实际应用中具有很高的灵活性和可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82912.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java学习笔记】SringBuffer类(重点)

StringBuffer(重点) 1. 基本介绍 (1)StringBuffer是可变的字符序列,可以对字符串内容惊醒增删 (2)很多方法喝String相同,但StringBuffer可变长度 (3)Strin…

计算机网络领域所有CCF-A/B/C类期刊汇总!

本期小编统计了【计算机网络】领域CCF推荐所有期刊的最新影响因子,分区、年发文量以及投稿经验,供大家参考! CCF-A类 1 IEEE Journal on Selected Areas in Communications 【影响因子】13.8 【期刊分区】JCR1区,中科院1区TOP …

AI-Sphere-Butler之如何启动AI全能管家教程(WSL测试环境下适用)

环境: Ubuntu20.04 WSL2 问题描述: AI-Sphere-Butler之如何启动AI全能管家教程(WSL测试环境下适用) 解决方案: 打开管家大模型 1.运行大模型在cmd下输入: ollama run qwen2.5-3bnsfwny运行管家 数字人运行脚本&#xff…

【python深度学习】Day 47 注意力热图可视化

知识点:热力图 作业:对比不同卷积层热图可视化的结果 一、概念 为了方便观察输出,将特征图进行可视化。特征图本质就是不同的卷积核的输出,浅层指的是离输入图近的卷积层,浅层卷积层的特征图通常较大,而深层…

C#语音识别:使用Whisper.net实现语音识别

C#语音识别:使用Whisper.net实现语音识别 在当今数字化时代,语音识别技术已广泛应用于智能助手、语音转文字、会议记录等众多领域。对于 C# 开发者而言,如何快速、高效地实现语音识别功能呢?今天,我们就来介绍一个强大…

开源分享|适合初创商家的餐饮系统,基于thinkphp8+element-plus

一、项目介绍 三勾餐饮点餐连锁版系统是一个基于thinkphp8element-plusuniapp打造的面向开发的小程序商城的全面解决方案,旨在为连锁餐饮企业提供高效的点餐与管理服务。该系统支持多端应用发布,包括微信小程序、H5、安卓及iOS平台,实现数据…

rec_pphgnetv2完整代码学习(一)

rec_pphgnetv2是paddleocr_v5中的重要改进,因此对其完整代码进行学习十分之有必要。 一、IdentityBasedConv1x1 这段代码定义了 IdentityBasedConv1x1 类,它是 PaddleOCRv5 中 rec_pphgnetv2 模型的关键改进之一。该层通过将恒等映射(Ident…

vue3+dify从零手撸AI对话系统

vue3dify从零手撸AI对话系统 前言 近年来,人工智能技术呈现爆发式增长,其应用已深度渗透至各行各业。甚至家里长辈们也开始借助AI工具解决日常问题。作为程序员群体,我们更应保持技术敏锐度,紧跟这波浪潮。 回溯求学时期&#xf…

robot_lab train的整体逻辑

Go2机器人推理(Play)流程详细分析 概述 本文档详细分析了使用命令 python scripts/rsl_rl/base/play.py --task RobotLab-Isaac-Velocity-Rough-Unitree-Go2-v0 进行Go2机器人推理的完整流程,基于实际的代码实现,包括模型加载、环境配置调整、推理循环…

Python Day45

Task: 1.tensorboard的发展历史和原理 2.tensorboard的常见操作 3.tensorboard在cifar上的实战:MLP和CNN模型 效果展示如下,很适合拿去组会汇报撑页数: 作业:对resnet18在cifar10上采用微调策略下,用tens…

MySQL SQL 优化:从 INSERT 到 LIMIT 的实战与原理

在数据库驱动的现代应用中,SQL 查询的性能直接决定了用户体验和系统效率。本文将深入探讨 MySQL (特别是 InnoDB 存储引擎)中常见的 SQL 性能瓶颈,并结合实际案例,详细剖析从数据插入到复杂分页查询的优化策略与底层实…

SQL 基础入门

SQL 基础入门 SQL(全称 Structured Query Language,结构化查询语言)是用于操作关系型数据库的标准语言,主要用于数据的查询、新增、修改和删除。本文面向初学者,介绍 SQL 的基础概念和核心操作。 1. 常见的 SQL 数据…

HTTP 请求协议简单介绍

目录 常见的 HTTP 响应头字段 Java 示例代码:发送 HTTP 请求并处理响应 代码解释: 运行结果: 文件名: 总结: HTTP(HyperText Transfer Protocol)是用于客户端与服务器之间通信的协议。它定…

《100天精通Python——基础篇 2025 第5天:巩固核心知识,选择题实战演练基础语法》

目录 一、踏上Python之旅二、Python输入与输出三、变量与基本数据类型四、运算符五、流程控制 一、踏上Python之旅 1.想要输出 I Love Python,应该使用()函数。 A.printf() B.print() C.println() D.Print() 在Python中想要在屏幕中输出内容,应该使用print()函数…

求解一次最佳平方逼近多项式

例 设 f ( x ) 1 x 2 f(x)\sqrt{1x^2} f(x)1x2 ​,求 [ 0 , 1 ] [0,1] [0,1]上的一个一次最佳平方逼近多项式。 解 : d 0 ∫ 0 1 1 x 2 d x 1 2 ln ⁡ ( 1 2 ) 2 2 ≈ 1.147 d_0\int_{0}^{1}\sqrt{1x^2}dx\frac{1}{2}\ln(1\sqrt{2})\frac{\sqrt…

在Ubuntu上使用 dd 工具制作U盘启动盘

在Ubuntu上使用 dd 工具制作U盘启动盘 在Linux系统中,dd 是一个功能强大且原生支持的命令行工具,常用于复制文件和转换数据。它也可以用来将ISO镜像写入U盘,从而创建一个可启动的操作系统安装盘。虽然图形化工具(如 Startup Disk…

如何理解OSI七层模型和TCP/IP四层模型?HTTP作为如何保存用户状态?多服务器节点下 Session方案怎么做

本篇概览: OSI 七层模型是什么?每一层的作用是什么?TCP/IP四层模型和OSI七层模型的区别是什么? HTTP 本身是无状态协议,HTTP如何保存用户状态? 能不能具体说一下Cookie的工作原理、生命周期、作用域?使用…

深入剖析 RocketMQ 中的 DefaultMQPushConsumerImpl:消息推送消费的核心实现

前言 在 Apache RocketMQ 的消息消费体系中,RocketMQ 提供了DefaultMQPushConsumer(推送消费)和DefaultMQPullConsumer(拉取消费)两种主要消费方式。DefaultMQPushConsumer与DefaultMQPullConsumer在消息获取方式&…

Linux编程:2、进程基础知识

一、进程基本概念 1、进程与程序的区别 程序:静态的可执行文件(如电脑中的vs2022安装程序)。进程:程序的动态执行过程(如启动后的vs2022实例),是操作系统分配资源的单位(如 CPU 时…

React Router 中 navigate 后浏览器返回按钮不起作用的问题记录

React Router 中 navigate 后浏览器返回按钮不起作用的问题记录 在使用 React Router(v6)开发项目时,我遇到了一个让人困惑的问题: 当我从 /article 页面使用 navigate("/article/next") 进行跳转后,点击浏…