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

【Ragflow】9.问答为什么比搜索响应慢?从源码角度深入分析

概述

前几天看到有群友提到一个现象:Ragflow的搜索界面的问答速度很快,但聊天界面的问答速度很慢,究竟是什么原因?

在深入挖掘源码之后,逐渐发现了问题的答案。

调试准备

ragflow 默认推荐docker的部署方式,但不利于本地部署调试。

下面使用本地环境来运行,在docker中关闭ragflow-server,仅保留其它相关组件容器保持运行状态。

各容器状态

运行前端环境,打开ragflow/web,安装依赖:

npm install

启动前端:

npm run dev

运行后端环境,需要先根据pyproject.toml或uv.lock配置当前环境,官方给了一个docker/launch_backend_service.sh这样一个liunx的后端启动脚本,如果是windows系统,可直接执行:

python -m api.ragflow_server

前后端均启动后,访问前端控制台显示地址,可正常登录访问。

聊天后台响应逻辑

下面在聊天界面,发送问题,观察后台日志如下:

2025-04-01 23:00:15,761 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:00:15] "POST /v1/conversation/set HTTP/1.1" 200 -
2025-04-01 23:00:15,812 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:00:15] "GET /v1/conversation/list?dialog_id=ec69b3f4fbeb11ef862c0242ac120002 HTTP/1.1" 200 -
2025-04-01 23:00:16,217 ERROR    2724 LLMBundle.encode_queries can't update token usage for d3de1596fb6911efa0f40242ac120006/EMBEDDING used_tokens: 7
2025-04-01 23:00:16,470 INFO     2724 POST http://localhost:1200/ragflow_d3de1596fb6911efa0f40242ac120006/_search [status:200 duration:0.101s]
2025-04-01 23:00:17,526 INFO     2724 HTTP Request: POST http://10.195.140.47:11434/api/chat "HTTP/1.1 200 OK"
2025-04-01 23:00:17,673 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:00:17] "POST /v1/conversation/completion HTTP/1.1" 200 -

从中可以注意到,在聊天界面对话时,前端实际是通过/v1/conversation/completion这个接口向后端请求数据。

进一步查看源码,后端在得到前端请求后,响应逻辑如下(下面的缩进表示函数调用的层次关系):

  • conversation_app.py 中的 completion 函数处理请求:
    • 调用api\db\services\dialog_service.py里的 chat 函数
      • embd_mdl 从 LLMBundle 得到 embedding 模型
      • 自动读取用户最后3条问题信息
      • 如果存在历史对话信息,并开启多轮对话优化,调用 rag\prompts.py 的 full_question 进行问题优化,这一点之前文章分析过,不做赘述
      • 如果开启关键词分析,调用 rag\prompts.py 的 keyword_extraction 进行一轮额外模型询问,提取关键词
      • 如果开启推理,调用 agentic_reasoning\deep_research.py 进行对问题进行推理
      • 调用 rag\nlp\search.py 的 retrieval 进行知识库检索
      • 如果填了tavily_api_key密钥,调用 rag\utils\tavily_conn.py 的 search 进行外部知识检索
      • 如果开启知识图谱,额外进行知识图谱检索
      • 调用 rag\prompts.py 的 kb_prompt 将检索到的知识库内容格式化为模型的提示词,这里有一个小的限制,即当检索到的知识数量超过97%模型的max_tokens时,会将未添加的知识进行舍弃。
      • 如果开启显示引文,会加入额外的引文提示词作为系统prompt,具体内容见 rag\prompts.py 的 citation_prompt 函数。
      • 调用 rag\prompts.py 的 message_fit_in,进一步对超出 95% max_tokens 限制的问题进行精简,这里的问题不包括额外添加的引文提示信息,精简逻辑是尽可能保留系统信息和最后一条用户信息,对超出部分进行截断。
      • 调用 api\db\services\llm_service.py 的 chat_streamly 进行LLM问答交互
      • 回答之后,处理引用信息,添加引用标记
    • 得到回答内容,格式化成json格式,返回给前端

搜索后台响应逻辑

下面在搜索界面,发送问题,观察后台日志如下:

2025-04-01 23:07:10,491 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:07:10] "POST /v1/conversation/ask HTTP/1.1" 200 -
2025-04-01 23:07:10,639 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:07:10] "POST /v1/chunk/retrieval_test HTTP/1.1" 200 -
2025-04-01 23:07:10,761 ERROR    2724 Image not found.NoneType: None
2025-04-01 23:07:10,764 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:07:10] "GET /v1/document/image/undefined HTTP/1.1" 200 -
2025-04-01 23:07:10,931 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:07:10] "GET /v1/document/thumbnails?doc_ids=eb47531afbea11ef8f2e0242ac120002-fe5c351b2c6ad031 HTTP/1.1" 200 -
2025-04-01 23:07:16,311 INFO     2724 127.0.0.1 - - [01/Apr/2025 23:07:16] "POST /v1/conversation/related_questions HTTP/1.1" 200 -

可以看到,搜索时,前端实际通过/v1/conversation/ask这个接口向后端请求数据。

后端在得到前端请求后,响应逻辑如下:

  • conversation_app.py 中的 ask_about 函数处理请求:
    • 调用 api\db\services\dialog_service.py里的 ask 函数
      • embd_mdl 从 LLMBundle 得到 embedding 模型
      • 过滤知识库信息,比如有些知识库是共用,有些是私用,所有选定知识库选择唯一的一条记录信息
      • 调用 rag\nlp\search.py 的 retrieval 进行知识库检索
      • 调用 rag\prompts.py 的 kb_prompt 将检索到的知识库内容格式化为模型的提示词
      • 采用默认提示词,用于作为模型系统提示词
      • 调用 api\db\services\llm_service.py 的 chat_streamly 进行LLM问答交互
      • 回答之后,处理引用信息,添加引用标记
    • 得到回答内容,格式化成json格式,返回给前端

处理完之后,前端实际还会通过/v1/conversation/related_questions这个接口,再次向模型发一轮询问,以显示相关问题提示,不过这不影响搜索界面的回答速度,不在本文的讨论范围之内,这里不作展开。

聊天响应慢的真相

比较两者的具体处理方式,可以看出,实际上两者都共用了数据库检索、模型问答等接口,主要区别在于,聊天的响应中包含了大量的数据处理方式。

比如,开启关键词分析和多轮对话优化后,系统都会启动一轮额外的交互使速度变慢(两个同时开就是额外两轮交互),多轮对话在默认情况下是开启的。这是响应速度慢的主要原因。

其次,聊天界面的会自动将最近三轮的对话纳入提示词之中,如果开启显示引文后,系统会自动的塞入一大段系统提示词,这某种程度也略微增加了一点响应时间,不过只是次要原因。

下面通过一个简单的小实验来证实推断:

使用本地部署的DeepSeek-r1:70b模型,聊天界面关闭所有可选项,响应时间(从用户发起请求到模型开始输出第一个字)约3秒,时间和搜索界面差不多。

如果开启显示引文、关键词分析、多轮对话优化之后,相同问题,聊天界面响应时间约13秒,的确慢了不少。

搜索功能分析

搜索实际上的作用是通过自然语言,对指定知识库文件进行语义检索。为什么要在这里塞个不考虑聊天历史的一次性问答?

当我把这个功能给客户演示时,客户也产生了相同的疑问,不禁思考,这个功能是否有存在的必要?

在后续二次开发的ragflow-plus中,也许会考虑将该功能移除掉。

http://www.dtcms.com/a/106787.html

相关文章:

  • 社交类 APP 设计:打造高用户粘性的界面
  • LE AUDIO CIS连接建立失败问题分析
  • 6.git项目实现变更拉取与上传
  • C++虚函数与抽象类
  • 使用 libevent 处理 TCP 粘包问题(基于 Content-Length 或双 \r\n)
  • 操作系统高频(七)虚拟地址与页表
  • ADASH VA5 Pro中的route功能
  • electron 的 appData 和 userData 有什么区别
  • SPI高级特性分析
  • JavaScript instanceof 运算符全解析
  • 「DeepSeek-V3 技术解析」:无辅助损失函数的负载均衡
  • 双模多态驱动:DeepSeek-V3-0324与DeepSeek-R1医疗领域应用比较分析与混合应用讨论
  • 移动通信网络中漫游机制深度解析:归属网络与拜访网络的协同逻辑
  • PHP的相关配置和优化
  • openstack 查看所有项目配额的命令
  • SU CTF 2025 web 复现
  • tcp的粘包拆包问题,如何解决?
  • 【深度学习量化交易21】行情数据获取方式比测(2)——基于miniQMT的量化交易回测系统开发实记
  • 常见电源模块设计
  • ColPali:基于视觉语言模型的高效文档检索
  • 探索鸿蒙操作系统:迎接万物互联新时代
  • 【IOS webview】源代码映射错误,页面卡住不动
  • STM32单片机入门学习——第7节: [3-3] GPIO输入
  • 树莓派超全系列教程文档--(22)使用外部存储设备的相关操作
  • Spring Boot 集成Redis中 RedisTemplate 及相关操作接口对比与方法说明
  • #Linux内存管理# 假设设备上安装了一块2G的物理内存,在系统启动时,ARM Linux内核是如何映射的?
  • RAG 和 RAGFlow 学习笔记
  • 【VUE3】Pinia
  • ARM 性能分析工具:Streamline
  • 高并发内存池(二):Central Cache的实现