原创|查询大数据级数据表的AI实现思路(Excel2SQL,Text2SQL)
·
背景
遇到一个用户需求:
查询大数据级数据表(如产品表),将查询结果返回,想通过LLM进行精准输出。
一般软件做法为找数据工程师做提数SQL,或通过前台页面筛选条件+查询表单实现相对灵活的查询。
这个需求他们通过截图表格+输入问题的形式问Deepseek等LLM,发现准确度和稳定性都不行,
- 其一产品ABC命名有相似且产品行数多,噪音大,导致稳定性不足;
- 其次有一些统计问题回答不对,比如开发售卖的产品有几只,了解LLM原理的也知道数学题超过LLM能力边界。
Boss问我想法时,对于噪音和数学题,我明确知道要借助Workflow可能有解决方案,加上之前接触过Text2SQL,
我的第一反应是以SQL作为对其模态,
- 输入方向(广义的知识构建阶段),将EXCEL输出SQL数据表和数据,并生成足够的释义作为回答的背景;
- 输出方向(广义的知识检索阶段),初始节点为用户问题Text2SQL,然后执行SQL节点,将问题,SQL和SQL查询结果给到二次LLM节点,输出最终回答。
通过Dify和FastGPT都可以实现两段式输入到输出
结果
是验证了50条excel含5个字段的产品表,问了30个问题,迭代3版Prompt达到28/30的惊人的95%的正确率。
输入Excel:

用户问题:

实操过程
-
基本思路的流程图,关键是目标如何达成,串联起来闭环。

-
上手开撸
AI workfow其实没什么难度,就是3个节点,LLM或MCP/Faction call进行数据库处理;
主要还是Prompt,此处分享粗调最后一版prompt。
[构建]读取excel到输出SQL
# 指令
认真阅读与理解输入excel的内容,依次执行以下任务:
1. 生成建表语句:将表格输出注释完整的、可执行的建表SQL语句。
2. 生成插入语句:将表格的全部数据记录输出成数据写入SQL语句,要求必须保证完整性,按顺序输出全部内容行,不可以遗漏。
5. 生成查询示例SQL语句:涵盖查询信息,数量等典型使用场景,如查询基金代码为xx的基金信息,统计满足某些字段条件的基金数量,根据实际场景生成1-5个符合当前内容的查询语句,一定要在建表和插入语句下多次检查其正确性,这个很重要。
4. 生成建表语句json:生成建表语句的json对象,包括表名与描述,描述包含表名及描述、字段名及描述以及查询示例SQL语句。
5. 生成表字典插入SQL语句:将表名和建表语句json作为一条数据记录,插入到一个名为ai_codetable的表中。
# 要求
- 严格按任务要求顺序执行,100%完成任务
- SQL语句使用严格MYSQL语法,目标是完整性且可直接执行,不需要在意美观,如不使用“\n”等影响执行的换行符
- 表字典插入SQL语句为:INSERT INTO `ai_codetable` (`table_name`, `table_desc`) VALUES ('表名', '建表语句json')
- 严格按照输出格式要求进行输出,格式严格,不允许出现省略,需要100%完整性输出。
- 生成插入语句很多时,可以使用批量插入语句,如:INSERT INTO `table_name` (`field1`, `field2`, `field3`) VALUES ('value1', 'value2', 'value3'), ('value1', 'value2', 'value3');一定要保证完整性,按顺序输出全部内容行,不可以遗漏。
# 输出格式要求
{
"CREATE_SQL": "生成建表语句替换",
"INSERT_SQL": "生成插入语句替换",
"TABLE_JSON": "生成建表语句json替换",
"INSERT_AI_CODETABLE": "生成表字典插入SQL语句替换",
"QUERY_SQL": "生成一些使用场景查询SQL替换"
}
# 示例
## 建表语句json示例
{
"table_name": {
"hx_overseas_fund_status": "华夏海外基金业务开放状态表"
},
"table_fields": {
"id": "主键ID",
"fund_name": "基金名称",
"fund_code": "基金代码",
"purchase_status": "申购开放状态",
"redemption_status": "赎回开放状态",
"switch_in_status": "转换入开放状态",
"switch_out_status": "转换出开放状态",
"fixed_investment_status": "定投开放状态",
"create_time": "创建时间",
"update_time": "更新时间"
},
table_usecase": "/*查询基金代码为111141的基金信息*/SELECT * FROM `hx_overseas_fund_status` WHERE `fund_code` = '111141'; /*查询申购开放状态为开放-有限制的基金数量*/SELECT COUNT(*) FROM `hx_overseas_fund_status` WHERE `purchase_status` = '开放-有限制'; /*查询定投开放状态为开放的基金信息*/SELECT * FROM `hx_overseas_fund_status` WHERE `fixed_investment_status` = '开放'; /*查询转换入和转换出都开放的基金信息*/SELECT * FROM `hx_overseas_fund_status` WHERE `switch_in_status` = '开放' AND `switch_out_status` = '开放'; /*统计各类申购开放状态的基金数量*/SELECT `purchase_status`, COUNT(*) AS count FROM `hx_overseas_fund_status` GROUP BY `purchase_status`;",
"notes": [
"table_name 为表名及其描述",
"table_fields 为字段及其描述",
"table_usecase 为使用场景示例",
"notes 为补充说明"
]
}
## 查询示例SQL语句示例
/*查询申购开放状态(purchase_status)为开放-有限制)的基金数量*/SELECT COUNT(*) FROM `hx_overseas_fund_status` WHERE `purchase_status` = '开放-有限制';
[检索]用户问题转SQL
# 指令
对于输入的问题,仅限于背景信息,输出最准确,可靠的SQL文本。
# 背景
- 每个最外层"{}"包含一套表的说明,由TABLE_JSON和QUERY_SQL两个字段组成;TABLE_JSON是表结构描述,QUERY_SQL是典型查询SQL示例。
‘’‘
{
/*TABLE_JSON是相关表结构,QUERY_SQL是典型查询SQL示例*/
"TABLE_JSON": "{\"table_name\": {\"hx_overseas_fund_status\": \"华夏海外基金业务开放状态表\"}, \"table_fields\": {\"id\": \"主键ID\", \"fund_name\": \"基金名称\", \"fund_code\": \"基金代码\", \"purchase_status\": \"申购开放状态\", \"redemption_status\": \"赎回开放状态\", \"switch_in_status\": \"转换入开放状态\", \"switch_out_status\": \"转换出开放状态\", \"fixed_investment_status\": \"定投开放状态\", \"create_time\": \"创建时间\", \"update_time\": \"更新时间\"}, \"notes\": [\"table_name 为表名及其描述\", \"table_fields 为字段及其描述\", \"notes 为补充说明\"]}",
"QUERY_SQL": "/*查询基金代码为111141的基金信息*/SELECT * FROM `hx_overseas_fund_status` WHERE `fund_code` = '111141'; /*查询申购开放状态为开放-有限制的基金数量*/SELECT COUNT(*) FROM `hx_overseas_fund_status` WHERE `purchase_status` = '开放-有限制'; /*查询定投开放状态为开放的基金信息*/SELECT * FROM `hx_overseas_fund_status` WHERE `fixed_investment_status` = '开放'; /*查询转换入和转换出都开放的基金信息*/SELECT * FROM `hx_overseas_fund_status` WHERE `switch_in_status` = '开放' AND `switch_out_status` = '开放'; /*统计各类申购开放状态的基金数量*/SELECT `purchase_status`, COUNT(*) AS count FROM `hx_overseas_fund_status` GROUP BY `purchase_status`;"
}
‘’‘
- 额外背景知识补充:
- 基金名称由中文、字母和小括号("("与")")组合而成,不会包含其他特殊字符,也不会包括空格,查询前需要做预处理
- 基金代码一般由6位数字代码组成,也会出现带"SH"或"SZ"前缀的情况,不会包含其他特殊字符,也不会包括空格,查询前需要做预处理
- xx基金的判定规则一般体现在xx出现在基金名称内,如QDII基金的基金名称内会包含"QDII",联接基金名称内会包含"联接",发起式基金名称内会包含"发起式"
- C类或A类基金的规则时基金名称内包含"C"或"A",如"中证AH经济蓝筹股票指数C"是C类,所以还要根据以下规则做二次约束
- A/C作为结尾
- A/C不是结尾,但后一位会接字母
- 业务有:申购,赎回,转换入,转换出,定投
- 业务状态有:开放,开放-有限制,未开放
- 当询问业务状态时,关闭=未开放;开放包含开放和开放-有限制
# 要求
- 需要3次以上思考、复盘和确认,是否输出的是最准确的SQL文本,需要保证置信度>80%,进行输出,否则重新生成。
- 当思考10次还无法满足以上置信度前提,则输出疑问,与用户进行确认存疑项,问题可以帮助提高置信度。
- 再次复核与审题,最终输出是否可回答输入问题
# 输出格式要求
- 当置信度满足要求时,仅输出可执行的、准确的SQL文本,不需要输出任何解释或说明。SQL语句使用严格MYSQL语法,目标是可执行性,准确性,不需要在意美观,如不使用“\n”等影响执行的换行符
- 当置信度不满足要求时,输出疑问,与用户进行确认存疑项,问题旨在解决问题,帮助下一次回答的置信度。
构建AI workflow流程图

检索AI workflow流程图


最后
- 因为fastGPT薅公司的云服务版本(本身也是work!),没法和我本地数据库连通,所以还是本着MVP手撸执行SQL,充当人肉搬运工
- 上agent平台通过插件/factionCall/MCP 链接数据库就非常丝滑了(fastGPT有现成插件可用)
- 基于企业级应用,且关注时效,本次使用的都是deepseek-v3-0324
更多推荐


所有评论(0)