(六)Prompt 优化

针对 Text-to-SQL 场景,Prompt 优化的核心目标是消除歧义、减少模型试错、让 SQL 一步生成到位 ,从根源解决 max iterations 超限问题,同时大幅提升查询准确率。

下面按优先级排序,结合你的公交维修业务场景,讲透可直接落地的优化方法,最后给出完整的优化版模板。


一、Prompt 优化的 6 个核心维度

1. 结构化 Schema 信息:消除字段歧义(最基础)

模型 80% 的试错都来自「字段含义不清、同名不同义」。不要只扔表名,要把每张表的字段、类型、业务含义、枚举值都写清楚。

优化要点:

  • 分表罗列,核心字段标注业务注释
  • 重名字段必须明确区分(比如车辆状态和工单状态都叫 status)
  • 枚举值直接写出编码对应的业务含义

示例(你的业务场景):

复制代码
【可用表及核心字段】
1. bus_vehicle(车辆基础表)
   - vehicle_id INT 车辆唯一ID(主键)
   - bus_no VARCHAR 车辆自编号(内部运营编号)
   - plate_no VARCHAR 车牌号
   - model VARCHAR 车型
   - fleet_id INT 所属车队ID(外键)
   - buy_date DATE 购置日期
   - status TINYINT 车辆状态:1=运营中,2=维修中,3=停运

2. bus_fleet(车队组织表)
   - fleet_id INT 车队ID(主键)
   - fleet_name VARCHAR 车队名称,如"119车队"
   - company_name VARCHAR 分公司名称,如"第一运营分公司"

3. repair_order(维修工单表)
   - order_id INT 工单ID(主键)
   - vehicle_id INT 关联车辆ID(外键)
   - fault_type VARCHAR 故障类型:电机系统/底盘系统/电气系统/车身系统
   - repair_content TEXT 维修内容
   - order_time DATETIME 报修时间
   - status TINYINT 工单状态:1=待修,2=维修中,3=已完成

2. 显式声明表关联关系:避免模型瞎猜

多表查询时,模型会浪费大量迭代去猜测用哪个字段关联。直接把所有关联关系写死,一步到位。

示例:

复制代码
【表关联关系(必须严格遵守)】
- 车辆归属车队:bus_vehicle.fleet_id = bus_fleet.fleet_id
- 工单对应车辆:repair_order.vehicle_id = bus_vehicle.vehicle_id

3. 业务术语字典:打通自然语言与数据库编码

业务口语和数据库编码的映射,是场景化准确率的核心。模型不知道「一公司」「坏车」「上月」对应什么,就会反复试错。

示例:

复制代码
【业务字典(必须严格匹配)】
- "一公司" / "第一分公司" = company_name = "第一运营分公司"
- "X车队" = fleet_name = "X车队"
- "坏车" / "待修车" = 车辆status = 2(维修中)
- "上月" = 时间范围为上一个自然月的第一天到最后一天
- "近30天" = order_time >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)

4. Few-shot 少样本示例(性价比最高的优化)

给模型 3~5 个「业务问题 → 正确 SQL」的真实示例,模型会直接模仿格式和逻辑,迭代次数通常能从 5+ 次降到 1~2 次。

示例要点:

  • 覆盖常见查询类型:清单查询、统计计数、时间筛选、多表关联
  • SQL 写法就是你期望的标准写法
  • 示例越贴近真实业务,效果越好

示例:

复制代码
【参考示例】
问:一公司119车队的车辆清单
答:SELECT v.bus_no, v.plate_no, v.model, v.status 
    FROM bus_vehicle v 
    JOIN bus_fleet f ON v.fleet_id = f.fleet_id 
    WHERE f.company_name='第一运营分公司' AND f.fleet_name='119车队'

问:119车队上个月有多少条维修工单
答:SELECT COUNT(*) as 工单数量 
    FROM repair_order r
    JOIN bus_vehicle v ON r.vehicle_id = v.vehicle_id
    JOIN bus_fleet f ON v.fleet_id = f.fleet_id
    WHERE f.fleet_name='119车队' 
    AND r.order_time BETWEEN '2026-08-01 00:00:00' AND '2026-08-31 23:59:59'

问:运营中车辆最多的是哪个车队
答:SELECT f.fleet_name, COUNT(*) as 运营车辆数
    FROM bus_vehicle v
    JOIN bus_fleet f ON v.fleet_id = f.fleet_id
    WHERE v.status = 1
    GROUP BY f.fleet_name
    ORDER BY 运营车辆数 DESC
    LIMIT 1

5. 硬性约束规则:划定边界,避免无效操作

明确告诉模型什么能做、什么不能做、输出格式是什么,减少不必要的推理和返工。

示例:

复制代码
【严格规则】
1. 只能生成 SELECT 查询语句,绝对禁止 DELETE/UPDATE/INSERT/DROP/ALTER 等任何修改语句
2. 禁止使用 SELECT *,必须明确列出需要的字段
3. 必须使用表别名(如 v 代表 bus_vehicle),提升SQL可读性
4. 如果问题缺少必要条件或语义模糊,请直接反问用户,不要猜测编造
5. 回答格式:先给出自然语言结论,再附上数据表格
6. 如果查询无结果,明确告知用户"未查询到符合条件的数据"

6. 思维链(CoT)引导:先思考再写 SQL

让模型先理清楚逻辑再写代码,看似多了一步,实则减少了后续反复修正的次数,整体迭代更少、准确率更高。

示例指令(加在Prompt末尾):

复制代码
【答题步骤】
请先按以下步骤思考,再输出最终答案:
1. 用户的核心需求是什么
2. 需要用到哪几张表
3. 表之间的关联条件是什么
4. 筛选条件有哪些
5. 需要返回哪些字段
思考完成后,直接写出完整的SQL语句并执行。

二、进阶优化技巧(适合复杂场景)

1. 表召回前置

如果你的数据库有十几张甚至几十张表,不要全塞给模型。先做一步「表召回」:用关键词匹配或向量检索,只把和当前问题相关的 2~3 张表的 Schema 传给模型,减少信息干扰。

2. 错误自修正提示

把模型常犯的错误直接写在提示里,让它自己检查。

复制代码
【常见错误自查】
写完SQL后,请先自查:
- 有没有用 SELECT *
- 表关联条件是否正确
- 状态枚举值有没有用错
- 时间范围是否完整
有错误就自行修正,再执行。

3. 动态字段裁剪

根据问题类型只返回相关字段。比如问「数量」就只给统计相关字段,问「清单」就给基础信息字段,避免冗余信息干扰。


三、完整优化版 Prompt(直接替换到代码里)

把上面所有优化点整合,针对你的公交维修场景,最终版如下:

python 复制代码
custom_prompt = """
你是公交机务数据查询专家,只能根据提供的数据库表结构回答问题。

【可用表及核心字段】
1. bus_vehicle(车辆基础表)
   - vehicle_id INT 车辆唯一ID(主键)
   - bus_no VARCHAR 车辆自编号(内部运营编号)
   - plate_no VARCHAR 车牌号
   - model VARCHAR 车型
   - fleet_id INT 所属车队ID(外键)
   - buy_date DATE 购置日期
   - status TINYINT 车辆状态:1=运营中,2=维修中,3=停运

2. bus_fleet(车队组织表)
   - fleet_id INT 车队ID(主键)
   - fleet_name VARCHAR 车队名称,如"119车队"
   - company_name VARCHAR 分公司名称,如"第一运营分公司"

3. repair_order(维修工单表)
   - order_id INT 工单ID(主键)
   - vehicle_id INT 关联车辆ID(外键)
   - fault_type VARCHAR 故障类型:电机系统/底盘系统/电气系统/车身系统
   - repair_content TEXT 维修内容
   - order_time DATETIME 报修时间
   - status TINYINT 工单状态:1=待修,2=维修中,3=已完成

【表关联关系(必须严格遵守)】
- 车辆归属车队:bus_vehicle.fleet_id = bus_fleet.fleet_id
- 工单对应车辆:repair_order.vehicle_id = bus_vehicle.vehicle_id

【业务字典(必须严格匹配)】
- "一公司" / "第一分公司" = company_name = "第一运营分公司"
- "X车队" = fleet_name = "X车队"
- "坏车" / "待修车" = 车辆status = 2(维修中)
- "上月" = 时间范围为上一个自然月的第一天0点到最后一天23:59:59
- "近30天" = order_time >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)

【严格规则】
1. 只能生成 SELECT 查询语句,绝对禁止 DELETE/UPDATE/INSERT/DROP/ALTER 等任何修改语句
2. 禁止使用 SELECT *,必须明确列出需要的字段
3. 必须使用表别名(如 v 代表 bus_vehicle),提升SQL可读性
4. 如果问题缺少必要条件或语义模糊,请直接反问用户,不要猜测编造
5. 回答格式:先给出自然语言结论,再附上数据表格
6. 如果查询无结果,明确告知用户"未查询到符合条件的数据"

【参考示例】
问:一公司119车队的车辆清单
答:SELECT v.bus_no, v.plate_no, v.model, v.status 
    FROM bus_vehicle v 
    JOIN bus_fleet f ON v.fleet_id = f.fleet_id 
    WHERE f.company_name='第一运营分公司' AND f.fleet_name='119车队'

问:119车队上个月有多少条维修工单
答:SELECT COUNT(*) as 工单数量 
    FROM repair_order r
    JOIN bus_vehicle v ON r.vehicle_id = v.vehicle_id
    JOIN bus_fleet f ON v.fleet_id = f.fleet_id
    WHERE f.fleet_name='119车队' 
    AND r.order_time BETWEEN '2026-08-01 00:00:00' AND '2026-08-31 23:59:59'

【答题步骤】
请先按以下步骤思考,再输出最终答案:
1. 用户的核心需求是什么
2. 需要用到哪几张表
3. 表之间的关联条件是什么
4. 筛选条件有哪些
5. 需要返回哪些字段
思考完成后,直接写出完整的SQL语句并执行。
"""

四、优化效果验证方法

  1. 开启 verbose 日志 :把 verbose=True 打开,观察 Agent 迭代次数
    • 优化前:复杂问题可能 5~8 步还没做完
    • 优化后:绝大多数问题 1~2 步就能生成正确SQL并执行
  2. 校验 SQL 正确性:看生成的 SQL 语法、关联条件、筛选值是否符合业务预期
  3. Bad Case 迭代:把答错的问题和正确 SQL 补充到 Few-shot 示例里,持续迭代

五、常见避坑点

  1. 不要信息过载:只开放必要的表和字段,表越多、字段越多,模型越容易出错
  2. 不要模糊表述:所有业务术语都要有明确映射,不要让模型「意会」
  3. 示例不要太简单:示例要覆盖真实的复杂场景,只用单表查询示例没用
  4. 不要频繁改结构:数据库表结构变更时,同步更新 Prompt 里的
相关推荐
Elcker1 小时前
Ynuo Agent(依诺) 一 Agentic 设计模式详解
agent·ai编程
小鹿的周先生1 小时前
第19章-Agent
java·spring·ai
全栈练习生1 小时前
大模型推理全链路
python·ai
欣欣之王来了1 小时前
2024主流国产大模型深度对比:文心一言/通义千问/智谱AI/Qwen等选型指南
人工智能·ai·大模型
泡海椒2 小时前
JQuick-Excel VALIDATION 实战:用作用范围约束 Excel 导入校验
开发语言·python·excel
threerocks2 小时前
速来!认领你的「口播Bot」,妈妈再也不用担心我做口播视频了!
人工智能·aigc·ai编程
笨蛋©2 小时前
2026制造业质量数字化:Infra CONVERT 中国代理技术支持下的检验计划自动化实战
ai·数字化·cad·质量管理·制造业
颜进强2 小时前
26 · NestJS 基础篇 · 全专栏总结:五个阶段,一次收拢
前端·后端·ai编程
玩AI的奶茶3 小时前
从零到跑通:在算家云上部署大模型的完整操作手册(实例创建 / 镜像选择 / 远程连接 / 成本控制)
人工智能·ai·gpu算力·token·算力租赁