微信扫码
与创始人交个朋友
我要投稿
在企业构建RAG应用系统时,需要满足不同用户群体的需求。这些用户群体包括企业管理人员、企业内部用户以及大众用户。首先,整理清楚各类用户的需求,有助于明确他们的交互操作需求,并基于此确定所需的交互界面数量。接着,可以根据需求决定是否实现Web端、手机端或其他设备端(如PAD等)的支持。
在确定了用户的操作端后,接下来便是考虑如何承载这些操作端的后台服务系统。我们可以选择采用单体系统,也可以根据不同领域将后台服务拆分为多个独立的服务。我推荐采用领域驱动设计,将系统划分为多个服务,分别是后台管理服务系统、用户交互服务系统和文档解析服务系统等。这些服务之间通过微服务架构进行通信。具体而言,后台管理服务系统负责处理企业管理相关配置和企业内部用户的界面,用户交互服务系统则专注于ToC(面向消费者)用户的服务,服务系统则支撑Web、手机及其他设备端的交互需求。
这种划分的最大优势在于能够根据不同流量需求规划服务能力,尤其是针对ToC端流量对大模型服务的压力,可以单独进行规划与管理。谈到大模型的部署,这一环节同样至关重要,需要独立规划并作为一个关键模块。大模型部署不仅是RAG应用系统的核心部分,而且直接影响系统的性能与扩展能力。
接下来,我们将以RAGFlow为例,深入探讨RAG的流程架构和企业最佳的系统架构设计。
手绘系统架构
系统工程说明:
B端与管理:
面向企业用户和管理后台的 Web 工程模块。
B端与管理服务:
提供 B 端和管理功能的核心服务工程。
文档解析服务:
专用于将文档解析为知识块(Chunk)并构建知识图谱的服务模块。
C端(Web、移动端):
面向终端用户的 Web 和移动端交互平台。
RAG服务:
支持 B 端和 C 端的检索与处理的核心服务模块。
文档解析LLM:
专注于文档解析的大模型服务,支持知识块抽取与处理。
生成LLM:
用于检索后生成内容的大模型服务。
当前实践中的产品架构采用上述设计,从模块解耦性和系统部署便利性来看,这是一种高效且灵活的架构方案,能够满足复杂业务场景需求。
RAGFlow源码解析
我们基于 RAGFlow 提供的 RAG 流程,解析并设计了系统架构。接下来,让我们深入了解 RAGFlow 是如何实现这一流程的。
源码结构
模块说明:
Agent模块: 实现Agent流程的编辑与执行功能。
API模块: 提供管理端与AI助理端功能的API接口,基于Flask实现。该模块没有按照B端与C端进行区分。
DeepDoc模块: RAGFlow的文档解析模块,是该项目的核心卖点之一。
GraphRAG模块: 受微软开源项目启发,负责知识图谱解析,与DeepDoc模块一样,承担文档解析任务。
RAG模块: 提供文档解析服务,包含多个子模块,如NLP、LLM、App(解析场景)、Utils等,支持分词、合并、Embedding等功能,确保文档解析的高效与精准。
Web模块: 管理端与AI助理共享,并未按照用户端(B端和C端)进行区分。
其中,最为关键的模块是API和RAG。API模块负责启动后台服务并提供接口服务,RAG模块则专注于文档解析服务,是系统运行的核心模块。
其它中间件
数据库: 采用MySQL作为关系型数据库管理系统。
文件存储: 使用MinIO进行文件存储,提供高效的对象存储服务。
向量数据库: 默认使用ElasticSearch进行向量数据存储,但也支持切换为Infinity,Infinity是RAGFlow公司自主研发的向量数据库。
文档解析源码分析
RAGFlow的文件解析采用异步处理方式,通过Redis消息队列实现解析任务的异步执行。此前,该功能存在一些问题,主要表现为消息消费存在Bug,导致文档上传后虽然启动了解析,但任务长时间未被执行。然而,从当前的启动代码来看,这个问题应该已经得到解决。特别是在0.15版本的代码中,任务启动后的功能更为完善,解析过程得到了显著改进。
具体以下代码:
这段代码的核心功能包括:
TRACE_MALLOC_DELTA
的倍数)进行内存使用分析。通过这种方式,代码不仅可以持续处理任务,还能够定期分析内存使用,帮助开发者在运行时监控内存使用情况。
具体处理消息接收并进行处理的方法是handle_task()
collect()
方法是消费 Redis 消息队列的具体实现。从代码中可以看出,该方法的执行过程已经被监控,且从当前功能的展现来看,之前的消费阻塞问题已经得到修复。
通过分析代码,可以看出 RAGFlow 在系统的健壮性和可用性方面都有了显著提升。
main()
提供了必要的初始化配置、内存监控和任务处理循环,确保系统能够稳定启动并持续运行。内存监控的引入使得系统能在高负载情况下及时发现问题,防止内存泄漏带来的性能下降和崩溃风险。
handle_task()
通过使用锁机制、异常捕获以及任务状态更新,确保系统能够应对各种异常情况。当任务处理失败时,系统会尽量清理并回滚任务状态,避免任务数据丢失或系统状态异常。
collect()
对任务获取过程进行了严格的异常处理,避免系统在无法获取任务时崩溃或阻塞。通过检查任务状态,确保不会处理不需要执行的任务,从而提高了系统的健壮性。
通过后台线程方式,main()
确保了任务处理和状态报告的异步执行,避免了状态报告对任务处理的阻塞。内存快照和定期分析也能帮助开发人员提前发现并优化系统,提升长期可用性。
由于 handle_task()
内部实现了详尽的异常处理,系统在执行任务时不会因为某个任务的失败或取消而中断。即使某个任务出错,系统依然会继续处理后续任务,保证了系统的稳定性和可用性。
由于采用了异常处理和安全的状态检查,collect()
能保证即使在任务获取失败时,系统仍能正常运行。此方法在获取不到任务时会适当延迟(通过 time.sleep(1)
),确保系统始终处于“等待任务”的状态,而不至于停滞。
在这个业务场景中,对性能的要求并不是非常高,因此保证系统的高健壮性和高可用性是最为重要的目标。只要系统能够稳定运行并处理异常,确保服务持续可用,那么这就可以算作是最大的成功。
当消息被消费进入文档解析过程,代码如下:
其中build_chunks处理具体的解析场景,可以根据上传文档的类型和解析场景选择解析方法。
可以看到根据parser_id来加载支持的场景,具体支持场景如下:
文档解析页面交互
解析成功后后可以看到分块数,点击名称列的文件可以查看具体的解析块信息。
文件检索
文件检索的支持可以通过实际的对话处理流程来查看。对话的 API 为 /v1/conversation/completion
,而实际的对话处理则是在 api/db/services/dialog_service.py
文件中的 chat()
方法中完成。
深入跟踪对话处理流程,我们可以看到文件检索是在 rag/nlp/search.py
文件中的 search()
方法中完成的。
RAGFlow 当前实现了混合检索,结合了文本检索和向量检索。混合检索的实现完全依赖于 ElasticSearch,具体实现如下所示:
检索结果的重排
文件的重排操作是在 rag/nlp/search.py
文件中的 rerank()
方法中完成的。重排基于文本匹配得分和向量匹配得分的混合排序,默认情况下,文本匹配的权重为 0.3,向量匹配的权重为 0.7。对应的实现如下所示:
RAGFlow支持灵活配置检索和生成模型,企业可以选择自部署开源模型生成答案,这不仅提升了系统的控制力,还显著降低了外接模型的使用成本。
总结
本文通过分析RAGFlow的RAG流程架构,讲解了构建最佳系统架构的思路,并深入解析了RAGFlow 0.15.1版本的核心源码,展示了实现RAG应用系统的关键步骤。企业可根据自身技术栈选择自研或基于开源项目二次开发,打造专属RAG系统。下一篇文章将重点讲解如何通过vLLM部署企业级开源大模型。
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2025-01-06
RAG成为过去式?缓存增强生成(CAG)is All You Need?
2025-01-06
GraphRAG × AutoGen × Ollama × Chainlit = 本地免费多代理 RAG 超级 AI 助手
2025-01-05
装上记忆,Agent牛了!
2025-01-04
检索增强生成 和思维链 结合: 如何创建检索增强思维链 (RAT)?
2025-01-04
我如何利用 ChromaDB 和 Chainlit 构建基于 Graph-RAG 系统的 LLM 应用程序
2025-01-04
吴恩达DeepLearning.AI课程系列 —— 大模型检索增强生成(一)
2025-01-04
吴恩达DeepLearning.AI课程系列 —— 大模型检索增强生成(二):文档划分技术简介
2025-01-04
吴恩达DeepLearning.AI课程系列 —— 大模型检索增强生成(三):向量数据库及嵌入
2024-07-18
2024-09-04
2024-05-05
2024-06-20
2024-05-19
2024-07-09
2024-07-09
2024-06-13
2024-07-07
2024-07-07
2025-01-06
2025-01-04
2024-12-30
2024-12-27
2024-12-26
2024-12-24
2024-12-21
2024-12-14