NL2SQL 正确率怎么提升:ChatBI 的 `<error-msg>` 错误反馈闭环

NL2SQL 正确率怎么提升:ChatBI 的 <error-msg> 错误反馈闭环

标签:NL2SQL Text2SQL LLM Prompt Engineering ChatBI

背景

Text-to-SQL 工程里,LLM 生成的 SQL 常见三类错误:

类型 示例
语法错误 关键字拼错、引号/方言不匹配
语义错误 字段不存在、JOIN 条件错误
权限错误 访问了不该碰的表

ChatBI 在首轮生成前,已通过 M-Schema 表结构、术语库、SQL 样例训练降低错误率。但对复杂查询,仍需要第二层保障:执行 → 失败 → 捕获原生报错 → 注入 Prompt → 再生成。


整体架构

flowchart TD A[用户提问] --> B[LLM 生成 SQL] B --> C[exec_sql 执行] C --> D{结果} D -->|成功| E[返回数据] D -->|失败| F[save_error exec-sql-err] F --> G[用户再次提问] G --> H[get_last_execute_sql_error] H --> I[注入 error-msg] I --> B

核心实现

1. 执行失败:捕获并结构化存储

backend/apps/chat/task/llm.py:

python 复制代码
elif isinstance(e, ChatBIDBError):
    error_msg = orjson.dumps({
        'message': 'Execute SQL Failed',
        'traceback': str(e),
        'type': 'exec-sql-err'
    }).decode()
self.save_error(message=error_msg)

traceback 是数据库原生报错,不是 LLM 生成的解释。

2. 下轮读取:只取 exec-sql-err

backend/apps/chat/curd/chat.py:

python 复制代码
def get_last_execute_sql_error(session, chart_id):
    obj = orjson.loads(res)
    if obj.get('type') == 'exec-sql-err':
        return obj.get('traceback')
    return None

连接错误(db-connection-err)不会进入 SQL 修正闭环。

3. Prompt 注入

llm.py 初始化时:

python 复制代码
if last_execute_sql_error:
    self.chat_question.error_msg = f'''<error-msg>
{last_execute_sql_error}
</error-msg>'''

backend/template.yaml 用户 Prompt:

yaml 复制代码
user: |
  <background-infos>
    <current-time>{current_time}</current-time>
  </background-infos>
  {error_msg}
  <user-question>{question}</user-question>

System Prompt 已说明:<error-msg> 提供上次执行 SQL 的错误信息。

4. 多轮上下文控制

  • 历史消息通过 generate_sql_logs 保留
  • base_message_count_limit = 6 限制上下文,控制 token
  • 当前为用户触发的多轮修正,非服务端静默自动重试

时序图

sequenceDiagram participant U as 用户 participant FE as 前端 participant LLM as LLMService participant DB as 数据库 participant Store as ChatRecord U->>FE: 提问 FE->>LLM: 发起问数请求 LLM->>LLM: 读取上次 exec-sql-err LLM->>LLM: 组装 Prompt(含 error-msg) LLM->>LLM: 生成 SQL LLM->>DB: exec_sql DB-->>LLM: 执行失败 + 原生报错 LLM->>Store: save_error(traceback) LLM-->>FE: 返回错误 FE-->>U: 展示错误详情 U->>FE: 再次提问 Note over LLM,Store: 下轮自动带上 error-msg

错误分类策略

flowchart LR A[异常] --> B{类型} B -->|连接| C[db-connection-err → 提示检查连接] B -->|执行| D[exec-sql-err → 注入 error-msg] B -->|解析| E[ParseSQLResultError → 单独处理] B -->|业务| F[SingleMessageError → 直接返回]
错误 处理
syntax error at or near 修正关键字/引号,1--2 轮通常可解决
column does not exist 回查 M-Schema,可能需换字段或补 JOIN
permission denied 不重试,直接降级提示

前端 ErrorInfo.vue 区分展示:db-connection-err 显示数据源无效,exec-sql-err 显示执行失败并可展开 traceback。


重试上限与降级(演进方向)

现状:用户驱动 + 6 条历史上限,无自动重试计数器。

建议演进:

python 复制代码
MAX_AUTO_RETRY = 3

RETRYABLE = ['syntax error', 'does not exist', 'unknown column']
NON_RETRYABLE = ['permission denied', 'access denied']

def should_retry(error: str, count: int) -> bool:
    if count >= MAX_AUTO_RETRY:
        return False
    if any(k in error.lower() for k in NON_RETRYABLE):
        return False
    return any(k in error.lower() for k in RETRYABLE)

超限降级:友好提示 + 展示最后 SQL + 推荐简化问题。


设计 Checklist

  1. 捕获原生报错 --- 不用 LLM 翻译错误
  2. 结构化存储 --- JSON 区分 exec-sql-err / db-connection-err
  3. 专用标签注入 --- <error-msg> 与用户问题分离
  4. 按类型分流 --- 权限/连接错误不进修正闭环
  5. 重试上限 + 降级 --- 避免无限烧 token

相关代码路径

模块 路径
错误注入 backend/apps/chat/task/llm.py
错误读取 backend/apps/chat/curd/chat.py
Prompt 模板 backend/template.yaml
异常定义 backend/common/error.py
前端错误展示 frontend/src/views/chat/ErrorInfo.vue

总结

NL2SQL 工程化的核心,是把正确SQL从训练数据搬到运行时:数据库说错了什么,就把什么喂回模型。

ChatBI 的 <error-msg> 闭环不复杂,但抓住了「错了能改、改时有据」这个关键点。

相关推荐
roman_日积跬步-终至千里5 小时前
数仓开发的三层责任:业务定义、模型设计与 SQL 实现
数据库·数据仓库·sql·数据建模
Gauss松鼠会6 小时前
GaussDB 整体架构解析
运维·服务器·网络·数据库·sql·架构·gaussdb
Gauss松鼠会7 小时前
GaussDB 中 gsql 与 DBeaver(JDBC)客户端工具查询时间不一致:原因、排查与处理
运维·服务器·数据库·sql·gaussdb·经验总结
渣渣盟7 小时前
Flink SQL 流批一体:从 SQL 到执行计划,优化器如何工作?
大数据·sql·flink
Decay__13 小时前
05_MySQL 常用 SQL 大全 —— 诊断、管理、优化辅助 SQL 与三大系统库速查
运维·数据库·sql·mysql·架构
Decay__19 小时前
04_MySQL DBA 日常运维手册 —— 会话管理、锁与阻塞、事务监控、慢查询与日志巡检
运维·数据库·sql·mysql·架构
吃一碗粉只付一碗钱1 天前
10-令牌里的用户主键不要明文
服务器·数据库·sql·sqlserver·c#
sun03221 天前
【JDK 动态代理】 和 【CGLIB 代理】对比
java·数据库·sql
l1t1 天前
DeepSeek总结的AI 智能体应该用哪种语言搜索其记忆:SQL 还是 SPARQL?
数据库·人工智能·sql
geovindu1 天前
SQL Data Sampling and Approximation Techniques using postgreSQL 18
大数据·数据库·数据仓库·sql·postgresql·数据库开发·数据库架构