1. 引言

**检索增强生成(RAG)**是指通过检索对大模型生成进行增强的技术,通过充分利用信息检索(尤其是语义检索)相关技术,实现大模型快速扩展最新知识、有效减少幻觉的能力。主流RAG框架包括问题理解、知识检索、知识选择/重排、答案生成等几个过程,并且通常来说这几个步骤是顺序执行的(pipeline),如下图(图片引用自https://medium.com/@mayssamayel4/building-a-rag-system-with-gpt-4-a-step-by-step-guide-291711342f0d)所示:
RAG流程图
继RAG之后,研究人员提出了DeepSearch技术,主要是针对RAG的单轮串行流程可能无法进行准确回答的问题,提出通过多轮的问题扩展、检索、上下文判别的方式,实现对问题更加完整、准确的回答。DeepSearch流程不是顺序的pipeline,而是循环流程,如下图(图片引用自https://milvus.io/zh/blog/introduce-deepsearcher-a-local-open-source-deep-research.md)所示。
DeepSearch流程图
循环流程是指包含重复执行环节的流程。通常来说,普通的数据处理——也就是常见的ETL任务——都是线性流程,包括读取、转换、过滤、抽取、入库等流程节点,他们按照业务要求组合成完整流程,每条数据像水流一样按照顺序“流”经每一个节点。循环流程则能够基于指定的循环是否终止的判定,对指定的子流程进行重复执行。

SmartETL框架作为一个ETL框架,此前未考虑循环流程。DeepSearch的流程虽然通常是用于问答助手这类应用,但其实也可以用于实现基于大模型的数据处理,例如数据集构造大模型蒸馏等。因此有必要在框架中增加循环流程的流程控制逻辑。

2.循环流程控制设计

新设计一个特殊的processor组件,命名为While,将可能循环的子流程(对应代码中的循环体)交给While组件托管,在所给定的条件(匹配或过滤节点)符合时执行子流程。

While组件的构造参数包括:

  1. 循环子流程,是另一个Process组件,通常为Chain串联的一套流程
  2. 匹配条件,一个函数或函数式对象(实现了__call__方法的类的对象),或者提供一个字段名,如果这个字段的值不为空,表示条件满足
  3. 最大迭代次数,避免进入死循环,且方便评估和控制流程的整体时延。

While组件重写了__process__方法,这是实现流程循环的关键。简单地说,在每一次迭代中,对每一条输入数据,检查匹配条件是否满足,如果满足则执行指定的子流程,并收集子流程的输出数据作为当前迭代的输出数据(子流程可能产生多条输出,比如包含Flat操作)。如果匹配条件不满足,需要注意,这里要将上一次迭代的输出数据(或整个While循环的输入)作为整个While循环的输出,以确保符合循环流程的逻辑。

下图是一个对比普通过滤节点与循环节点的示意图,流程均为Chain(A, B, C)。在上半部分,数据通过节点B(普通节点或过滤节点)时,如果输出为None(即没有输出),则当前处理流程结束,否则数据传输给节点C。在下半部分中,B节点是一个循环节点,如果循环条件不满足,则数据直接传输给节点C,否则将B的子流程的输出数据传输给节点C。
普通节点与循环节点对比

3.DeepSearch应用

DeepSearch应用的处理过程可以看成一种对输入问题进行循环处理,最终输出问题答案的数据处理流程。利用循环流程机制,SmartETL可以实现DeepSearch应用,下面介绍这个流程是如何设计的。

首先,需要设计一种数据结构,对DeepSearch的各个阶段的状态进行统一表示。因为ETL框架与普通的编程语言或运行时环境不一样,ETL流程是以数据为驱动的,每个节点除了自身的配置信息(也称为组件的环境信息)和当前处理数据以外,通常无法获得全局信息。SmartETL也在考虑加入某种获取全局信息的机制。数据结构设计如下:

{“original_query”: “user query”, //原始查询“gap_queries”: [“query1”, “query2”], //当前的差距查询列表 最初由原始查询提示生成,后续通过提示大模型基于original_query、all_sub_queries和all_chunks生成“chunks”: [{“text”: “doc1”}], //当前查询的检索结果文档列表 基于当前gap_queries语义化检索得到“all_chunks”: [{“text”: “doc1”}, {“text”: “doc2”}], //当前已收集的全部相关文档 持续合并chunks相关的得到“all_sub_queries”: [“sub1”, “sub2”], //当前全部子查询 不断合并gap_queries得到“answer”: “xxxx” //最终答案 通过original_query、all_sub_queries和all_chunks提示给大模型进行生成
}

第二,流程设计。将整个流程划分为3个阶段,如下图所示:
在这里插入图片描述
阶段1:初始化阶段,初始化all_chunksall_sub_queries字段为空列表,并通过提示大模型生成最初的gap_queries

阶段2:循环流程阶段,包括检索判定反思3个具体过程。检索过程对当前gap_queries进行向量化并检索,获得一批候选文档chunks。判定过程对当前候选文档进行相关性判定,相关的文档会合并到all_chunks中。反思过程是基于当前的original_queryall_sub_queriesall_chunks,提示大模型进行推理思考,确定是否还需要进一步搜索,得到的结果作为新的gap_queries字段,但为了保存全部子查询,这里在生成新的gap_queries之前,将gap_queries合并到all_sub_queries中。

阶段3:基于当前的original_queryall_sub_queriesall_chunks,提示大模型进行答案生成。虽然阶段2可以执行多次以尽量获得答案,但是也必须有限制,在达到迭代次数限制或Token超限之后,尽管没有获得完全足够的上下文信息,也需要让大模型进行生成,避免输出空的答案。

第三,流程yaml文件编写。基于已有的数据结构和流程设计,整个流程实现已经变得较为容易了。

不过存在一个问题:在阶段2中,需要多次对批量数据进行处理,包括对gap_queries进行向量化、基于向量化结果进行检索、对检索结果进行相干性判定。SmartETL框架已有的向量化、大模型调用等组件的设计不支持批量处理,并且这里需要进行逻辑对应,需要逐个gap_query进行向量化、检索相关文档,然后对结果文档逐个进行相关性判定,过滤掉不相关文档,最后把对应同一个原始查询的结果进行聚合,以便在阶段3进行答案生成。为了实现这个目的,在不增加批量处理算子的情况下,通过扁平化(Flat)聚合(Group by)分组收集操作,实现批处理。修改后的数据结果如下所示:

{“original_query”: “user query”, //原始查询“gap_queries”: [“query1”, “query2”], //当前的差距查询列表 最初由原始查询提示生成,后续通过提示大模型基于original_query、all_sub_queries和all_chunks生成“all_chunks”: [{“text”: “doc1”}, {“text”: “doc2”}], //当前已收集的全部相关文档 持续合并chunks相关的得到“all_sub_queries”: [“sub1”, “sub2”], //当前全部子查询 不断合并gap_queries得到“answer”: “xxxx”, //最终答案 通过original_query、all_sub_queries和all_chunks提示给大模型进行生成“sub_query”: “sub1”, //当前的一个子查询“sub_query_vector”: [0.5, 0.3, .... ], //当前子查询对应向量 基于sub_query向量化“chunks”: [{“text”: “doc1”}], //当前子查询的检索结果文档列表 基于sub_query_vector的语义检索“chunk”: {“text”: “doc1”}, //当前的一篇文档“selected”: true, //当前文档是否与问题相关 基于提示大模型进行相关性判定“chunks_selected”: [{“text”: “doc2”}] //当前检索结果中相关的文档
}

4.总结

本文面向DeepSearch应用的迭代处理需求,基于SmartETL框架设计了循环流程控制,使得支持部分子流程的循环处理。通过设计DeepSearch流程,验证了循环流程的有效性,并为其他具有循环结构的数据处理流程提供了参考。

附录

  1. SmartETL项目地址:https://github.com/ictchenbo/SmartETL
  2. 循环流程控制节点代码:https://github.com/ictchenbo/SmartETL/blob/main/wikidata_filter/iterator/flow_control.py
  3. 基于SmartETLDeepSearch应用流程:https://github.com/ictchenbo/SmartETL/blob/main/flows/agent/deepsearch-v2.yaml
  4. 实现DeepSearch应用的所有大模型提示模板可以在这里找到:https://github.com/ictchenbo/SmartETL/blob/main/config/prompt/deepsearch
  5. Jina-DeepSearch实施指南:https://jina.ai/news/a-practical-guide-to-implementing-deepsearch-deepresearch/

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

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

相关文章

uni-app开发小程序,根据图片提取主题色值

需求&#xff0c;在页面根据传入的图片提取图片主色值并用来设置区块背景色<template><view class"icon-container"><view class"sport-icon" :style"{ backgroundColor: mainColor }"><image :src"/static/images/sp…

ESP32-Cam三脚架机器人:DIY你的智能移动监控平台

项目概述 在物联网与机器人技术融合发展的今天&#xff0c;基于ESP32的创意项目层出不穷。今天为大家介绍一款极具创新性的ESP32-Cam三脚架机器人&#xff08;Dodge&#xff09;&#xff0c;它将传统三脚架结构与智能监控功能完美结合&#xff0c;通过巧妙的机械设计和开源硬件…

Kotlin集合过滤

过滤操作 在处理集合时&#xff0c;根据特定条件过滤集合或检查集合中是否包含符合特定条件的元素是软件开发中的常见任务。为了解决这个问题&#xff0c;我们可以使用 Kotlin 中实现的函数式 API。 在本主题中&#xff0c;我们将介绍如何使用谓词过滤集合&#xff0c;并获得满…

14.8 LLaMA2-7B×Dolly-15K实战:从准确率63%到89%,如何用优质数据让大模型性能飙升42%?

LLaMA2-7BDolly-15K实战:从准确率63%到89%,如何用优质数据让大模型性能飙升42%? 在大模型微调中,“数据质量”往往比“数据数量”更能决定最终效果。Databricks发布的Dolly-15K数据集以“全人工标注+多维度校验”的特点,成为指令微调的“黄金样本”——用它微调后的LLaMA…

OpenCV中常用特征提取算法(SURF、ORB、SIFT和AKAZE)用法示例(C++和Python)

OpenCV 中提供了多种常用的特征提取算法&#xff0c;广泛应用于图像匹配、拼接、SLAM、物体识别等任务。以下是 OpenCV 中几个主流特征提取算法的 用法总结与代码示例&#xff0c;涵盖 C 和 Python 两个版本。常用特征提取算法列表算法特点是否需额外模块SIFT&#xff08;尺度不…

复杂度+包装类型+泛型

什么是集合框架什么是数据结构什么是算法时间复杂度与空间复杂度的概念时间复杂度的表达方式时间复杂度的大 O 的渐近表示法时间复杂度函数的大小排序包装类和泛型基本数据类型和对应的包装类型包装类型出现的原因什么叫做装箱&#xff08;装包&#xff09;和拆箱&#xff08;拆…

硬件设计学习DAY15——自举电容:MOSFET高端驱动的核心奥秘

每日更新教程&#xff0c;评论区答疑解惑&#xff0c;小白也能变大神&#xff01;" 目录 一.自举电容 1.自举电容的作用 2.自举电路原理 3.工作过程分析 4.实际应用中的问题 5.关键要点 二.自举电容实现MOSFET高端驱动 2.1MOSFET半桥高端驱动的基本原理 2.2自举电…

【SpringAI实战】实现仿DeepSeek页面对话机器人

一、实现效果 二、代码实现 2.1 后端代码 2.2 前端代码 一、实现效果 可以保存聊天记录与会话记录 二、代码实现 2.1 后端代码 pom.xml <!-- 继承Spring Boot父POM&#xff0c;提供默认依赖管理 --><parent><groupId>org.springframework.boot</grou…

RedisJSON 指令精讲JSON.STRLEN 高效统计字符串长度

1 场景与价值 在日志累加、指标采集、消息追踪等场景中&#xff0c;我们常需快速判断某个字符串字段“到底有多长”&#xff0c;以便&#xff1a; 阻止过大日志&#xff1a;若长度超限则截断或归档&#xff1b;动态分桶&#xff1a;按长度选择不同存储策略&#xff1b;性能监控…

大数据量查询计算引发数据库CPU告警问题复盘

大数据量查询计算引发数据库CPU告警问题复盘一、背景二、根因分析三、解决方案方案1&#xff1a;多线程缓存方案2&#xff1a;利用中间表缓存四、总结一、背景 2025年7月份某天&#xff0c;CDP系统每天不定时推送我们的Portal服务&#xff0c;生产环境运营看板会展示统计数据&…

2025最新版虚幻引擎5(UE5)C++入门教程:前言——你的随身教程和学习笔记

大家好&#xff0c;我是开发游戏的老王&#xff0c;一名高校教师&#xff0c;我主讲游戏开发已有十余年时间&#xff0c;通过我的博客大家应该可以了解我所涉猎的游戏技术范畴非常广泛&#xff0c;除了Unreal,Unity,Godot等主流游戏引擎&#xff0c;还包括Blender、Houdini、3D…

(3)重定向 | 时间相关指令 | 文件查找 | 打包与压缩

Ⅰ . 初始重定向01 输出重定向 >在上一节中我们为了方便讲解 head 和 tail 指令&#xff0c;我们用到了 > 去生成了一千行文本。通过 > 将生成的一千行文本写入到了 large.txt 中……我们现在来正式介绍一下&#xff1a;$ echo "内容" > [目标] 本来应…

DTH11测量温湿度学习(第十一天)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-削好皮的Pineapple! &#x1f468;‍&#x1f4bb; hello 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 削好皮的Pineapple! 原创 &#x1f468;‍&#x1f4…

Go语言初识--标识符 可见性

Go语言初识–标识符 可见性 和C语言相似&#xff0c;go语言的基本组成有&#xff1a; 包声明&#xff0c;编写源文件时&#xff0c;必须在非注释的第一行指明这个文件属于哪个包&#xff0c;如package main。引入包&#xff0c;其实就是告诉Go 编译器这个程序需要使用的包&…

Python实例之画小猪佩奇

效果图&#xff1a;python代码以及解释&#xff0c;没有运用模块。 """ 绘制小猪佩奇 """ from turtle import *def nose(x,y):"""画鼻子"""penup()# 将海龟移动到指定的坐标goto(x,y)pendown()# 设置海龟的方向&…

Unity笔记——事件中心

事件中心是什么事件中心是 Unity 游戏开发中常用的架构设计&#xff0c;它基于观察者模式 或 发布-订阅模式&#xff0c;通过委托和事件构建的一种消息管理系统。主要用于降低代码耦合度&#xff0c;实现模块间的松耦合通信的消息处理系统能大幅提升代码的可维护性和扩展性&…

Java: 反射机制的 ParameterizedType(参数化类型)

在 Java 中&#xff0c;ParameterizedType 是 java.lang.reflect 包下的一个接口&#xff0c;属于反射 API 的一部分&#xff0c;主要用于表示参数化类型&#xff08;即带有类型参数的泛型类型&#xff09;。它是 Java 反射机制中处理泛型类型信息的关键接口之一。 一、什么是参…

OkHttp 与 Retrofit 完美结合:打造高效的 Android 网络请求

前言在现代 Android 开发中&#xff0c;网络请求是几乎每个应用都必不可少的功能。OkHttp 和 Retrofit 作为当前最流行的网络请求库组合&#xff0c;为开发者提供了简洁高效的解决方案。本文将详细介绍如何将这两者结合使用&#xff0c;充分发挥它们的优势。一、OkHttp 和 Retr…

系统辨识建模

系统辨识建模 一、系统辨识建模的作用 1. 建立真实物理系统的数学模型 2. 为后续控制器/强化学习算法提供仿真环境 3. 提高控制精度和安全性 二、本文的系统辨识是怎么做的 1. 实验采集 2. 数学建模 3. 在控制系统中的作用 三、实际用法流程(简化版) 1. 系统辨识阶段 2. 强化…

Android开发:Java与Kotlin深度对比

1. 语言特性与现代性 Java (特别是 Android 主要使用的 Java 8 及之前版本): 相对冗长&#xff1a; 需要编写更多的样板代码&#xff08;如 getter/setter、findViewById 的显式类型转换、匿名内部类等&#xff09;。空指针异常 (NPE)&#xff1a; 类型系统默认允许 null&#…