[Bug]: minimum_should_match fraction is truncated, not rounded, in every full-text doc-store connector

RAGFlow 全文检索连接器把 minimum_should_match 小数比例转成百分比字符串时,用 int() 截断导致阈值比预期少 1%(如 0.29 被转成 "28%")。优先检查 rag/utils/ 与 memory/utils/ 下六个连接器 search() 方法中的 str(i

快速结论:RAGFlow 全文检索连接器把 minimum_should_match 小数比例转成百分比字符串时,用 int() 截断导致阈值比预期少 1%(如 0.29 被转成 “28%”)。优先检查 rag/utils/ 与 memory/utils/ 下六个连接器 search() 方法中的 str(int(fraction * 100)) + “%” 写法,并改为 round() 取整。

适用环境:RAGFlow 源码提交 a39b6ec2e9a840c8cf9c1c8c021ade6a7613be56;影响 ESConnection、OSConnection、OBConnection、InfinityConnection 及其 memory/ 对应实现;不涉及 Docker 镜像方式部署(Issue 通过直接运行连接器复现)。

最快修复方案:暂无确认的一步修复方案(Issue 在关闭时尚未合并补丁);可优先尝试将六个连接器中的 str(int(fraction * 100)) + “%” 替换为 str(round(fraction * 100)) + “%”,这与项目此前 PR #12688 的修复方式一致。

注意事项:该修复属于代码层面的修改,需重新构建或对应环境运行;若通过 Docker 镜像部署需等待官方镜像更新。Issue 明确说明这不是 common/float_utils.py 中 normalize_overlapped_percent 那条路径,不要混淆。

问题场景

RAGFlow 全文搜索路径中,调用方(如 rag/nlp/query.py 的 question() 或 memory/services/query.py)把用户传入的 minimum_should_match 小数阈值传给 MatchTextExpr.extra_options[“minimum_should_match”],最终到达六个全文存储连接器(ESConnection、OSConnection、OBConnection、InfinityConnection 及 memory 版本)时,这些连接器统一用 str(int(fraction * 100)) + “%” 把小数转成百分比字符串。由于绝大多数两位小数在 IEEE-754 中不能精确表示(如 0.29 实际存储为 0.28999999999999998),int() 向零截断后会让查询引擎收到比请求更严格的阈值,并且总是向下取整。

报错原文

[Bug]: minimum_should_match fraction is truncated, not rounded, in every full-text doc-store connector
>>> str(int(0.29 * 100)) + "%"
'28%'   # requested 29%
>>> str(int(0.57 * 100)) + "%"
'56%'   # requested 57%
>>> str(int(0.58 * 100)) + "%"
'57%'   # requested 58%

原因分析

可能原因:六个连接器重复使用了同一段截断表达式 str(int(minimum_should_match * 100)) + “%”。浮点运算中 0.29 * 100 的结果略小于 29(即 28.999…),int() 截断小数部分得到 28。Issue 作者检查了 (0,1) 区间内全部 99 个两位小数,确认多个值因浮点表示误差落在边界上,导致结果总是向下取整而非四舍五入。注意,这是独立于 common/float_utils.py 中 normalize_overlapped_percent 截断的另一条代码路径,后者对应的是 chunk 重叠百分比字段且有 [0,90] 区间限制,与本问题无关。

环境排查

  • 确认 RAGFlow 源码 commit ID:a39b6ec2e9a840c8cf9c1c8c021ade6a7613be56(可执行 git checkout 验证)
  • 检查 rag/utils/es_conn.py、rag/utils/opensearch_conn.py、rag/utils/ob_conn.py、rag/utils/infinity_conn.py 以及 memory/utils/es_conn.py、memory/utils/infinity_conn.py 中是否存在 str(int(fraction * 100)) + “%”
  • 若通过 Docker 部署,需确认镜像构建时间是否包含 fix 提交;Issue 复现方式是直接运行连接器而非 Docker

解决步骤

  1. 定位六个文件中对应的 search() 方法,找到 minimum_should_match 转百分比字符串的表达式。
  2. 将 str(int(minimum_should_match * 100)) + “%” 改为 str(round(minimum_should_match * 100)) + “%”(参考此前 PR #12688 对类似问题的处理方式)。
  3. 如涉及 Infinity、OpenSearch、OceanBase 等不同后端,确认各连接器接受百分比字符串的格式一致。
  4. 检查 rag/nlp/query.py 中 question() 与 memory/services/query.py 的调用链,确认传入 extra_options[“minimum_should_match”] 的值类型为 float。
  5. 若同时使用多个全文检索后端(ES/OS/OB/Infinity),需要在这六个文件里全部同步修改,否则行为会不一致。

验证方法

在修改后的环境里执行 Issue 中的复现脚本:python3 -c “for f in (0.29, 0.57, 0.58): print(f, ‘->’, str(round(f * 100)) + ‘%’)”,确认输出应为 29%、57%、58%;再对 rag/utils/es_conn.py 等文件做一次实际的最小实例搜索,用查询日志确认发送给后端的 minimum_should_match 参数值与请求一致,不再比请求阈值少 1%。

参考来源

infiniflow/ragflow #19027

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 21648

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注