该数据可视化方案基于 AI Text2SQL 技术,实现自然语言到 SQL 查询的智能转换,使用户无需编写 SQL 语句即可获取和分析数据。用户只需输入查询需求,AI 便能自动解析意图,生成 SQL 并执行查询,最终通过图表、仪表盘等多种可视化方式直观呈现数据。方案支持自适应图表推荐,极大降低数据分析门槛,提高决策效率,适用于业务分析、数据监控等场景。
视频演示:www.bilibili.com/video/BV1bU...
功能演示:xryder.cn 智能监控
该方案使用的是技术栈是:Java 21 + Spring AI + 智普AI 的在线API。
实现思路
-
首先需要根据输入的问题,判断是否是数据分析类问题,这里将问题输入大模型,让大模型判断是否是数据分析类问题,返回1或者0,通过提示词和示例来让大模型返回1或者0。
-
如果是数据分析类问题,再将问题和提供的数据库表 元数据信息(表名,表的描述,字段名,字段类型和字段描述) 作为prompt提供给大模型,期间要求大模型只输出SQL。如果大模型返回内容包含md的SQL代码格式,则需要先处理一下:
java
// 清理 SQL 的方法
private String cleanSql(String sql) {
return sql.replaceAll("```", "").replace("sql", "").trim();
}
- 通过SQL获取查询语句返回的字段:
java
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
@PersistenceContext
private EntityManager entityManager;
...
public List<String> getReturnFields(String sql) {
// 初始化返回字段列表
List<String> fieldNames = new ArrayList<>();
// 使用 Hibernate Session 获取 Connection
Session session = entityManager.unwrap(Session.class);
session.doWork(connection -> {
try (PreparedStatement statement = connection.prepareStatement(sql)) {
ResultSetMetaData metaData = statement.getMetaData();
if (metaData != null) {
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
fieldNames.add(metaData.getColumnName(i));
}
}
}
});
return fieldNames;
}
- 执行查询语句,封装返回的结果、SQL语句和字段信息。如果执行SQL失败,需要增加SQL重试机制,将错误信息和SQL语句提供给大模型,重新生成SQL,再执行。
- 根据返回结果让大模型判断选择使用哪种图表进行展示。
- 根据查询结果让大模型做个总结summary。
- 封装最终结果返回给前端
- 前端根据提供的数据和图表进行可视化渲染。
整个过程期间需要调用多次大模型,其中有些步骤需要对大模型返回的数据做结构化生成。比如第一个问题分类,需要大模型只返回0或者1。
代码示例
结构化输出(问题分类):
java
record QuestionType(Integer type, String description) {
}
//问题分类
public Integer getQuestionType(String question) {
String template = """
请将问题按以下类别进行分类。
1: 数据分析类问题
2: 其他类型问题
问题如下:
{question}
以下是具体交互示例:
- **问答示例**:
用户:统计最近14天每天的阅读量是多少?
你的回答:1
用户:最受欢迎的文档是什么?
你的回答:1
用户:你是谁?
你的回答:2
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Prompt prompt = promptTemplate.create(Map.of("question", question));
return Objects.requireNonNull(normalChatClient.prompt()
.system("你非常擅长对用户问题进行分类,可以将问题打上类别标签")
.user(prompt.getContents())
.call()
.entity(QuestionType.class)).type;
}
这是一个让大模型推荐图表的功能:
java
public String getChartType(String question, String data) {
String template = """
请根据问题和数据推荐一个合适的用于展示该数据的图表, 只需要给出图表类型的英文名称。
问题如下:
{question}
数据如下:
{data}
可选择的图表类型如下:
Area, Line, Bar, Radar
以下是一个具体示例:
问题:统计最近30天每天的网站访问量
你的回答:Line
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Prompt prompt = promptTemplate.create(Map.of("question", question, "data", data));
return normalChatClient.prompt()
.user(prompt.getContents())
.call().content();
}
其中关键部分是提供数据库表元数据信息给到大模型,这样大模型才可能正确生成SQL。
后记
经常看到很多人用大模型做数据分析,将一个excel表格直接扔给大模型,让大模型去做统计。如果excel数据量少还可以,数据量多了之后,效果就不行了。这个中间其实需要增加一步,生成python代码或者SQL语句的方式将问题转化为可执行的脚本,运行脚本之后,让大模型根据执行结果来回答问题,这样效果更好。再结合函数调用,可以拓展更多的使用场景。
关于大模型做数据分析和其他可用场景,欢迎大家一起交流讨论!