Spring AI系列——大模型驱动的自然语言SQL引擎:Java技术实现详解

1. 引言

在现代数据处理场景中,用户通常希望通过自然语言与数据库交互,而无需编写复杂的SQL语句。这种需求推动了大模型在自然语言处理(NLP)和数据库查询生成领域的应用。本文将详细介绍如何使用大模型实现自然语言查询关系型数据库SQL的功能,包括技术原理、架构设计、代码实现以及参数配置。


2. 技术原理

大模型通过理解用户输入的自然语言问题,并将其转换为对应的SQL查询语句,从而实现对关系型数据库的查询操作。以下是该功能的核心原理:

  1. 自然语言理解:大模型首先需要解析用户输入的自然语言问题,提取其中的关键信息(如实体、关系、条件等)。
  2. SQL生成:基于解析后的语义信息,大模型生成符合数据库模式的SQL查询语句。
  3. 执行与返回结果:生成的SQL语句被发送到数据库执行,并将查询结果返回给用户。

3. 架构设计

以下是大模型实现自然语言查询关系型数据库SQL的典型架构:

  1. 前端接口层
    • 提供RESTful API接口,接收用户输入的自然语言问题。
    • 示例代码如下:
java 复制代码
package com.alibaba.example.sql.controller;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

import com.alibaba.example.sql.SQLGenerationException;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SQLController {

	@Value("classpath:/schema.sql")
	private Resource ddlResource;

	@Value("classpath:/sql-prompt-template.st")
	private Resource sqlPromptTemplateResource;

	private final ChatClient chatClient;
	private final JdbcTemplate jdbcTemplate;

	public SQLController(
			ChatClient.Builder aiClientBuilder,
			JdbcTemplate jdbcTemplate
	) {

		this.chatClient = aiClientBuilder.build();
		this.jdbcTemplate = jdbcTemplate;
	}

	@PostMapping(path = "/sql")
	public Answer sql(@RequestBody SqlRequest sqlRequest) throws IOException {

		String schema = ddlResource.getContentAsString(Charset.defaultCharset());
		String sqlPromptTemplate = sqlPromptTemplateResource.getContentAsString(Charset.defaultCharset());

		String query = chatClient.prompt()
				.user(userSpec -> userSpec
						.text(sqlPromptTemplate)
						.param("question", sqlRequest.question())
						.param("ddl", schema)
				)
				.call()
				.content();

		assert query != null;
		if (query.toLowerCase().startsWith("select")) {

			return new Answer(
					query,
					jdbcTemplate.queryForList(query)
			);
		}

		throw new SQLGenerationException(query);
	}

	public record SqlRequest(String question) { }

	public record Answer(String sqlQuery, List<Map<String, Object>> results) { }

}
  1. 大模型服务层
    • 使用预训练的大模型(如DashScope)生成SQL查询。
    • 配置文件中需指定大模型的API密钥:
yaml 复制代码
 spring:
   ai:
     dashscope:
       api-key: ${AI_DASHSCOPE_API_KEY:sk-7074dss9idjddkkdbf31ssss}
  1. 数据库层
    • 配置数据库连接信息,支持执行生成的SQL查询。
    • 示例配置如下:
yaml 复制代码
 spring:
   datasource:
     url: jdbc:mysql://IP:3306/DB?useSSL=false&serverTimezone=UTC
     username: test
     password: h4tewdwerwefgvfebU
     driver-class-name: com.mysql.cj.jdbc.Driver

4. 参数配置与分析

以下是关键参数的配置规则及使用方法:

  1. sql-prompt-template.st

    • 定义了SQL生成的模板,包含问题和数据库模式的占位符。

    • 示例模板:

      复制代码
      Given the DDL in the DDL section, write an SQL query to answer the question in the QUESTION section.
      Only produce select queries. If the question would result in an insert, update,
      or delete, or if the query would alter the DDL in any way, say that the operation
      isn't supported. If the question can't be answered, say that the DDL doesn't support
      answering that question.
      
      Answer with the raw SQL query only; no markdown or other punctuation that isn't part of the query itself.
      
      QUESTION
      {question}
      
      DDL
      {ddl}
  2. schema.sql

    • 定义了数据库的表结构,供大模型参考生成SQL。
    • 示例表结构:
sql 复制代码
 create table Authors (
                         id int not null auto_increment,
                         firstName varchar(255) not null,
                         lastName varchar(255) not null,
                         primary key (id)
);

create table Publishers (
                            id int not null auto_increment,
                            name varchar(255) not null,
                            primary key (id)
);

create table Books (
                       id int not null auto_increment,
                       isbn varchar(255) not null,
                       title varchar(255) not null,
                       author_ref int not null,
                       publisher_ref int not null,
                       description varchar(255) DEFAULT NULL,
                       primary key (id)
);
  1. data.sql
    • 初始化数据库中的测试数据。
    • 示例数据:
sql 复制代码
insert into Authors (firstName, lastName) values ('Craig', 'Walls');
insert into Authors (firstName, lastName) values ('Josh', 'Long');
insert into Authors (firstName, lastName) values ('Ken', 'Kousen');
insert into Authors (firstName, lastName) values ('Venkat', 'Subramaniam');

insert into Publishers (name) values ('Manning Publications');
insert into Publishers (name) values ('OReilly Media');
insert into Publishers (name) values ('Pragmatic Bookshelf');

insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781617292545', 'Spring Boot in Action', 1, 1);
insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781617297571', 'Spring in Action', 1, 1);
insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781680507256', 'Build Talking Apps for Alexa', 1, 3);
insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781934356401', 'Modular Java', 1, 3);

insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781449374648', 'Cloud Native Java', 2, 2);

insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781680508222', 'Help Your Boss Help You', 3, 3);
insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781492046677', 'Kotlin Cookbook', 3, 2);

insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781680509816', 'Cruising Along with Java', 4, 3);
insert into Books (isbn, title, author_ref, publisher_ref)
values ('9781680506358', 'Programming Kotlin', 4, 3);
  

5. 测试验证

为了验证系统的正确性,可以设计以下测试用例:

  1. 测试用例1

    • 输入问题:"Find all books written by Craig Walls."
    • 预期SQL:SELECT * FROM Books WHERE author_ref = (SELECT id FROM Authors WHERE firstName = 'Craig' AND lastName = 'Walls');
    • 预期结果:返回所有由Craig Walls撰写的书籍。
  2. 测试用例2

    • 输入问题:"Insert a new author into the Authors table."
    • 预期响应:"Operation not supported."
  3. 测试用例3

    • 输入问题:"What is the total number of books published by each publisher?"
    • 预期SQL:SELECT p.name, COUNT(*) AS book_count FROM Books b JOIN Publishers p ON b.publisher_ref = p.id GROUP BY p.name;
    • 预期结果:返回每个出版社出版的书籍总数。
相关推荐
sheji52612 分钟前
JSP基于信息安全的读书网站79f9s--程序+源码+数据库+调试部署+开发环境
java·开发语言·数据库·算法
毕设源码-邱学长3 分钟前
【开题答辩全过程】以 基于Java Web的电子商务网站的用户行为分析与个性化推荐系统为例,包含答辩的问题和答案
java·开发语言
小咖自动剪辑5 分钟前
Base64与图片互转工具增强版:一键编码/解码,支持多格式
人工智能·pdf·word·媒体
独自归家的兔7 分钟前
从 “局部凑活“ 到 “全局最优“:AI 规划能力的技术突破与产业落地实践
大数据·人工智能
一个处女座的程序猿7 分钟前
AI:解读Sam Altman与多位 AI 构建者对话—构建可落地的 AI—剖析 OpenAI Town Hall 与给创业者、产品/工程/安全团队的实用指南
人工智能
依依yyy7 分钟前
沪深300指数收益率波动性分析与预测——基于ARMA-GARCH模型
人工智能·算法·机器学习
海域云-罗鹏18 分钟前
国内公司与英国总部数据中心/ERP系统互连,SD-WAN专线实操指南
大数据·数据库·人工智能
摇滚侠18 分钟前
Java项目教程《尚庭公寓》java项目从开发到部署,技术储备,MybatisPlus、MybatisX
java·开发语言
冬奇Lab20 分钟前
深入理解 Claude Code:架构、上下文与工具系统
人工智能·ai编程
Up九五小庞27 分钟前
本地部署 + Docker 容器化实战:中医舌诊 AI 项目 TongueDiagnosis 部署全记录-九五小庞
人工智能