从数据库到 Echarts,打造高效数据可视化的全新工作流。
核心内容:
1. 数据源转换:从 Excel 迁移至数据库
2. 自然语言查询数据库与 SQL 语句自动生成
3. 数据处理及 Echarts 可视化图表呈现
上一篇文章介绍了如何读取 Excel 数据并通过 Echarts 实现数据可视化。其实,既然能从 Excel 中提取数据,就能同样从数据库里读取数据——两者的差异仅在于数据源不同。一旦成功查询出数据,后续的处理流程就完全一致了。下面直接进入具体操作步骤。
整体思路是:先实现自然语言查询数据库(之前文章已有详细说明),再通过 HTTP 节点向数据库发起请求,接着将返回的数据处理成 Echarts 所需的格式并传递到图表中。从数据库获取数据后,后面的操作与 Excel 版本完全一致。
先看整体效果:
工作流如下:
1. 开始节点:提供一个输入框,让用户告诉 AI 想要统计展示什么样的数据。
2. 知识检索:需提供数据库表的 DDL,这样 AI 才能理解数据字段含义,进而根据自然语言描述自动生成查询数据的 SQL 语句。
这里创建一个销售表,DDL 如下(并插入几条示例数据):
CREATE TABLE sales ( id INT AUTO_INCREMENT PRIMARY KEY, product_name VARCHAR(50) NOT NULL, sales_quantity INT NOT NULL, sales_amount DECIMAL(10, 2) NOT NULL );
将这段 DDL 保存为 TXT 文件,并基于该文件创建一个知识库即可。
3. LLM 节点:负责将自然语言转换为 SQL 语句。建议多测试不同模型以对比效果,此处选用 qwen-coder-turbo-latest,提示词如下:
你是一个数据分析师,擅长使用SQL查询数据库,根据用户数据库的表结构{{#context#}}和用户的查询要求给出对应的sql语句。用户的查询要求是:{{#1741600668823.content#}}。注意生成的SQL必须经过严格的校验。你可以使用函数在用户输入类似于“求和”或“总和”时,则在sql语句中使用SUM()。用户输入类似于“平均数”或“平均”时,在在sql语句中使用A VG()。要求1.如果用户输入的内容无法生成为sql语句,请直接说“抱歉,该命令无法形成数据库查询操作”。2.当可以生成sql语句时,请确保输出的内容为完整正确的sql语句,除此以外不要输出其他任何信息,不要注释和说明,也不要格式化,不要用markdown格式来输出,直接输出纯文本,也不要输出 n 这样的回车换行符,确保你生成的sql语句可以直接执行查询操作。3.对于字符串内容的查询请使用LIKE操作而不是等于操作。4.禁止中间过程输出。
4. 参数提取器:从上个节点的输出中提取出可直接执行的合法 SQL 语句。有时 LLM 返回的数据会被包装成 markdown 格式,需根据实际情况调整。由于 qwen-coder-turbo-latest 生成 SQL 时总是以 markdown 格式返回,因此增加一个参数提取器。指令很简单:“从输入变量中准确提取出一个可执行的 sql 语句”。
5. HTTP 请求节点:将 SQL 语句发送至后台,让后台执行查询并返回数据。参数需与后台接口保持一致,包括 URL、请求方法、body 返回格式等。后台代码可自行编写,此处用 Flask 创建了一个简单的查询接口:
@app.route('/query', methods=['POST'])
def query():
connection = None
try:
data = request.get_json()
sql = data.get('sql')
if not sql:
return jsonify({'error': 'SQL query is required'}), 400
if not sql.strip().lower().startswith('select'):
return jsonify({'error': 'Only SELECT queries are allowed'}), 400
connection = get_db_connection()
with connection.cursor() as cursor:
cursor.execute(sql)
result = cursor.fetchall()
return jsonify(result)
except Exception as e:
return jsonify({'error': str(e)}), 500
finally:
if connection:
connection.close()
6. 解析数据库数据:从上个节点的输出中解析出需要的数据。HTTP 请求会返回很多额外信息(如状态码),这些并非我们所需。此处让 AI 把查询到的数据解析成一个 JSON 数组,每条记录对应数组中的一个元素。注意:提示词里写的 JSON 字段不需要与数据库表完全对应,因为实际表结构多样,无法预知具体字段。提示词如下:
##角色 你是一位数据库专家,根据{{#1747017252540.body#}}返回的数据,如果code参数等于200,则说明数据返回成功,根据data中的数据封装成json的格式输出。
###输出示例:
[
{
"SALE_PRICE": "200.0",
"MENDIAN_CODE": "1.0",
"GOODS_NAME": "无线充电器",
"XIAOSHOU_DATE": "2025-01-03",
"SALE_NUMBER": "3.0",
"PAY_WAY": "现金",
"ZK_MONEY": "540.0",
"GOODS_CODE": "1003.0"
},
{
"SALE_PRICE": "7000.0",
"MENDIAN_CODE": "3.0",
"GOODS_NAME": "笔记本电脑",
"XIAOSHOU_DATE": "2025-01-04",
"SALE_NUMBER": "1.0",
"PAY_WAY": "信用卡",
"ZK_MONEY": "6650.0",
"GOODS_CODE": "1004.0"
}
]
7. 提取 Echarts 格式数据:将上个节点输出中 Echarts 所需的数据提取出来,其余无关数据全部丢弃。
8. LLM 节点:将上个节点的输出转换为 Echarts 渲染图表所需的配置格式。提示词如下:
# 角色 你是一个数据整理专家且也是echart方面的专家,根据用户描述智能整理并筛选计算出符合用户的数据,echart图表类型,数据都根据用户描述智能生成,确保echarts的配置项为一个标准且可解析的JSON格式。
##数据 源数据: {{#context#}} 用户描述: {{#sys.query#}}
##输出格式示例:
```echarts
{
"option": {
"title": {
"text": "示例标题"
},
"series": [
{
"type": "line",
"data": [
5,
20,
36,
10,
10,
20
]
}
]
}
}
```
# 任务 输出结果仅保留echart相关结构
9. 参数提取器:从上个节点输出中提取出 Echarts 执行时需要的数据,过滤掉其他内容。多个参数提取器的作用类似,都是因为前一个节点的输出可能包含 markdown 格式的额外内容。
10. 代码执行:在该节点内编写代码,接收上个节点的数据并生成 Echarts 图表。代码如下:
import json
def main(csv_string) -> dict:
echarts_config = json.loads(csv_string)
option = echarts_config.get('option', {})
output = "n```echartsn"+ json.dumps(option,indent=2,ensure_ascii=False) + "n```"
return {"output": output}
11. 最后一个直接回复节点:输出上一个节点的内容,即最终的 Echarts 图表。
最后执行一下,看下实际效果:
