用 LLM 给 1245 张数据库表写描述反而让检索效果崩了

数据分析师Leo 专家 1小时前 93 浏览 6 点赞 约 3 分钟

给数据库表做索引时,最直觉的操作就是让 LLM 把那些像 v_pmpm 这样看不懂的表名翻译成人类语言的描述,然后把描述和表名一起存入向量库或全文索引。理论上这能弥补用户查询词(英文)与表名(缩写/代码)之间的鸿沟。但我实测一个包含 1245 张表的真实 Schema 时,结果完全相反:检索召回率不仅没升,反而暴跌。

最离谱的是,原先直接搜 contacts 能排在第 3 位的表,在加上了 LLM 生成的准确描述后,竟然掉到了 40 名以后。这意味着描述写得越准确,检索越没用。

为什么描述写得越准确,检索反而越差?

问题出在 BM25 的 IDF(逆文档频率)机制上。BM25 衡量一个词的权重取决于它在整个语料库中出现的频率:

idf(t) = log(1 + (N - n_t + 0.5) / (n_t + 0.5))

简单说,一个词在越少的文档里出现,它的权重(区分度)就越高。

但在 CRM 这种业务场景下,LLM 描述表时会陷入一个陷阱:虽然它写得没错,但它习惯用同一套词汇。比如描述 contacts 表时会提到 "contacts",描述 contact_lists 时也会提到 "contacts",甚至描述审计表或用户表时,因为业务相关性,LLM 也会写上 "contacts"。

结果就是,在 1245 个文档里,"contact" 这个词竟然出现了 1072 次。在算法眼里,这个词已经从一个“高价值的关键词”变成了像 "the" 或 "and" 一样的“停用词”。

我核对了一下数据,在只有表名时,"contact" 的 IDF 值是 4.27(高区分度);但在加上 LLM 描述后,这个值直接掉到了 0.15。这意味着用户输入 "contacts" 时,系统认为这个词毫无区分度,无法帮你定位到核心表。

长度归一化带来的二次打击

如果说 IDF 崩塌只是让排名变平,那么 BM25 的长度归一化(Length Normalization)则直接把排名给反转了。

BM25 有个参数 b,用来惩罚过长的文档。逻辑是:一个长文档里出现一次关键词,不如短文档里出现一次关键词那么“相关”。

但在数据库 Schema 场景里,最核心的表(比如 contacts 表)通常字段最多,列名最长,再加上 LLM 生成的描述,它的文档长度远超平均值。而那些边缘表(比如 contact_import_log)只有几个字段,加上一句简单的描述后依然很短。

结果就变成了:

  • 核心表: 包含关键词 → 文档太长 → 被惩罚 → 排名后移。
  • 边缘表: 包含关键词 → 文档短 → 权重高 → 排名上升。

这两个因素叠加在一起,导致原本最相关的表被排到了后面,而一些无关紧要的日志表反而冲到了前面。

避坑指南:怎么做才有效?

如果你也在做 Text-to-SQL 或者文档增强索引,千万不要盲目相信「LLM 总结 → 索引」这个链路。

第一,不要把 LLM 描述和原始名称放在同一个检索字段里。
建议采用双路检索或权重分离。给表名(Schema Name)极高的权重,给 LLM 描述较低的权重。不要让 LLM 生成的自然语言稀释了原始标识符的唯一性。

第二,控制描述的词汇多样性。
在 Prompt 里强制要求 LLM 避免使用泛化词,或者在索引前对描述进行关键词提取,而不是直接索引整段话。

第三,针对数据库场景,考虑禁用或调整长度惩罚。
在处理 Schema 这种结构化数据的元数据时,文档长度与相关性并不成反比(核心表字段多是正常现象),此时降低 b 参数的值可以缓解排名反转的问题。

这次实操让我意识到,所谓的「增强」如果破坏了数据的分布特性,实际上就是一种「噪声」。

BM25Text-to-SQLRetrieval
同类方向的延伸案例可以参考AI大模型变现案例库,有不少直接可参考的案例。

全部回复 (3)

强迫症脚本小子 专家 1小时前

这种纯靠捐款吊命的科研模式也太心酸了,要是真崩了,那几个核心库谁来维护?

0 回复
独立开发者Leo 专家 1小时前

这破网站加载速度慢得要死,等了快10秒才开出来,你确定这玩意儿好用?

0 回复
数据分析师大山 中级 1小时前

又在画饼,不用工程就敢说 scalable?赶紧告诉我这玩意儿跑 1000 个并发会不会直接崩掉。

0 回复

发表回复

支持 Markdown 格式