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

在 crag 中用 LangGraph 进行评分知识精炼-下

在上一次给大家展示了基本的 Rag 检索过程,着重描述了增强检索中的知识精炼和补充检索,这些都是 crag 的一部分,这篇内容结合 langgraph 给大家展示通过检索增强生成(Retrieval-Augmented Generation, RAG)的工作流,来处理问题并生成答案。
好了,下面我们直接开始代码。

定义graph

首先我们还是先定义 web 搜索工具,这里的 web 搜索工具作为补充检索很重要:

### Search
from langchain_community.tools.tavily_search import TavilySearchResultsweb_search_tool = TavilySearchResults(k=3)

然后定义我们 graph 的基本状态结构:

from typing import List
from typing_extensions import TypedDict
class GraphState(TypedDict):"""表示我们图的状态。属性:question: 问题generation: 大语言模型生成的内容web_search: 是否使用web搜索documents: 检索出来的文档列表"""question: strgeneration: strweb_search: strdocuments: List[str]

定义工作流节点

定义检索与问题相关的文档的节点:

def retrieve(state):"""检索文档参数:state (dict): 当前图状态返回:state (dict): 更新后的状态,包含检索到的文档"""print("---RETRIEVE---")question = state["question"]# 檢索相关文档documents = retriever.get_relevant_documents(question)return {"documents": documents, "question": question}

定义基于检索到的文档生成答案的节点:

def generate(state):"""生成答案参数:state (dict): 当前图状态返回:state (dict): 更新后的状态,包含生成的答案"""print("---GENERATE---")question = state["question"]documents = state["documents"]# RAG generationgeneration = rag_chain.invoke({"context": documents, "question": question})return {"documents": documents, "question": question, "generation": generation}

定义评估检索到的文档是否与问题相关的节点:

def grade_documents(state):"""评估检索到的文档是否与问题相关参数:state (dict): 当前图状态返回:state (dict): 更新后的状态,仅包含相关文档"""print("---CHECK DOCUMENT RELEVANCE TO QUESTION---")question = state["question"]documents = state["documents"]# Score each docfiltered_docs = []web_search = "No"for d in documents:score = retrieval_grader.invoke({"question": question, "document": d.page_content})grade = score.binary_scoreif grade == "yes":print("---GRADE: DOCUMENT RELEVANT---")filtered_docs.append(d)else:print("---GRADE: DOCUMENT NOT RELEVANT---")web_search = "Yes"continuereturn {"documents": filtered_docs, "question": question, "web_search": web_search}

重写问题以生成更好的查询:

def transform_query(state):"""重写问题以生成更好的查询参数:state (dict): 当前图状态返回:state (dict): 更新后的状态,包含重写后的问题"""print("---TRANSFORM QUERY---")question = state["question"]documents = state["documents"]# Re-write questionbetter_question = question_rewriter.invoke({"question": question})return {"documents": documents, "question": better_question}

基于重写后的问题进行网络搜索,并将结果添加到文档列表中。

def web_search(state):"""基于重写后的问题进行网络搜索参数:state (dict): 当前图状态返回:state (dict): 更新后的状态,包含网络搜索结果"""print("---WEB SEARCH---")question = state["question"]documents = state["documents"]# Web searchdocs = web_search_tool.invoke({"query": question})web_results = "\n".join([d["content"] for d in docs])web_results = Document(page_content=web_results)documents.append(web_results)return {"documents": documents, "question": question}

最后定义我们的条件边,决定是生成答案还是重写问题。

def decide_to_generate(state):"""决定是生成答案还是重写问题参数:state (dict): 当前图状态返回:str: 下一个节点的决策("transform_query" 或 "generate")"""print("---ASSESS GRADED DOCUMENTS---")# state["question"]web_search = state["web_search"]# state["documents"]if web_search == "Yes":# All documents have been filtered check_relevance# We will re-generate a new queryprint("---DECISION: ALL DOCUMENTS ARE NOT RELEVANT TO QUESTION, TRANSFORM QUERY---")return "transform_query"else:# We have relevant documents, so generate answerprint("---DECISION: GENERATE---")return "generate"

这里我们稍微等一下,做个小总结,上面定义的一系列的工作流节点主要是下面几个用途:

1.检索文档: 调用 retrieve 函数,获取与问题相关的文档。
2:评估文档相关性: 调用 grade_documents 函数,过滤掉不相关的文档。
3:决定下一步:如果所有文档都不相关,调用 transform_query 重写问题,然后进行网络搜索(web_search)。如果有相关文档,调用 generate 生成答案。生成答案: 调用 generate 函数,基于相关文档生成最终答案。

创建工作流

我们把上面定义好的节点和边组织在一起:

from langgraph.graph import END, StateGraph, START# 创建工作流
workflow = StateGraph(GraphState)# 定义节点
workflow.add_node("retrieve", retrieve)  # 检索文档
workflow.add_node("grade_documents", grade_documents)  # 评估文档相关性
workflow.add_node("generate", generate)  # 生成答案
workflow.add_node("transform_query", transform_query)  # 重写问题
workflow.add_node("web_search_node", web_search)  # 网络搜索# 构建工作流
workflow.add_edge(START, "retrieve")  # 从 START 到 retrieve
workflow.add_edge("retrieve", "grade_documents")  # 从 retrieve 到 grade_documents
workflow.add_conditional_edges("grade_documents",  # 从 grade_documents 出发decide_to_generate,  # 根据 decide_to_generate 的返回值决定下一步{"transform_query": "transform_query",  # 如果返回 "transform_query",跳转到 transform_query 节点"generate": "generate",  # 如果返回 "generate",跳转到 generate 节点},
)
workflow.add_edge("transform_query", "web_search_node")  # 从 transform_query 到 web_search_node
workflow.add_edge("web_search_node", "generate")  # 从 web_search_node 到 generate
workflow.add_edge("generate", END)  # 从 generate 到 END# 编译工作流
app = workflow.compile()from IPython.display import display, Image
display(Image(graph.get_graph().draw_mermaid_png()))

得到下面的图形化结果:
在这里插入图片描述
我们这里就完成了整个工作流的逻辑框架,下面我们来调用这个 graph 试一下,看能得出什么结果:

from pprint import pprintinputs = {"question": "agent memory 的类型有哪些?"}
for output in graph.stream(inputs):for key, value in output.items():# Nodepprint(f"Node '{key}':")pprint(f"value '{value}':")pprint("\n---\n")

在这里插入图片描述
我们分析执行流程日志就可以发现,我们采用一个基于状态的工作流 (StateGraph),通过不同的节点和边来处理问题并生成答案的方式串联起了我们 crag 的整个流程,然后可以看到它是怎么来进行检索,然后怎么来调用工具的,到最后怎么完成知识精炼和补充,然后大模型返回给我们增强后的答案。大家可以根据上面的代码自己试一下。

相关文章:

在 crag 中用 LangGraph 进行评分知识精炼-下

在上一次给大家展示了基本的 Rag 检索过程,着重描述了增强检索中的知识精炼和补充检索,这些都是 crag 的一部分,这篇内容结合 langgraph 给大家展示通过检索增强生成(Retrieval-Augmented Generation, RAG)的工作流&am…...

基于springboot+vue的哈利波特书影音互动科普网站

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...

Cypher入门

文章目录 Cypher入门创建数据查询数据matchoptional matchwhere分页with 更新数据删除数据实例:好友推荐 Cypher入门 Cypher是Neo4j的查询语言。 创建数据 在Neo4j中使用create命令创建节点、关系、属性数据。 create (n {name:$value}) return n //创建节点&am…...

使用Z-score进行数据特征标准化

数据标准化是数据处理过程中非常重要的一步,尤其在构建机器学习模型时尤为关键。标准化的目的是将不同量纲的变量转换到相同的尺度,以避免由于量纲差异导致的模型偏差。Z-score标准化是一种常见且简单的标准化方法,它通过计算数据点与平均值的差异,并将其按标准差进行缩放,…...

初级数据结构:栈和队列

一、栈 (一)、栈的定义 栈是一种遵循后进先出(LIFO,Last In First Out)原则的数据结构。栈的主要操作包括入栈(Push)和出栈(Pop)。入栈操作是将元素添加到栈顶,这一过程中&#xf…...

【思维导图】java

学习计划:将目前已经学的知识点串成一个思维导图。在往后的学习过程中,不断往思维导图里补充,形成自己整个知识体系。对于思维导图里的每个技术知识,自己用简洁的话概括出来, 训练自己的表达能力。 面向对象三大特性 …...

Redis脑裂问题详解及解决方案

Redis是一种高性能的内存数据库,广泛应用于缓存、消息队列等场景。然而,在分布式Redis集群中,脑裂问题(Split-Brain)是一个需要特别关注的复杂问题。本文将详细介绍Redis脑裂问题的成因、影响及解决方案。 一、什么是…...

玩转大语言模型——配置图数据库Neo4j(含apoc插件)并导入GraphRAG生成的知识图谱

系列文章目录 玩转大语言模型——使用langchain和Ollama本地部署大语言模型 玩转大语言模型——ollama导入huggingface下载的模型 玩转大语言模型——langchain调用ollama视觉多模态语言模型 玩转大语言模型——使用GraphRAGOllama构建知识图谱 玩转大语言模型——完美解决Gra…...

【Windows Server实战】生产环境云和NPS快速搭建

前置条件 本文假定你已达成以下前提条件: 有域控DC。有证书服务器(AD CS)。已使用Microsoft Intune或者GPO为客户机申请证书。服务器上至少有两张网卡(如果用虚拟机做的测试环境,可以用一张HostOnly网卡做测试&#…...

[ESP32:Vscode+PlatformIO]新建工程 常用配置与设置

2025-1-29 一、新建工程 选择一个要创建工程文件夹的地方,在空白处鼠标右键选择通过Code打开 打开Vscode,点击platformIO图标,选择PIO Home下的open,最后点击new project 按照下图进行设置 第一个是工程文件夹的名称 第二个是…...

【NLP251】Transformer精讲 残差链接与层归一化

精讲部分,主要是对Transformer的深度理解方便日后从底层逻辑进行创新,对于仅应用需求的小伙伴可以跳过这一部分,不影响正常学习。 1. 残差模块 何凯明在2015年提出的残差网络(ResNet),Transformer在2016年…...

康德哲学与自组织思想的渊源:从《判断力批判》到系统论的桥梁

康德哲学与自组织思想的渊源:从《判断力批判》到系统论的桥梁 第一节:康德哲学中的自然目的论与自组织思想 核心内容: 康德哲学中的自然目的论和反思判断力概念,为现代系统论中的自组织思想提供了哲学基础,预见了复…...

SpringBoot 整合 SpringMVC:SpringMVC的注解管理

分类&#xff1a; 中央转发器(DispatcherServlet)控制器视图解析器静态资源访问消息转化器格式化静态资源管理 中央转发器&#xff1a; 中央转发器被 SpringBoot 自动接管&#xff0c;不需要我们在 web.xml 中配置&#xff1a; <servlet><servlet-name>chapter2&l…...

松灵机器人 scout ros2 驱动 安装

必须使用 ubuntu22 必须使用 链接的humble版本 #打开can 口 sudo modprobe gs_usbsudo ip link set can0 up type can bitrate 500000sudo ip link set can0 up type can bitrate 500000sudo apt install can-utilscandump can0mkdir -p ~/ros2_ws/srccd ~/ros2_ws/src git cl…...

使用 Numpy 自定义数据集,使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数

1. 导入必要的库 首先&#xff0c;导入我们需要的库&#xff1a;Numpy、Pytorch 和相关工具包。 import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import accuracy_score, recall_score, f1_score2. 自定义数据集 …...

MapReduce简单应用(一)——WordCount

目录 1. 执行过程1.1 分割1.2 Map1.3 Combine1.4 Reduce 2. 代码和结果2.1 pom.xml中依赖配置2.2 工具类util2.3 WordCount2.4 结果 参考 1. 执行过程 假设WordCount的两个输入文本text1.txt和text2.txt如下。 Hello World Bye WorldHello Hadoop Bye Hadoop1.1 分割 将每个文…...

c语言(关键字)

前言&#xff1a; 感谢b站鹏哥c语言 内容&#xff1a; 栈区&#xff08;存放局部变量&#xff09; 堆区 静态区&#xff08;存放静态变量&#xff09; rigister关键字 寄存器&#xff0c;cpu优先从寄存器里边读取数据 #include <stdio.h>//typedef&#xff0c;类型…...

蓝桥杯思维训练营(一)

文章目录 题目总览题目详解翻之一起做很甜的梦 蓝桥杯的前几题用到的算法较少&#xff0c;大部分考察的都是思维能力&#xff0c;方法比较巧妙&#xff0c;所以我们要积累对应的题目&#xff0c;多训练 题目总览 翻之 一起做很甜的梦 题目详解 翻之 思维分析&#xff1a;一开…...

【C语言】结构体对齐规则

文章目录 一、内存对齐规则二、结构体的整体对齐&#xff1a; 一、内存对齐规则 1.第一个数据成员&#xff1a;结构体的第一个数据成员总是放置在其起始地址处&#xff0c;即偏移量为0的位置。 2.其他数据成员的对齐&#xff1a;每个后续成员的存储地址必须是其有效对齐值的整…...

2025-工具集合整理

科技趋势 github-rank &#x1f577;️Github China/Global User Ranking, Global Warehouse Star Ranking (Github Action is automatically updated daily). 科技爱好者周刊 制图工具 D2 D2 A modern diagram scripting language that turns text to diagrams 文档帮助 …...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...