Dify 知识库索引(中):打开源码,拆穿关于“经济索引”的三个谣言

|-------------------------------------------------------------------------|
| 先划重点: 经济索引不是 BM25,也不是用 LLM 生成关键词。 这俩说法流传很广,但都是错的,看 Dify 源码就能验证。 |

动笔前我专门搜了一圈国内文章,直到 2025 年底还有高赞教程写着"经济索引通过 LLM 生成关键词"。以讹传讹,越传越像真的。所以这篇所有结论都来自我本地部署的 Dify 1.15.0 源码,一行行翻的。你装的是同一份开源代码,随时能自己验证。

一、高质量索引:Embedding + 向量数据库

高质量索引的核心流程非常标准:把每个分段喂给 Embedding 模型,得到向量,写入向量数据库。

1.1 建库阶段

在高质量模式下,Dify 会调用你配置的 Embedding 模型(OpenAI 的 text-embedding-3、智谱的 embedding、或者本地部署的 BGE 系列都行),把每个分块转成固定维度的稠密向量,连同原文一起写入向量数据库。

Dify 支持的向量数据库后端不少:Weaviate、Qdrant、pgvector、Milvus 等。向量数据库干两件事:存向量,以及做快速近似最近邻搜索(ANN)。注意"近似"这两个字------它为了速度牺牲了一点精度,但换来的是百万级向量也能毫秒返回,这是生产环境能跑起来的前提。

关于向量库怎么选,我自己的经验是分规模看:

|------------------------------|-----------------|---------------------|
| 场景 | 我的推荐 | 理由 |
| 中小规模(百万分段以内)、团队已有 PostgreSQL | pgvector | 不用多维护一套系统,能力够用 |
| 需要高并发、大规模、多租户隔离 | Qdrant / Milvus | 专门的向量引擎,性能上限高 |
| 想快速起步、跟 Dify 默认配置走 | Weaviate | Dify 本地部署默认就是它,文档最全 |

选型时别被"向量数据库"这个词唬住。中小规模下 pgvector 完全能打,不少团队一上来就上 Milvus 集群,结果跑了一年才几千个分段,纯属杀鸡用牛刀。

1.2 三种检索策略

高质量索引建好后,Dify 提供三种检索设置:

|----------|-----------------------|----------------|
| 检索策略 | 原理 | 适合场景 |
| 向量检索 | 把查询也 Embedding,找最近邻分段 | 语义改写、跨语言、概念性问题 |
| 全文检索 | 对文档词汇建索引,按关键词匹配 | 精确术语、错误码、法条编号 |
| 混合检索 | 向量 + 全文并行,再融合排序 | 通用场景,容错性最好 |

混合检索是 Dify 官方文档明确推荐的默认策略。原因很直观:纯向量会漏精确词,纯关键词会漏语义改写,两者并行召回再融合,互为兜底。

我翻源码确认过混合检索的实现:向量检索和全文检索是并发执行的,各自召回一批结果,去重之后交给一个融合环节------你可以手动调"语义权重/关键词权重"(语义权重拉到 1 就是纯向量,关键词权重拉到 1 就是纯全文),也可以挂一个 Rerank 模型来做精排。这个设计值得肯定,它把"怎么融合"的选择权交给了使用者,而不是写死在代码里。

实操建议:拿不准权重怎么设的时候,先 1:1 跑起来,用评测集对比;绝大多数场景下,Rerank 融合比手动调权重更省心,效果也更好。权重调节适合没有 Rerank 模型可用的场景,作为次优解。

1.3 Rerank 是选配,但很值得

三种检索策略都支持开启 Rerank。要理解它为什么值钱,得先知道一个概念:Embedding 检索用的是双塔模型(bi-encoder),查询和文档各自编码成向量再比距离,速度快,但查询和文档之间没有"交互",细粒度相关性判断天然弱。Rerank 用的是交叉编码器(cross-encoder),把查询和候选文档拼在一起送进模型,让它们充分交互后再打分。精度高,但每次都要过一遍模型,慢且贵。

所以生产级的标准做法是两级:先用便宜的向量检索粗召回一批候选,再用 Rerank 精排到前几名,最后才送进大模型。Anthropic 在 2024 年底公开过一组实验数据:他们对比了各种检索方案的 top-20 召回失败率,纯向量 Embedding 加 BM25 的基线是 5.7%,在前面加一道 Rerank 精排(先召回 150 个候选,再精排到 20 个),失败率降到了 1.9%,降幅 67%。这组数字被业界反复引用,因为它量化了一个很多人凭直觉就知道的事实:粗召回 + 精排,比单一检索强得多。

我自己在本地部署 bge-reranker 跑过类似对比,方向一致:Rerank 对排序精度的提升非常明显,尤其是候选里同时存在"高度相关"和"勉强相关"的段落时,交叉编码器能把它们拉开差距。注意 Rerank 的价值不在召回更多,而在让排在前面的更准------所以它的收益要配合"候选集大小"一起看,候选太少精排空间有限,候选太多成本又上来了,一般 50~150 个候选是个合理区间。

二、经济索引:jieba 关键词表

经济索引的实现和国内很多博客描述的不一样。我们直接看源码。

2.1 建库:jieba 抽关键词,没有 LLM

在 Dify 源码的 jieba_keyword_table_handler.py 里,关键词抽取用的是 jieba 的 extract_tags 接口,也就是 TF-IDF 算法。建库时每个分段默认抽 10 个关键词:

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| def extract_keywords(self, text: str, max_keywords_per_chunk: int | None = 10) -> setstr: keywords = self._tfidf.extract_tags(sentence=text, topK=max_keywords_per_chunk or 10) |

这个 10 不是拍脑袋写死的,它在数据库模型里有个字段 keyword_number,默认值就是 10,也就是说你可以在知识库设置里改它。

这里有几个事实必须说清楚。这几个事实也值得先摆出来,因为网上至少一半相关文章在这里写错:

  • 全程没有调用 LLM。 关键词是本地 jieba 算法生成的,不消耗任何模型 Token。这就是它叫"经济"的原因------建库和检索都不花钱。
  • 它也不是 BM25。 BM25 是基于整个语料库词频统计的排序函数;而这里只是从单段文本里抽 Top-K 关键词,两者是完全不同的东西。Dify 的高质量索引里其实有真正的全文检索(用向量库的倒排能力),那才沾 BM25 的边;经济索引的倒排表是 jieba 关键词级别的,比全文检索粗糙得多。
  • 写索引的时候还有一把 Redis 锁串行处理,防止并发写坏关键词表。这个细节平时没人提,但大语料批量建库时会成为吞吐瓶颈------并发写不进,只能排队,语料越大越明显。

2.2 查询:命中计数排序

检索时,Dify 同样用 jieba 从查询句里抽关键词,然后去关键词表里查每个词对应哪些分段,最后按"命中关键词数量"倒序排列:

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| chunk_indices_count: dictstr, int = defaultdict(int) for keyword in keywords_list: for node_id in keyword_tablekeyword: chunk_indices_countnode_id += 1 sorted_chunk_indices = sorted(chunk_indices_count.keys(), key=lambda x: chunk_indices_countx, reverse=True) |

翻译成人话:哪个分段命中的关键词多,哪个就排前面。 没有 BM25 的 IDF 加权,也没有考虑词频 TF。默认只返回前 4 个分段(top_k 默认值)。

这个实现还有个容易忽视的特点:查询句抽出的关键词,只有在关键词表里真实存在的才会参与计数。如果用户提问用了文档里根本不出现的词,那检索结果直接是空的------连"矮子里拔将军"的机会都没有。这也是经济索引在口语化提问下表现最差的原因之一。

2.3 检索设置只有 TopK

经济索引下,Dify 只提供 TopK 一个参数,不支持 Score 阈值,也不支持 Rerank。这意味着你没法做精细过滤,召回结果完全由关键词命中数决定。想上重排?先把知识库升级成高质量再说。

三、网上流传的三个误解,逐个纠正

误解 1:经济索引用 LLM 生成关键词

错。源码里是 jieba 的 TF-IDF 提取,全程没有 LLM 调用。为什么这个谣言流传这么广?我猜是因为早期 Dify 文档里"经济"两个字让人联想到"用便宜的模型",再加上网上文章互相抄,就传成了"用 LLM 生成关键词"。实际上它就是纯本地的分词算法,跟模型一点关系没有。判断一篇技术文章靠不靠谱,这其实是个很好的试金石:连这个都写错的,其他细节大概率也没核实过。

误解 2:经济索引是 BM25

错。BM25 需要全局文档频率(IDF)和词频(TF)加权,是信息检索领域几十年的经典算法;Dify 经济索引只是按命中关键词数量排序,连 BM25 的边都沾不上。这个误解的危害在于:很多人以为经济索引"够专业",拿它当 BM25 用,结果遇到复杂查询就翻车。

误解 3:经济索引零成本

部分对、部分不对。它确实不消耗 Embedding 和 Rerank 的 Token 费用,但关键词表要整体加载,写索引还有 Redis 锁串行排队,在超大规模语料下,这些都会成为运维层面的隐性成本。省的是钱,没省心。

四、算一笔公开价格的账

很多企业纠结经济还是高质量,本质是纠结成本。我按公开价格算过一笔示意账,结论可能出乎意料:

  • 语料规模:2000 万 token(约 4 万个 500 token 的分段)
  • 月查询量:10 万次
  • Embedding:OpenAI text-embedding-3-small,约 $0.02 / 百万 token(按 2026 年公开价,实际以官方最新报价为准)

|--------------|-----------------------------|-------------|
| 成本项 | 计算方式 | 金额 |
| Embedding 建库 | 20M × 0.02 / 1M | 0.40 |
| Embedding 查询 | 10万 × 30 token × 0.02 / 1M | 0.06 / 月 |
| 向量库基础设施 | 托管实例最小规格 | 几十美元 / 月 |
| Rerank 精排 | 10万次 × 每次精排数十至上百候选 | 数百到数千美元 / 月 |

这张表里最扎眼的是:一次性 Embedding 建库成本只有 4 毛钱。 你没看错,2000 万 token 的语料,用 OpenAI 最便宜的 embedding 模型建库,成本不到 1 美元。月度查询的向量化开销更是可以忽略。顺便说一句,OpenAI 的 Batch API 还能再打五折,建库这种一次性任务完全可以用批量接口,把钱省到极致。

真正的大头是 Rerank。而且 Rerank 的计价口径这几年还变过------早期按"每千次搜索"计费,后来主流厂商改成按 token 计费(查询和候选文档一起算)。口径一变,同样用量的账单可能差一个数量级。这里要提醒一句:看 Rerank 预算,一定要按自己真实的候选集大小和官方最新计价方式重算,别拿着两年前的估算数字做决策。

Rerank 成本还有几个工程上的控制手段,按性价比排序:

  1. 缩小候选集:粗召回 50 个就够的场景,别拉到 150。候选少一半,Rerank 账单直接减半。
  2. 只在必要时精排:简单查询命中很准,就不必每次都过 Rerank;复杂查询、多条件查询再触发。这就是所谓的置信度门控。
  3. 本地部署 Rerank 模型:BGE 系列的 reranker 效果不差,跑在一台有 GPU 的机器上,费用归零,就是要点运维功夫。

这意味着一个反常识的结论:如果你的目标只是"省 Embedding 的钱",经济索引能省的空间非常有限------本来就没几个钱。但它牺牲的语义召回能力,可能直接影响用户体验。这笔账怎么算都是亏的。

那经济索引是不是一无是处?也不是。它真正的价值在"没有外部模型可用"的场景:离线内网环境、没有 GPU 的机房、或者只想快速跑通验证流程。这些情况下,经济索引是唯一的选择,而不是省钱的选择。

如果确实预算敏感,我更推荐的路子是:本地部署开源的 Embedding 和 Rerank 模型(BGE 系列、bge-reranker 都行),用 Dify 的 OpenAI-API 兼容接口接进来。效果和商业 API 差距不大,费用是零,就是需要一台能跑的机器------Embedding 模型一般几 GB 显存就够,Rerank 模型更小,普通开发机都能扛。我自己就是这么配的,跑了大半年很稳,唯一要习惯的是模型更新要自己维护。说句实在话,对大多数国内团队,这一步比在"经济还是高质量"之间纠结有价值得多。

五、结论

  1. 高质量索引的竞争力在"语义泛化 + 混合检索 + Rerank"的完整链路,实现就是标准的 Embedding + 向量库。
  2. 经济索引的竞争力在"零外部模型依赖 + 快速部署",本质是 jieba 关键词 + 命中计数排序,既不是 LLM 生成,也不是 BM25。
  3. 成本真相:Embedding 便宜到可以忽略,Rerank 和基础设施才是持续支出;想省钱优先考虑控制候选集、门控触发和本地模型,而不是牺牲索引能力。

下一篇聊具体场景怎么选、落地怎么分层,还有几个上线前必须知道的坑。


本文用到


【欢迎访问我的个人博客,这里有我的精选文章和每日AI资讯专栏。】

小羊知慧 | 个人知识分享博客

相关推荐
zzzll11111 小时前
Spring Boot 入门指南:从零开始构建微服务
spring boot·后端·微服务
李可以量化1 小时前
Tornado 从入门到精通(二)上:协程核心机制详解
python
晴天161 小时前
AgentLoop分享(上): 让 AI 真正“自主干活“-Day15
人工智能·python
运维行者_1 小时前
企业带宽监控工具实战:网络流量分析与异常排查的5个关键能力
运维·服务器·开发语言·网络·分布式·后端·php
Patrick在香港1 小时前
Python爬虫框架实战:优雅抓取香港政府公开API数据的通用方案
java·开发语言·爬虫·python·ai编程·数据可视化·可用性测试
长栎2 小时前
你用了五年的消息队列,不知道它背后站着中介者模式
后端
Gopher_HBo2 小时前
路由注册:RouterGroup(routergroup.go)
后端
用户608186527902 小时前
Avalonia UI 控件样式定义的三种方式详解
后端
feng尘2 小时前
volatile 可见性与内存屏障知识点
后端
SamDeepThinking2 小时前
第3篇:企业级CAS单点登录实战-技术架构设计方案
后端·程序员·架构