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

大模型之Langchain篇(二)——RAG

写在前面

跟着楼兰老师学习【LangChain教程】2025吃透LangChain框架快速上手与深度实战,全程干货无废话,三天学完,让你少走百分之99弯路!_哔哩哔哩_bilibili

计算相似度

一般用的余弦相似度,这里只是演示计算。

from sklearn.metrics.pairwise import cosine_similarity
import numpy as np# 定义两个⽂本
text1 = "我喜欢吃苹果"
text2 = "我最爱吃的⽔果是苹果"
text3 = "今天天⽓不错"# 获取⽂本向量
vector1 = np.array(embedding_model.embed_query(text1)).reshape(1,-1)
vector2 = np.array(embedding_model.embed_query(text2)).reshape(1,-1)
vector3 = np.array(embedding_model.embed_query(text3)).reshape(1,-1)# 计算余弦相似度
similarity12 = cosine_similarity(vector1, vector2)[0][0]
similarity13 = cosine_similarity(vector1, vector3)[0][0]# 计算欧氏距离
euclidean_distance12 = np.linalg.norm(vector1 - vector2)
euclidean_distance13 = np.linalg.norm(vector1 - vector3)# 计算曼哈顿距离
manhattan_distance12 = np.sum(np.abs(vector1 - vector2))
manhattan_distance13 = np.sum(np.abs(vector1 - vector3))print(f"\"{text1}\" 与 \"{text2}\" 余弦相似度:{similarity12:.4f}")
print(f"\"{text1}\" 与 \"{text3}\" 余弦相似度:{similarity13:.4f}")
print(f"\"{text1}\" 与 \"{text2}\" 欧氏距离:{euclidean_distance12:.4f}")
print(f"\"{text1}\" 与 \"{text3}\" 欧氏距离:{euclidean_distance13:.4f}")
print(f"\"{text1}\" 与 \"{text2}\" 曼哈顿距离:{manhattan_distance12:.4f}")
print(f"\"{text1}\" 与 \"{text3}\" 曼哈顿距离:{manhattan_distance13:.4f}")

利用redis构建检索库

如何用redis见大模型之Langchain篇——基础操作-CSDN博客。

用add_texts的方式添加数据。

检索器的检索方式

similarity 类型

similarity 即相似度检索,这是最基础的向量检索方式。它会计算查询向量和向量存储中所有文档向量的相似度(通常用余弦相似度),然后按照相似度从高到低排序,返回前 k 个文档。在你的代码里,k 值为 3,意味着会返回相似度最高的 3 个文档。

similarity_score_threshold

该类型在 similarity 检索基础上增加了相似度阈值。它会先计算查询向量和文档向量的相似度,只返回相似度高于设定阈值的文档,并且最多返回 k 个文档。但好像需要实现 _similarity_search_with_relevance_scores 方法,但langchain_redis 库中的 RedisVectorStore 尚未实现这个用于返回文档及相关性分数的方法,因此调用失败。

mmr

最大边界相关检索,目的是在保证与查询相关性的同时,提高返回文档的多样性。它会先选出与查询最相关的文档,然后在后续选择时,综合考虑文档与查询的相关性以及和已选文档的差异性,避免返回的文档过于相似。

from langchain_redis import RedisConfig,RedisVectorStore
config = RedisConfig(index_name="fruit",redis_url=redis_url
)
vector_store = RedisVectorStore(embedding_model,config=config)
vector_store.add_texts(["⾹蕉很⻓","苹果很甜","⻄⽠⼜⼤⼜圆"])
vector_store.add_texts(["黄瓜很长","这个黄瓜太长了","香蕉是长条形的水果","甘蔗比香蕉还长"])# 构建检索器,类型为similarity,检索的⽂档个数为3
retriver = vector_store.as_retriever(search_type="similarity",search_kwargs={"k":3})
retriver1 = vector_store.as_retriever(search_type="similarity",search_kwargs={"k":3})print ("\nretriver1 类型为similarity,检索的⽂档个数为3")
retriver1.invoke("⻓⻓的⽔果是什么?")# # 构建检索器,设置相似度阈值为 0.8
# retriever2 = vector_store.as_retriever(
#     search_type="similarity_score_threshold",
#     search_kwargs={"score_threshold": 0.8}
# )
# print ("\nretriever2 类型为similarity_score_threshold,检索的⽂档个数为3,相似度阈值为 0.8")
# retriever2.invoke("长长的水果是什么?")# 构建 MMR 检索器
retriever3 = vector_store.as_retriever(search_type="mmr",search_kwargs={"k": 3, "lambda_mult": 0.5}  # lambda_mult 控制相关性和多样性的权重
)
print ("\nretriever3 类型为mmr,检索的⽂档个数为3,lambda_mult 控制相关性和多样性的权重")
retriever3.invoke("长长的水果是什么?")

可以在resp.app中看到检索库信息

将检索器链接到chain中

才知道自定义的函数也能放到chain中(下面代码的format_prompt_value)

from langchain_core.prompts import ChatPromptTemplate
# 创建提示模板
prompt = ChatPromptTemplate.from_messages([("human", "{question}"),
])
# 格式转换函数,prompt.invoke⽅法返回PromptValue,⽽retriver.invoke需要传⼊的参数为str。中间做个格式转换
def format_prompt_value(prompt_value):return prompt_value.to_string()
# 链式连接检索器和提示模板
chain = prompt | format_prompt_value | retriver
# 调⽤链并传⼊⽤户的问题
documents = chain.invoke({"question":"⼜⻓⼜甜的⽔果是什么?"})
for document in documents:print(document.page_content)

 meituan RAG

数据来源 

美团外卖 - 常见问题

也可以直接复制我的

 

Q:在线支付取消订单后钱怎么返还?
订单取消后,款项会在一个工作日内,直接返还到您的美团账户余额。Q:怎么查看退款是否成功?
退款会在一个工作日之内到美团账户余额,可在“账号管理——我的账号”中查看是否到账。Q:美团账户里的余额怎么提现?
余额可到美团网(meituan.com)——“我的美团→美团余额”里提取到您的银行卡或者支付宝账号,另外,余额也可直接用于支付外卖订单(限支持在线支付的商家)Q:余额提现到账时间是多久?
1-7个工作日内可退回您的支付账户。由于银行处理可能有延迟,具体以账户的到账时间为准。Q:申请退款后,商家拒绝了怎么办?
申请退款后,如果商家拒绝,此时回到订单页面点击“退款申诉”,美团客服介入处理。Q:怎么取消退款呢?
请在订单页点击“不退款了”,商家还会正常送餐的。Q:前面下了一个在线支付的单子,由于未付款,订单自动取消了,这单会计算我的参与活动次数吗?
不会。如果是未支付的在线支付订单,可以先将订单取消(如果不取消需要15分钟后系统自动取消),订单无效后,此时您再下单仍会享受活动的优惠。Q:为什么我用微信订餐,却无法使用在线支付?
目前只有网页版和美团外卖手机App(非美团手机客户端)订餐,才能使用在线支付,请更换到网页版和美团外卖手机App下单。Q:如何进行付款?
美团外卖现在支持货到付款与在线支付,其中微信版与手机触屏版暂不支持在线支付。Q:如何查看可以在线支付的商家?
你可以在商家列表页寻找带有“付”标识的商家,提交订单时可以选择支付方式。Q:美团外卖支持哪些支付方式?
现已支持美团余额、支付宝、网银(储蓄卡、信用卡)。Q:在线支付订单如何退款?
商家接单前,您可以直接取消订单,订单金额会自动退款到美团余额;商家接单后,您在点击“申请退款”,在线申请。提交退款申请之后,商家有24小时处理您的退款申请。商家同意退款,或24小时内没有处理您的退款申请,您的支付金额会退款至您的美团余额。Q:在线支付的过程中,订单显示未支付成功,款项却被扣了,怎么办?
出现此问题,可能是银行/支付宝的数据没有即时传输至美团,请您不要担心,稍后刷新页面查看。 如半小时后仍显示"未付款",请先联系银行/支付宝客服,获取您扣款的交易号,然后致电美团外卖客服4008507777,我们会协助您解决。Q:哪些商家有优惠?都有些什么优惠?
有优惠的商家在商家列表页均含有优惠标识;具体的优惠可以查看活动详情或者商家详情页中的描述。Q:在新用户享受的优惠中,新用户的条件是什么?
新用户是指第一次在美团外卖下单的用户(同一设备、同一手机号、同一账户仅可享受一次)。Q:我达到了满赠、满减的优惠的金额,为什么没有享受相关的优惠?
满赠与满减优惠是以订单内菜品的总额来计算的,不包含配送费与包装费。Q:超时赔付是什么意思?
超时赔付模式即:商家承诺一个送达时间和一个折扣,从用户下单时间开始计算,如果外卖超过了承诺时间才送到,该份外卖按照折扣价收取费用。由于恶劣天气、某些美食烹调时间过长、或者其他因素,商家会选择性的延长承诺时间或者不做承诺。预订单不参与超时赔付。Q:为什么提示我“账户存在异常,无法下单”?
包含(但不仅限于)以下行为者,系统将自动予以封禁(客服无权解封):i)有过虚假交易(编造不存在真实买卖的订单);ii)有过恶意下单行为;Q:如何取消订单?
如果商家尚未接单,您可以在订单详情页通过“取消订单”功能进行取消;如果商家已接单,则需要您电话联系后由商家取消订单。Q:我的订单为什么被取消了?
如果商家5分钟未接您的订单,为了保障您的权益,系统将会为您自动取消订单;商家接单后可能由于无法联系到您、菜品售完等原因无法配送,因而取消了您的订单,具体原因可查看系统发送的短信或通知。Q:如何进行催单?
您可以在订单状态页面点击“电话催单”按钮向商家商家催单。Q:刚下单发现信息填错了怎么办?
如果商家尚未接单,您可以自主取消订单;如果商家已经接单,您可以电话联系商家后由对方取消订单。然后重新下一单。Q:我的订单是否被商家确认?
App用户可以在商家确认您的订单时收到推送通知,并且订单状态会实时更新;手机触屏版及微信用户可以刷新订单状态页查看。Q:预计送达的时间为什么与我实际收餐的时间不符?
预计送达时间是系统根据用户评价的时间进行综合计算而得到的参考时间,餐厅的实际配送时间会受到当天的天气、订单量等外界因素影响。Q:为什么会出现无法下单的情况?
无法下单有很多情况,可能是菜品售完、餐厅不在营业时间等,请查看无法下单时给的提示。Q:为什么提示下单次数过多,已无法下单?
同一手机号在同一设备上一天最多可以成功提交7次订单(在线支付以完成支付为准,货到付款以提交订单为准)。Q:如果对商家服务不满意如何进行投诉?
您可以在该订单完成评价后点击订单详情页中的意见反馈向客服投诉,或者拨打美团外卖的客服电话(400-850-7777)向客服进行投诉。Q:如何联系客服解决问题?
您可以拨打美团外卖的客服电话(400-850-7777)或者在“我的”——>“意见反馈”页面提交反馈。Q:我用的是手机客户端,为什么无法定位?
请先检查手机的网络以及是否开启定位功能。若确认正常,请试着在户外或wifi环境下进行定位。Q:如何修改自己的账户信息?
美团外卖使用的是美团账号,您可以在“我的”页面修改个人账号信息,也可以在美团网账号页面修改个人账号。Q:为什么有时需要输入短信验证码?
为了保障您的账号安全及商家利益,对于新用户及一些有异常行为的下单系统会提示您输入短信验证码。如果迟迟未接收到短信验证码,您同样可以选择接听语音验证码。

文档切分

langchain有专门的切分工具CharacterTextSplitter,之所以切分不到31个块,是因为会首先保证在chunk_size字符内最大字符,然后根据separator字符进行切分,chunk_overlap是作为保留上下文信息交叉部分保留字符数量(也有其他办法,比如对用LLM对前文进行一次总结)

from langchain_text_splitters import CharacterTextSplitter
# 切分⽂档  块的内容限制在500字符以内  块与块之间有重叠  重叠的字符数为0  分隔符为两个换行符  保留换行符
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=0,separator="\n\n",keep_separator=True)
segments = text_splitter.split_documents(documents)
print(len(segments))
for segment in segments:print(segment.page_content)print("--------")

chain逻辑

chain都是从左到右运行,一共有以下部分组成

  • 输入映射部分:一个字典,负责处理和映射输入数据。
  • 提示词模板部分prompt_template,把处理后的输入数据填充到提示词模板里。
  • 大语言模型部分llm,依据提示词模板生成的提示信息生成回答。
  • 输出解析部分StrOutputParser(),将大语言模型的输出解析成字符串。

第一个字典里,"context":itemgetter("question") | retriever | collect_documents是为了将用户问题与向量数据库进行匹配,匹配到合适的文本块,作为“context”的内容

chain = ({"context":itemgetter("question") | retriever | collect_documents,   # 这行是用retriever召回用户问题相关的document"question":itemgetter("question")}|prompt_template|llm|StrOutputParser()
)

遇到的坑

使用docker和resp.app一起存储信息时,第一次按照大模型之Langchain篇——基础操作-CSDN博客没有出现什么问题,重启电脑之后发现报错,显示ResponseError: unknown command 'MODULE'Cell Execution Error

原因是因为resp.app版本太低,而docker镜像的版本没问题,此时电脑中有两个redis程序,用RedisVectorStore时识别到了低版本的resp.app,而没有用docker镜像的版本。按照以下操作解决

详细步骤如下:

  1. 找到并停止所有非 Docker 的 Redis 实例:

    • Windows 操作系统上

      • 打开任务管理器 (Ctrl + Shift + Esc)。

      • 切换到“服务”选项卡。

      • 查找名称中包含 "redis" 的服务。如果有,右键点击并选择“停止”。

      • 切换到“详细信息”选项卡。

      • 查找 redis-server.exe 进程。如果存在,选中它并点击“结束任务”。

      • 如果您是在 WSL2 中运行的 Linux 子系统,也需要检查 WSL2 中是否有其他 Redis 进程。

  2. 停止并删除任何可能存在问题的 Docker 容器: 打开您的命令行(cmd.exe 或 PowerShell):

    Bash
    docker stop redis-stack
    docker rm redis-stack
    

    (如果您之前没有设置持久化,这会丢失上次的数据。后续我们会解决这个问题。)

  3. (可选但推荐)删除旧的 Redis Stack Docker 镜像: 这可以确保您拉取到最新且健康的镜像。

    Bash
    docker rmi redis/redis-stack:latest
    
  4. 重新启动带有持久化卷的 Redis Stack Docker 容器: 使用以下命令,它不仅启动容器,还设置了数据持久化,这样以后重启就不会丢失数据了。

    Bash
    docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 \-v redis-stack-data:/data \ # <-- 这一行非常重要,用于持久化数据redis/redis-stack:latest
    
  5. 验证 Docker 容器中的 Redis 版本和模块: 等待几秒钟让容器完全启动。然后,执行以下命令进入容器内部的 Redis CLI 并检查模块列表:

    Bash
    docker exec -it redis-stack redis-cli
    MODULE LIST
    

    这次,您必须看到输出中包含 search 模块。 并且您也可以输入 INFO server 来确认 Redis 版本是 7.x (或更新的版本),而不是 3.x。

  6. 在 RESP.app 中连接: 现在,打开 RESP.app,确保连接配置是 localhost:6379。连接成功后,RESP.app 应该会显示 Redis 版本是 7.x (或更高),并且您应该能在其界面中看到 RediSearch 相关的索引管理选项(尽管不直接显示为 search 模块名称,但其功能会体现在 RESP.app 对 Redis Stack 的支持上)。

  7. 再次运行您的 Python 代码: 如果前面的所有步骤都成功,并且 MODULE LIST 确认了 search 模块的存在,那么您的 Python 代码应该能正常运行,不再报错 unknown command 'MODULE'

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

相关文章:

  • SQL的初步学习(二)(以MySQL为例)
  • 《区间dp》
  • Excalidraw:一款颠覆传统思维的免费开源绘图工具
  • DHS及HTTPS工作过程
  • JSON/AJAX/XHR/FetchAPI知识点学习整理
  • 代码随想录算法训练营第三十二天|动态规划理论基础、LeetCode 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
  • std::sort的核心设计思想
  • 代码随想录算法训练营第十七天
  • MongoDB数据基本介绍
  • 从 Intel MacBook 迁移到 ARM MacBook 的完整指南
  • Windows怎样同步时间服务器?
  • 【网络实验】-BGP选路原则-11条
  • 攻防世界——Web题 very_easy_sql
  • 嵌入式 Linux开发环境构建之安装 SSH 软件
  • Spring AI 项目实战(十六):Spring Boot + AI + 通义万相图像生成工具全栈项目实战(附完整源码)
  • mapstruct与lombok冲突原因及解决方案
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 44(题目+回答)
  • vue2入门(1)vue核心语法详解复习笔记
  • Agent篇
  • [Linux入门 ] RAID存储技术概述
  • 面向对象设计模式详解
  • 基于 STM32H743VIT6 的边缘 AI 实践:猫咪叫声分类 CNN 网络部署实战(已验证)中一些bug总结
  • OSPF 基础实验
  • 项目合作复盘:如何把项目经验转化为可复用资产
  • pthread_mutex_unlock函数的概念和用法
  • [办公及工程版浏览器]_Google Chrome 138.0.7204.101全屏启动插件
  • 专业PPT图片提取工具,操作简单
  • 欧拉系统安装UKUI桌面环境
  • spring--xml注入时bean的property属性
  • CentOS 7 升级系统内核级库 glibc 2.40 完整教程