Solon v3.10.0

skills - Text2SqlSkill 数据库自然语言查询

</> markdown
2026年3月10日 下午6:50:40

Text2SqlSkill 赋予了智能体(Agent)直接通过自然语言与结构化数据库对话的能力。它不仅仅是简单的 SQL 生成,更集成了一套从元数据探测到方言适配,再到执行安全拦截的完整闭环。

相关依赖包:solon-ai-skill-text2sql

1、 核心特性

自适应方言引擎:

  • 内置多种 SqlDialect,自动识别 MySQL、PostgreSQL、Oracle 等数据库差异,自动处理引号转义、分页语法(Limit/Offset)及系统函数差异。

分级元数据策略:

  • FULL 模式(表 <= 20):自动注入全量 DDL 和备注,让 AI 拥有“全局视角”。
  • DYNAMIC 模式(表 > 20):仅注入表清单与关系地图,引导 AI 通过 get_table_schema 按需探测,节省 Token。

语义关联引导:

  • 自动提取外键关系(Foreign Keys)与表/列备注,为 AI 提供多表 Join 的“语义线索”。

执行安全护栏:

  • 强制只读校验(仅限 SELECT)、标识符自动修复(Alias Repairing)以及最大行数(Max Rows)限制。

2、应用示例

将数据库变成智能体的知识库,只需几行代码:

// 1. 初始化 Skill,指定数据源及允许 AI 访问的表范围
Text2SqlSkill sqlSkill = new Text2SqlSkill(dataSource, "users", "orders", "order_refunds")
        .maxRows(50)            // 限制单次返回最大行数,防止大表扫描
        .readOnly(true)         // 强制只读模式,拦截任何写操作
        .maxContextLength(8000) // 结果截断长度,保护 AI 上下文
        .schemaMode(SchemaMode.DYNAMIC); // 如果表非常多,建议手动开启动态模式

// 2. 构建 ReAct 智能体
ReActAgent agent = ReActAgent.of(chatModel)
        .role("财务分析专家")
        .instruction("你负责分析订单与退款数据。请结合表备注理解字段含义,金额单位均为元。")
        .defaultSkillAdd(sqlSkill)
        .build();

// 3. 执行任务
// Agent 会经历:Reasoning (分析表名) -> Action (生成/执行 SQL) -> Observation (结果分析)
String response = agent.prompt("张三在 2024 年一共有多少笔退款订单?总金额是多少?")
       .call()
       .getContent();

3. 工作流程:从意图到结果

环境探测:

  • 在 onAttach 阶段,Skill 自动识别数据库产品名并匹配最优方言。

Schema 注入:

  • AI 在 System Prompt 中会看到当前数据库的方言类型(如 MySQL)和系统时间。
  • 根据 SchemaMode,AI 会获得全量表结构或带有外键线索的“关系地图”。

SQL 修复与执行:

  • 当 AI 调用 execute_sql 时,Skill 会通过正则修复 AI 经常遗漏引号的别名(如 SELECT count(*) AS count 修复为符合方言的转义格式)。
  • 自动注入分页逻辑(防止 SELECT * 导致的 OOM)。

纠错反馈:

  • 如果执行报错,Skill 会利用方言引擎将复杂的 SQL 错误转化为对 AI 友好的 Hint(纠错建议)。

4、 内置管理工具

工具名称 (Tool)触发模式功能说明
execute_sql始终开启执行 SELECT 查询。自动进行别名修复、只读检查和分页补全。
get_table_schemaDYNAMIC 模式AI 用来“探测”具体某张表的详细字段定义(DDL)、备注及主键信息。

5、 最佳实践建议

  • 完善注释:在数据库中为表和关键字段添加 COMMENT。Text2SqlSkill 会自动提取这些备注,这是提升 AI 字段识别准确率的最有效手段。
  • 权限隔离:虽然 Skill 有 readOnly(true) 护栏,但仍强烈建议在数据库层面为 AI 连接配置只读账号。
  • 表范围控制:在构造函数中只传入当前任务相关的表名,减少干扰并显著降低 Token 消耗。