我用四种方法为 text-to-SQL 提示挑选数据表
每个 text-to-SQL 提示都要带上表结构(schema)。全都发过去,每次调用都得为所有表付钱;只发几张,又可能正好漏掉问题需要的那张。所以怎么挑表很关键。
我在同一批问题上对比了四种做法,全程不调用模型:
- 完整表结构(Full schema):不做挑选。
- BM25:对每张表的定义做关键词检索。
- 向量检索(Embeddings):用 all-MiniLM-L6-v2 计算相似度,也就是 LangChain、LlamaIndex、Vanna 从向量库里挑表时的常见做法。
- schemagate:我维护的开源库,用的是同一个 MiniLM 模型。
每种方法拿到的表数量相同:在 Spider 2.0 的大型 BigQuery 和 Snowflake 数仓上为 12 张,在 BIRD 上为 6 张。
| 方法 | 数仓:所需表全部命中 | 数仓:token 数 | BIRD:所需表全部命中 | BIRD:token 数 |
|---|---|---|---|---|
| 完整表结构 | 93.8% | 56,237 | 100% | 579 |
| BM25 | 78.7% | 1,513 | 81.0% | 407 |
| 向量检索 | 78.2% | 1,555 | 89.4% | 438 |
| schemagate | 85.3% | 1,677 | 98.7% | 468 |
同一道题上,向量检索漏掉必需表、而 schemagate 全部命中的情况,在数仓数据集上有 17 次,反过来只有 1 次;BIRD 上是 151 比 9。
代价是:比普通检索多用 8–11% 的 token(模型按量计费的最小文本单位),多出来的主要是为了连接已选中的表而补进来的表。也正是这一步「补连接表」,让它的命中率更高。
没有测的部分:让大语言模型(LLM)自己挑表的选择器。那类做法每道题都要调一次模型,而这次比的是不花模型调用成本的一档。
脚本和完整结果都在这个 PR 里,想拿自己的问题跑一遍可以看:https://github.com/ashishsinha1602/schemagate/pull/189