Github 上 Star 数最多的大模型应用基础服务 Dify 深度解读(一)

背景介绍

接触过大模型应用开发的研发同学应该都或多或少地听过 Dify 这个大模型应用基础服务,这个项目自从 2023 年上线以来,截止目前(2024-6)已经获得了 35k 多的 star,是目前大模型应用基础服务中最热门的项目之一。这篇文章对 Dify 中核心的基础模块 RAG 服务进行深入解读,后续可能会更新其他模块的内容。

Dify 简介

Dify 是一个 LLMOps 服务, 涵盖了大语言模型(如GPT系列)开发、部署、维护和优化的一整套实践和流程。可以大幅简化大模型应用的开发。

基于 Dify 可以在不需要太多开发的情况下,快速搭建一个大模型应用。应用中可以调用 Dify 中内置的大量基础能力,比如知识库检索 RAG,大模型调用。通过可插拔式的组合构建大模型应用。一个典型的应用如下所示:
请添加图片描述

上面的场景中使用分类场景,RAG 服务以及大模型调用的基础模块,组合生成一个大模型应用。

RAG 核心流程

RAG 服务的基础流程在之前的 搭建离线私有大模型知识库 文章中已经介绍过了。RAG 服务的开源框架 有道 QAnything 和 Ragflow 也都解读过基础的 RAG 流程了,这部分就不详细展开了。一般情况下,RAG 服务会包含如下所示的功能模块:

  • 文件加载的支持;
  • 文件的预处理策略;
  • 文件检索的支持;
  • 检索结果的重排;
  • 大模型的处理;

因为 RAG 服务只是 Dify 中的一个基础模块,官方没有过多强调 RAG 服务的独特设计,但是依旧可以看到一个独特点:

  1. 支持 Q&A 模式,与上述普通的「Q to P」(问题匹配文本段落)匹配模式不同,它是采用「Q to Q」(问题匹配问题)匹配工作;
  2. 丰富的召回模式,支持 N 选 1 召回多路召回

下面的部分会对独特之处进行详细展开。

核心模块解读

之前介绍过来自中科院的 RAG 服务 GoMate 采取的是模块化设计,方便进行上层应用的组合。从目前的实现来看,Dify 的 RAG 设计也是采用模块化设计,RAG 的代码实现都在 api/core/rag 中,从代码结构上也很容易理解各个模块的作用:

请添加图片描述

深入来看代码的实现质量也比较高,对 RAG 的模块化设计感兴趣的可以深入了解下实现细节。

文件加载

Dify 的文件加载都是在 api/core/rag/extractor/extract_processor.py 中实现的,主要的文件解析是基于 unstructured 实现,另外基于其他第三方库实现了特定格式文件的处理

比如对于 pdf 文件,会基于 pypdfium2 进行解析,html 是基于 BeautifulSoup 进行解析,这部分代码实现都比较简单,就不展开介绍了。

文件预处理

加载的模型中的内容可能会存在一些问题,比如多余的无用字符,编码错误或其他的一些问题,因此需要对文件解析的内容进行必要的清理,这部分代码实现在 api/core/rag/cleaner 中。实际的清理都是基于 unstructured cleaning 实现的,Dify 主要就是将不同的清理策略封装为同样的接口,方便应用层自由选择。这部分实现也比较简单,感兴趣可以自行了解下。

Q&A 模式

Q&A 分段模式功能,与上述普通的「Q to P」(问题匹配文本段落)匹配模式不同,它是采用「Q to Q」(问题匹配问题)匹配工作,在文档经过分段后,经过总结为每一个分段生成 Q&A 匹配对,当用户提问时,系统会找出与之最相似的问题,然后返回对应的分段作为答案,实际的流程如下所示:

请添加图片描述

从上面的流程可以看到,Q&A 模式下会根据原始文档生成问答对,实现实现是在 api/core/llm_generator/llm_generator.py 中:

# 构造 promptGENERATOR_QA_PROMPT = ('<Task> The user will send a long text. Generate a Question and Answer pairs only using the knowledge in the long text. Please think step by step.''Step 1: Understand and summarize the main content of this text.\n''Step 2: What key information or concepts are mentioned in this text?\n''Step 3: Decompose or combine multiple pieces of information and concepts.\n''Step 4: Generate questions and answers based on these key information and concepts.\n''<Constraints> The questions should be clear and detailed, and the answers should be detailed and complete. ''You must answer in {language}, in a style that is clear and detailed in {language}. No language other than {language} should be used. \n''<Format> Use the following format: Q1:\nA1:\nQ2:\nA2:...\n''<QA Pairs>'
)def generate_qa_document(cls, tenant_id: str, query, document_language: str):prompt = GENERATOR_QA_PROMPT.format(language=document_language)model_manager = ModelManager()model_instance = model_manager.get_default_model_instance(tenant_id=tenant_id,model_type=ModelType.LLM,)# 拼接出完整的调用 promptprompt_messages = [SystemPromptMessage(content=prompt),UserPromptMessage(content=query)]# 调用大模型直接生成问答对response = model_instance.invoke_llm(prompt_messages=prompt_messages,model_parameters={'temperature': 0.01,"max_tokens": 2000},stream=False)answer = response.message.contentreturn answer.strip()

可以看到就是通过一个 prompt 就完成了原始文档到问答对的转换,可以看到大模型确实可以帮助实现业务所需的基础能力。

文件检索

知识库的检索是在 api/core/workflow/nodes/knowledge_retrieval/knowledge_retrieval_node.py 中实现的,与常规的 RAG 存在明显不同之处在于支持了丰富的召回模式。

丰富的召回模式

用户可以自由选择所需的召回模式:

请添加图片描述

  • N 选 1 召回:先根据用户输入的意图选择合适的知识库,然后从知识库检索所需的文档,适用于知识库彼此隔离,不需要互相联合查询的场景;
  • 多路召回:此时会同时从多个知识库检索,然后进行重新排序,适用于知识库需要联合查询的场景。

常规的 RAG 服务需要先手工选择知识库,然后从对应的知识库进行检索,无法支持跨库检索。相对而言,Dify 的这个设计还是要更方便一些。下面以 N 选 1 召回 为例介绍下文件的检索,对应的流程如下所示:

请添加图片描述

N 选 1 召回 的知识库选择是基于用户问题与知识库描述的语义匹配性来进行选择,存在 Function Call/ReAct 两种模式,实现代码在 api/core/rag/retrieval/dataset_retrieval.py 中,具体如下所示:

tools = []
# 根据用户输入的意图,使用知识库的描述构造 promptfor dataset in available_datasets:description = dataset.descriptionif not description:description = 'useful for when you want to answer queries about the ' + dataset.namedescription = description.replace('\n', '').replace('\r', '')message_tool = PromptMessageTool(name=dataset.id,description=description,parameters={"type": "object","properties": {},"required": [],})tools.append(message_tool)# 支持 ReAct 模式if planning_strategy == PlanningStrategy.REACT_ROUTER:react_multi_dataset_router = ReactMultiDatasetRouter()dataset_id = react_multi_dataset_router.invoke(query, tools, model_config, model_instance,user_id, tenant_id)
# 支持 Function Call 模式elif planning_strategy == PlanningStrategy.ROUTER:function_call_router = FunctionCallMultiDatasetRouter()dataset_id = function_call_router.invoke(query, tools, model_config, model_instance)
  • Function Call 模式就是构造了一个 prompt,让大模型根据描述选择合适的知识库,实现比较简单
  • ReAct 模式则是基于 ReAct , 通过推理 + 任务的结合选择正确的知识库

知识库检索

在前面根据模式选择了对应的知识库之后,就可以在单个知识库内进行检索,目前支持的检索方式包含下面三种:

  • 向量检索,通过生成查询嵌入并查询与其向量表示最相似的文本分段。
  • 全文检索,索引文档中的所有词汇,从而允许用户查询任意词汇,并返回包含这些词汇的文本片段。
  • 混合检索,同时执行全文检索和向量检索,并附加重排序步骤,从两类查询结果中选择匹配用户问题的最佳结果。

从实际的代码来看,还有一个 关键词检索 的能力,但是没有特别介绍,不确定是否是效果上还不够稳定,可以关注下后续的进展。混合检索的流程如下所示:

请添加图片描述
实际的实现在 api/core/rag/datasource/retrieval_service.py

# 关键词检索if retrival_method == 'keyword_search':keyword_thread = threading.Thread(target=RetrievalService.keyword_search, kwargs={'flask_app': current_app._get_current_object(),'dataset_id': dataset_id,'query': query,'top_k': top_k,'all_documents': all_documents,'exceptions': exceptions,})threads.append(keyword_thread)keyword_thread.start()# 向量检索(混合检索中也会调用)if RetrievalMethod.is_support_semantic_search(retrival_method):embedding_thread = threading.Thread(target=RetrievalService.embedding_search, kwargs={'flask_app': current_app._get_current_object(),'dataset_id': dataset_id,'query': query,'top_k': top_k,'score_threshold': score_threshold,'reranking_model': reranking_model,'all_documents': all_documents,'retrival_method': retrival_method,'exceptions': exceptions,})threads.append(embedding_thread)embedding_thread.start()# 文本检索(混合检索中也会调用)if RetrievalMethod.is_support_fulltext_search(retrival_method):full_text_index_thread = threading.Thread(target=RetrievalService.full_text_index_search, kwargs={'flask_app': current_app._get_current_object(),'dataset_id': dataset_id,'query': query,'retrival_method': retrival_method,'score_threshold': score_threshold,'top_k': top_k,'reranking_model': reranking_model,'all_documents': all_documents,'exceptions': exceptions,})threads.append(full_text_index_thread)full_text_index_thread.start()for thread in threads:thread.join()# 混合检索之后会执行向量和文本检索结果合并后的重排序if retrival_method == RetrievalMethod.HYBRID_SEARCH:data_post_processor = DataPostProcessor(str(dataset.tenant_id), reranking_model, False)all_documents = data_post_processor.invoke(query=query,documents=all_documents,score_threshold=score_threshold,top_n=top_k)
检索结果重排

检索结果的重排也比较简单,就是通过外部模型进行打分,之后基于打分的结果进行排序,实际的实现在 api/core/model_manager.py 中:

def invoke_rerank(self, query: str, docs: list[str], score_threshold: Optional[float] = None,top_n: Optional[int] = None,user: Optional[str] = None) \-> RerankResult:self.model_type_instance = cast(RerankModel, self.model_type_instance)# 轮询调用重排序模型,获得重排序得分,并基于得分进行排序return self._round_robin_invoke(function=self.model_type_instance.invoke,model=self.model,credentials=self.credentials,query=query,docs=docs,score_threshold=score_threshold,top_n=top_n,user=user)

总结

本文主要介绍了 Dify 的知识库 RAG 服务,作为完整 Agent 中一个基础模块,Dify 没有特别强调 RAG 独特之处,但是依旧存在一些独特的亮点:

  1. 多种召回模式,支持根据用户意图自动选择合适的知识库,也可以跨知识库进行检索,弥补了常规的 RAG 服务需要用户手工选择知识库的不便之处;
  2. 独特的 Q&A 模式,可以直接根据文本生成问答对,可以解决常规情况下用户问题与文本匹配度不够的问题,但是应该只适用于特定类型的场景,否则可能会因为转换导致的信息损耗导致效果更差;

总体而言,Dify 中的 RAG 服务是一个设计完备的服务,模块化的设计方便组合与拓展,一些独特的设计也可以提升易用性,代码质量也很高,感兴趣的可以深入研究下。

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

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

相关文章

从0到1搭建微服务框架

目录 1.技术栈&#xff1a; 2.模块介绍: 3.关键代码讲解 3.1基础公共模块(common)依赖&#xff1a; 3.3授权模块(auth)依赖: 3.4授权模块核心配置类(AuthrizatonConfig): 3.4 SecurityConfig.java 3.5 bootstrap的核心配置文件(其他服务配置类似这个)&#xff1a; 3.6n…

防爆巡检终端在石化工厂安全保障中的应用

防爆巡检终端在石化工厂安全保障中的应用是广泛而关键的&#xff0c;其设计旨在确保在易燃易爆环境中进行安全、有效的巡检工作。以下是防爆巡检终端在石化工厂安全保障中的详细应用描述&#xff1a; 1. 环境监测与预警 防爆巡检终端配备了各种传感器&#xff0c;能够实时监测…

网银U盾多又乱?后悔没早点用USB Server远程连接管理!

一、引言 网银服务已成为企业日常运营中不可或缺的一部分。但随着企业规模的扩大和业务的增多&#xff0c;网银U盾的数量也随之激增&#xff0c;又多又乱&#xff0c;只能频繁插拔、分散管理&#xff0c;不仅效率低下&#xff0c;而且存在严重的安全隐患。 事实上&#xff0…

ADS131A04硬件设计与软件调试

一、IC基本信息 ADS131A0x 双通道或四通道 24 位 128kSPS 同步采样 Δ-Σ ADC •双通道或四通道同步采样差分输入 • 数据速率&#xff1a;高达 128kSPS • 高性能&#xff1a; – 单通道精度&#xff1a;在 10,000:1 动态范围内优于 0.1% – 有效分辨率&#xff1a;20.6位…

SpringCloud-服务网关-Gateway

1.服务网关在微服务中的应用 (1)对外提供服务的难题分析&#xff1a; 微服务架构下的应用系统体系很庞大&#xff0c;光是需要独立部署的基础组件就有注册中心、配置中心和服务总线、Turbine异常聚合和监控大盘、调用链追踪器和链路聚合&#xff0c;还有Kaka和MQ之类的中间件&…

海思NNIE部署yolov5-shufflenet

1.简要说明 由于NNIE上transpose支持的顺序是固定的,shufflenet那种x=torch.transpose(x,1,2).contiguous() 的操作一般是不支持的。需要进行调整。 2.使用工程以及修改 使用的是开源工程:GitHub - Lufei-github/shufflev2-yolov5: shufflev2-yolov5:lighter, faster and ea…

玛格家居从深交所转板北交所:营收净利润连年下滑,销售费用大增

《港湾商业观察》施子夫 近日&#xff0c;玛格家居股份有限公司&#xff08;以下简称&#xff0c;玛格家居&#xff09;发布公告&#xff0c;重庆证监局已经受理其北交所上市的备案申请&#xff0c;辅导机构为国泰君安证券。 公开信息显示&#xff0c;2022年1月&#xff0c;玛…

基于STM32的智能电池管理系统

目录 引言环境准备智能电池管理系统基础代码实现&#xff1a;实现智能电池管理系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统实现4.4 用户界面与数据可视化应用场景&#xff1a;电池管理与优化问题解决方案与优化收尾与总结 1. 引言 智能电池管理系统&#xff08;Ba…

【昇思25天学习打卡营打卡指南-第十三天】ShuffleNet图像分类

ShuffleNet图像分类 ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操…

骁龙相机拍照流程分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 1.deliverInputEvent 拍照点击事件处理 2.submitRequestList Camera 提交拍照请求 3.createCaptureRequest 拍照请求帧数 骁龙相机通过binder 数据传输…

idea 内存参数修改不生效问题解决 VM参数设置不生效解决

很多人配置idea 内存参数&#xff0c;怎么配置都不生效&#xff0c;主要原因是配置文件用的不是你修改的那个。 系统环境变量中的这个才是你真正要修改的配置文件。 找到并修改后保存&#xff0c;重启idea就可生效

C++ | Leetcode C++题解之第208题实现Trie(前缀树)

题目&#xff1a; 题解&#xff1a; class Trie { private:vector<Trie*> children;bool isEnd;Trie* searchPrefix(string prefix) {Trie* node this;for (char ch : prefix) {ch - a;if (node->children[ch] nullptr) {return nullptr;}node node->children[…

13_网络安全

目录 网络安全协议 网络安全协议 PGP协议 网络安全技术 防火墙技术 入侵检测系统 入侵防御系统 杀毒软件 蜜罐系统 计算机病毒与木马 网络安全协议 网络安全协议 物理层主要使用物理手段隔离、屏蔽物理设备等&#xff0c;其他层都是靠协议来保证传输的安全&#xff…

美国服务器租用详细介绍与租用流程

在数字化时代&#xff0c;服务器租用已成为许多企业和个人拓展业务、存储数据的重要选择。美国作为全球科技发展的前沿阵地&#xff0c;其服务器租用服务也备受瞩目。下面&#xff0c;我们将详细介绍美国服务器租用的相关知识及租用流程。 一、美国服务器租用简介 美国服务器租…

探索数据结构:队列的的实现与应用

&#x1f511;&#x1f511;博客主页&#xff1a;阿客不是客 &#x1f353;&#x1f353;系列专栏&#xff1a;渐入佳境之数据结构与算法 欢迎来到泊舟小课堂 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 一、队列的概念 队列是一个线性的数据结构&#…

windows环境下创建python虚拟环境

windows环境下创建python虚拟环境 使用virtualenv库创建虚拟环境&#xff0c;可使不同的项目处于不同的环境中 安装方法&#xff1a; pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple pip install virtualenvwrapper-win -i https://pypi.tuna.tsinghua…

Spring Cloud Alibaba之负载均衡组件Ribbon

一、什么是负载均衡&#xff1f; &#xff08;1&#xff09;概念&#xff1a; 在基于微服务架构开发的系统里&#xff0c;为了能够提升系统应对高并发的能力&#xff0c;开发人员通常会把具有相同业务功能的模块同时部署到多台的服务器中&#xff0c;并把访问业务功能的请求均…

谈谈WebComponents | 前端开发

一、 源起 让我们以一个例子开始。 假设我们要做一个环形进度条&#xff0c;它可以&#xff1a; 1、根据进度数值的不同&#xff0c;计算出百分比&#xff0c;以渲染对应的角度值。 2、根据设置的进度不同&#xff0c;我们用不同的颜色加以区分。 3、在环的中间我们以动画递增的…

vision mamba

Mamba 成功的关键在于采用了 Selective Scan Space State Sequential Model&#xff08;S6 模型&#xff09;。是用于解决自然语言处理&#xff08;NLP&#xff09;任务。与 transformer中注意力机制不同&#xff0c;Mamba的S6 将 1D 向量中的每个元素&#xff08;例如文本序列…

现代信息检索笔记(二)——布尔检索

目录 信息检索概述 IR vs数据库: 结构化vs 非结构化数据 结构化数据 非结构化数据 半结构化数据 传统信息检索VS现代信息检索 布尔检索 倒排索引 一个例子 建立词项&#xff08;可以是字、词、短语、一句话&#xff09;-文档的关联矩阵。 关联向量 检索效果的评价 …