text2sql 怎么把表结构喂给模型
先抛结论:让模型写对 SQL,难点不在模型,在你怎么把库里的表结构喂给它。表结构给得糙,再聪明的模型也会瞎编字段名。我自己踩了一圈,最后稳定下来的喂法记在这。
我做的是一个让运营同学用大白话查数据的小工具。第一版我偷懒,直接把整个库的CREATE TABLE语句一股脑拼进 prompt,37 张表全塞进去,结果两件事同时发生:一是 token 直接顶到八千多,二是模型经常把别的表的字段张冠李戴,写出来的 SQL 跑都跑不起来。
表结构到底喂什么
我现在只喂三样,多一个字都不给:
表名 + 一句话表注释(这张表是干啥的)
字段名 + 类型 + 字段注释
每张表挑 2~3 行真实样例数据
样例数据是后加的,效果出乎意料地好。模型光看status int不知道 1 代表啥,但看到样例里status=1那行用户是"已付款",它就懂了枚举含义,WHERE 条件不再乱填。
喂进去的格式我用的是这种紧凑写法,比贴原始 DDL 省一半 token:
表: orders (订单主表) 字段: - id bigint 订单ID - user_id bigint 下单用户ID - amount decimal 金额(元) - status int 状态 1已付款 2已发货 3已完成 0已取消 - created_at datetime 下单时间 样例: id=1001 user_id=88 amount=29.90 status=3 created_at=2026-06-01 10:22:00注意我把status的枚举含义直接写进字段注释了。这一步比给样例还关键——枚举值不解释,模型十有八九猜错。
表太多怎么办
37 张表全喂肯定不行。我的做法是先做一轮"表召回":把用户问题和每张表的表注释做一次向量检索,只把最相关的 3~5 张表的结构喂给写 SQL 的那一步。
落地我是在一个能拖低代码工作流的平台上搭的,第一个节点做表召回(挂了个 RAG 检索),第二个节点才是真正写 SQL。这样平均喂进去的表从 37 张降到 4 张,token 从八千多压到一千出头,准确率反而上去了——因为干扰项少了。
两个具体的坑
坑一:外键关系模型看不出来。光给单表结构,遇到要 JOIN 的问题模型就抓瞎。我后来在 prompt 里单独加了一段"表关系"说明,像orders.user_id = users.id,写明哪些表能 JOIN、JOIN 哪个字段。加完之后跨表查询的成功率从大概六成涨到九成。
坑二:别让模型直接连库。我让模型只输出 SQL 文本,再由后端代码去执行,而且执行前强制套一层LIMIT 200。有次模型生成了个没带条件的全表 scan,要不是这个 LIMIT 兜底,那张两千万行的表能把库拖垮。
小结
text2sql 这事,七分在数据准备(表结构怎么裁、怎么注释、给不给样例),三分才在模型。把这套喂法跑顺之后,运营那边自助查数的比例明显上来了,找我跑 SQL 的人少了一多半。
剩下唯一没根治的是模糊问法——用户问"上个月卖得好的",到底"好"是按数量还是金额,模型只能猜,这种我现在是让它先反问一句。模型那层我直接用了讯飞星辰提供的现成大模型 API,免得自己搭推理服务,省下的精力都花在打磨表结构上了。
