背景

遇到一个用户需求:
查询大数据级数据表(如产品表),将查询结果返回,想通过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:
在这里插入图片描述
用户问题:
在这里插入图片描述

实操过程

  1. 基本思路的流程图,关键是目标如何达成,串联起来闭环。
    在这里插入图片描述

  2. 上手开撸
    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
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐