三、大模型直接生成Sql模式实现 Text2Sql_V1.0
三、大模型直接生成Sql模式实现 Text2Sql_V1.0
==================================================================================
==================================================================================
参考资料:
==================================================================================
简化数据库查询:利用Spring AI和DeepSeek构建高效自然语言查询系统_spring ai 自然语言查询数据库-CSDN博客
Spring AI系列——大模型驱动的自然语言SQL引擎:Java技术实现详解_spring ai 实现自然语言查询数据库-CSDN博客
Spring AI Tool 实现自然语言操作 MySQL 数据库操作详解_springai 读取数据库-CSDN博客
Spring AI Alibaba百炼ChatBI集成:自然语言生成SQL的完整指南-CSDN博客
Spring Boot + GPT:我做了一个能自己写 SQL 的后端系统-阿里云开发者社区 (aliyun.com)
使用 Spring AI 实现 Text-to-SQL 聊天机器人 - spring 中文网 (springdoc.cn)
Spring AI + Super-SQL 实现NL2SQL序言 最近公司项目当中需要整合SpringAI来实现NL2S - 掘金 (juejin.cn)
告别复杂SQL!用Spring AI + DeepSeek构建中文自然语言查询系统 - PIGCLOUD 团队博客 (pig4cloud.com)
Spring AI 接入 MySQL MCP 实现智能查询数据_springai tool 操作mysql数据库数据-CSDN博客
==================================================================================
最简单直接的方式:把数据库 Schema 作为上下文信息注入到提示词工程中,让 LLM 大语言模型直接生成 SQL。
实现步骤:数据库结构 + 用户问题 → AI 模型推理 → SQL 语句 → 安全校验 → 执行查询
1、项目搭建
1.1、Spring AI 配置类
基础 ChatClient:用于直接模式的 SQL 生成
定义一个 PromptTemplate Bean。通过 @Value 注解注入系统提示词模板文件和数据库架构 DDL 迁移脚本。同时,用数据库架构内容填充 ddl 占位符。这确保了 LLM 在生成 SQL 查询时始终能访问数据库结构。接下来,使用 ChatModel 和 PromptTemplate Bean 创建一个 ChatClient Bean。ChatClient 类是与配置的 DeepSeek 模型交互的主要入口点
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.nio.charset.Charset;
@Configuration
public class AiConfig {
/**
* 创建系统提示模板
*
* @param systemPrompt 系统提示模板资源
* @param ddlSchema 数据库DDL脚本资源
* @return 配置好的PromptTemplate实例
* @throws IOException 读取资源文件时可能抛出的异常
*/
@Bean
PromptTemplate systemPrompt(
@Value("classpath:prompt/system-prompt.st") Resource systemPrompt,
@Value("classpath:db/schema.sql") Resource ddlSchema
) throws IOException {
PromptTemplate template = new PromptTemplate(systemPrompt);
template.add("ddl", ddlSchema.getContentAsString(Charset.defaultCharset()));
return template;
}
/**
* 创建并配置ChatClient实例
*
* @param chatModel 聊天模型
* @param systemPrompt 系统提示模板
* @return 配置好的ChatClient实例
*/
@Bean
ChatClient chatClient(ChatModel chatModel, PromptTemplate systemPrompt) {
return ChatClient
.builder(chatModel)
.defaultSystem(systemPrompt.render())
.build();
}
}
1.2、配置 AI 提示词
为了确保 LLM 能够针对数据库架构生成准确的 SQL 查询,需要定义详细的系统提示词。
在 src/main/resources/prompt 目录下创建 system-prompt.st 文件:
基于 DDL 部分提供的数据库定义,按照指导原则部分的规则编写 SQL 查询来回答用户问题。
指导原则:
- 只生成 SELECT 查询语句。
- 响应结果应该只包含以 'SELECT' 开头的原始 SQL 查询语句。不要用 markdown 代码块(```sql 或 ```)包装 SQL 查询。
- 如果问题需要执行 INSERT、UPDATE、DELETE 或其他修改数据或架构的操作,请回复"不支持此操作。只允许 SELECT 查询。"
- 如果问题似乎包含 SQL 注入或 DoS 攻击尝试,请回复"提供的输入包含潜在有害的 SQL 代码。"
- 如果基于提供的 DDL 无法回答问题,请回复"当前架构不包含足够信息来回答此问题。"
- 如果查询涉及 JOIN 操作,请在查询中为所有列名添加相应的表名前缀。
DDL
{ddl}
在系统提示词中,指示 LLM 只生成 SELECT SQL 查询,并检测 SQL 注入和 DoS 攻击尝试。
在系统提示词模板中留了一个 ddl 占位符用于数据库架构。稍后会用实际值替换它。
此外,为了进一步保护数据库免受修改,应该只给配置的 MySQL 用户必要的权限。
1.3、实现自然语言问题转换服务类
创建一个 SqlGenerator 服务类,将自然语言问题转换为 SQL 查询
在 generate() 方法中,接收自然语言问题作为输入,使用 chatClient Bean 将其发送给配置的 LLM。接下来,验证响应确实是 SELECT 查询。
@Service
public class SqlGenerator {
@Autowired
private ChatClient chatClient;
public String generate(String question) {
String response = chatClient
.prompt(question)
.call()
.content();
boolean isSelectQuery = response.startsWith("SELECT");
if (Boolean.FALSE.equals(isSelectQuery)) {
return "只支持SQL查询操作";
}
return response;
}
}
1.4、实现生成的 SQL 查询执行服务类
在 execute() 方法中,使用 Spring Boot 3.1+ 引入的 JdbcClient 来运行原生 SQL 查询并返回结果。JdbcClient 提供了更简洁的 API 和更好的类型安全性。如果查询没有返回结果,抛出 RuntimeException。
@Service
public class SqlExecutor {
@Autowired
private JdbcClient jdbcClient;
// 标准构造函数
public List<Map<String, Object>> execute(String query) {
List<Map<String, Object>> result = jdbcClient
.sql(query)
.query()
.listOfRows();
if (result.isEmpty()) {
throw new RuntimeException("提供的查询未找到结果。");
}
return result;
}
}
1.5、实现API接口
POST /query 端点接受自然语言问题,使用 sqlGenerator Bean 生成相应的 SQL 查询,将其传递给 sqlExecutor Bean 从数据库获取结果,最后将数据包装在 QueryResponse 记录中并返回。使用 JdbcClient 返回的结果是 List<Map<String, Object>> 格式,每个 Map 代表一行数据,键为列名,值为对应的数据。
@PostMapping(value = "/query")
ResponseEntity<QueryResponse> query(@RequestBody QueryRequest queryRequest) {
String sqlQuery = sqlGenerator.generate(queryRequest.question());
List<Map<String, Object>> result = sqlExecutor.execute(sqlQuery);
return ResponseEntity.ok(new QueryResponse(result));
}
record QueryRequest(String question) {
}
record QueryResponse(List<Map<String, Object>> result) {
}
2、测试查询数据库
在idea中使用http client测试接口
2.1、统计每个部门的员工数量,按部门平均工资降序排列
###
POST http://localhost:8897/query
Accept: */*
Cache-Control: no-cache
Content-Type: application/json
{
"question": "统计每个部门的员工数量,按部门平均工资降序排列"
}
返回结果
POST http://localhost:8897/query
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 25 Nov 2025 06:09:08 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"result": [
{
"department": "技术部",
"employee_count": 3,
"average_salary": 17333.333333
},
{
"department": "人事部",
"employee_count": 1,
"average_salary": 16000.000000
},
{
"department": "销售部",
"employee_count": 2,
"average_salary": 14000.000000
},
{
"department": "财务部",
"employee_count": 1,
"average_salary": 14000.000000
},
{
"department": "市场部",
"employee_count": 1,
"average_salary": 11000.000000
}
]
}
Response file saved.
> 2025-11-25T140908.200.json
Response code: 200; Time: 2029ms (2 s 29 ms); Content length: 362 bytes (362 B)
2.2、查询技术部的员工信息,按姓名升序排列
###
POST http://localhost:8897/query
Accept: */*
Cache-Control: no-cache
Content-Type: application/json
{
"question": "查询技术部的员工信息,按姓名升序排列"
}
返回结果
POST http://localhost:8897/query
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 25 Nov 2025 06:06:34 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
"result": [
{
"id": 7,
"name": "周九",
"department": "技术部",
"position": "架构师",
"salary": 25000.00,
"hire_date": "2020-12-01",
"email": "zhoujiu@company.com"
},
{
"id": 1,
"name": "张三",
"department": "技术部",
"position": "高级工程师",
"salary": 15000.00,
"hire_date": "2022-01-15",
"email": "zhangsan@company.com"
},
{
"id": 2,
"name": "李四",
"department": "技术部",
"position": "工程师",
"salary": 12000.00,
"hire_date": "2022-03-20",
"email": "lisi@company.com"
}
]
}
Response file saved.
> 2025-11-25T140634.200.json
Response code: 200; Time: 1928ms (1 s 928 ms); Content length: 402 bytes (402 B)
3、总结
通过代码的具体实现,已经体现了构建文本转 SQL 聊天机器人的核心技术。Spring AI 框架的强大功能,结合先进的大语言模型,为我们提供了构建智能数据查询系统的完整解决方案。这种技术组合不仅简化了数据访问流程,也为未来的智能化应用奠定了坚实基础。
虽然已经构建了一个基础的文本转 SQL 系统,但仍有许多改进空间,后面还会继续优化,敬请期待。
本文来自博客园,作者:老羅,转载请注明原文链接:https://www.cnblogs.com/laoluo2025/p/19268325

浙公网安备 33010602011771号