跳转至

Dify 数据分析工作流搭建

本节目标

1、理解数据分析工作流的整体架构

2、掌握数据库结构自动获取方法

3、掌握基于大模型的 SQL 自动生成能力

一 完整流程图

数据分析工作流流程图如下所示:

1、获取数据库描述

img

2、SQL语句生成并查询回复

img

二 获取数据库信息模块工作流

1、数据库查询节点

(1)设置数据库查询节点

img

(2)设置数据库查询节点

img

(3)配置节点属性

img

数据库类型:MySQL

数据库地址:dify安装在docker中,我们填写:host.docker.internal 获取宿主机的地址。

也可以直接填写宿主机的ip地址:192.168.xx.xx

端口:3306

用户名:数据库的用户名

密码:数据库的密码

库名:数据库名称,这里填写:sales_analysis_db

(4)设置SQL语句

img

SQL查询语句:

SELECT
    TABLE_NAME,
    TABLE_COMMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'sales_analysis_db';

输出格式:有两个可选,markdown格式或者json格式。

因为我们要获取数据库名称,这里选择json格式。

(5)试运行观察结果

试运行发现得到结果如下:

{
  "text": "",
  "files": [],
  "json": [
    {
      "records": [
        {
          "TABLE_COMMENT": "订单明细表,存储每个订单中的商品信息",
          "TABLE_NAME": "order_item"
        },
        {
          "TABLE_COMMENT": "订单表,存储每一笔订单",
          "TABLE_NAME": "orders"
        },
        {
          "TABLE_COMMENT": "商品表,存储商品信息",
          "TABLE_NAME": "product"
        },
        {
          "TABLE_COMMENT": "用户表,存储用户基础信息",
          "TABLE_NAME": "user"
        }
      ]
    }
  ]
}

2、代码节点-获取表名字

(1)设置代码执行节点

img

img

(2)配置代码执行节点参数:

img

输入变量:上一步查询所有数据表的输出变量

python代码:可以通过以下代码获取表名以及表名对应的说明

def main(json):
    json = json[0]
    records = json.get("records", [])
    table_name_list = []
    table_name_comment_dict = {}
    for record in records:
        table_name = record.get("TABLE_NAME", "")
        table_comment = record.get("TABLE_COMMENT", "")
        table_name_list.append(table_name)
        table_name_comment_dict[table_name] = table_comment
    return {
        "table_name_list": table_name_list,
        "table_name_comment_dict": table_name_comment_dict,
    }

3、迭代节点-循环判断

(1)设置迭代节点

如图所示设置迭代节点

img

输入的为一个列表,就是上一步输出的list

(2)数据库查询节点-查询表结构

我们有了表结构,我们才可以根据表结构生成SQL语句。

继续设置数据库查询节点,配置和之前一样。

img

SQL查询语句:

SELECT
    COLUMN_NAME,
    COLUMN_TYPE,
    COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_NAME = ''
  AND TABLE_SCHEMA = 'sales_analysis_db';

(3)数据库查询节点-查询表例子

我们给大模型一些示例数据,大模型才可以根据示例数据生成更精确的SQL语句。

img

(4)代码节点-生成表描述

img

输入变量:

1、item:表名。

2、column_text:SQL查询表结构的结果。

3、example_text:SQL查询表例子的结果。

4、table_name_comment_dict:获取表名对应说明的dict。

代码配置如下:

def main(item:str, column_text: str, example_text: str, table_name_comment_dict):
    comment = table_name_comment_dict.get(item, "")
    result_text = f"""
    数据表名:{item}
    数据表描述:{comment}
    数据表字段及描述:
    {column_text}
    数据表例子(示例数据):
    {example_text}
    """
    return {
        "result": result_text
    }

输出变量:result

4、代码节点-整合多个表描述

(1)配置节点

img

输入变量:table_str_list

代码如下:

def main(table_str_list):
    result_str = ""
    result_str += "所有的表结构及描述如下:\n"
    for item in table_str_list:
        result_str += item
        result_str += "\n\n"
    return {
        "result": result_str
    }

输出变量:result

(2)试运行观察结果

img

三 SQL语句生成并回复

img

1、输出SQL语句

img

img

系统提示词:

你是一个专业的SQL生成助手,请根据用户的自然语言问题,生成【MySQL查询SQL语句】。

====================
【数据库结构信息】
====================

{{#1775219864143.result#}}

====================
【任务要求】
====================

1. 你只能生成【SELECT查询语句】,严禁生成:
- INSERT
- UPDATE
- DELETE
- DROP
- ALTER
- SHOW
- DESC

2. 字段使用规则:
- 只能使用已提供表中的字段
- 所有字段必须带表别名
- 多表查询必须优先使用 JOIN
- 禁止臆造不存在的字段和表

3. 查询规范:
- 默认加 LIMIT 10,除非用户明确要求全部数据
- 涉及“最多 / 最少 / TOP / 排名”时,必须使用 GROUP BY + ORDER BY + LIMIT
- 涉及金额统计时,优先使用 SUM / AVG / MAX / MIN
- 涉及时间时,优先使用 order_time 或 register_time
- 排序默认优先使用 DESC

4. 输出必须严格遵循 JSON 格式:
- 只能输出一个合法 JSON 对象
- 不要输出解释
- 不要输出 markdown
- 不要输出多余文字
- 不要使用 ```json 或 ```sql 包裹

====================
【输出JSON格式】
====================

{
"sql": "生成的SQL语句",
"question": "用户原始问题",
"tables": ["本次SQL涉及的表名1", "本次SQL涉及的表名2"],
"summary": "一句话说明这条SQL的查询意图"
}

====================
【输出要求补充】
====================

1. sql 字段中只放 SQL 语句本身
2. question 字段中保留用户原始问题
3. tables 字段中列出实际使用到的表名
4. summary 字段用一句简洁中文说明SQL用途
5. 输出内容必须是标准 JSON,可被程序直接解析
6. 若用户问题无法映射到当前表结构,也必须输出标准 JSON,格式如下:

{
"sql": "",
"question": "用户原始问题",
"tables": [],
"summary": "无法根据当前表结构生成SQL"
}

====================
【示例】
====================

用户问题:
每个城市有多少用户?

输出:
{
"sql": "SELECT u.city AS city, COUNT(*) AS user_count FROM user u GROUP BY u.city ORDER BY user_count DESC LIMIT 10;",
"question": "每个城市有多少用户?",
"tables": ["user"],
"summary": "统计每个城市的用户数量并按数量倒序排序"
}

用户提示词:

用户问题:{{#sys.query#}}

记忆:

可以配置记忆,使其涵盖记忆效果。

img

2、Json解析对象

(1)安装工具

安装json解析工具,如下图所示

img

(2)对生成的SQL进行JSON解析

img

解析对象:sql

我们从而获取到sql。

3、查询数据库

设置查询数据库模块。

img

img

SQL查询语句:这里SQL查询语句为上一步JSON解析的。

输出格式:这里设置为markdown

4、大模型LLM-根据查询结果回答

img

img

系统提示词:

你是一个专业的数据分析助手,你的任务是根据【数据库查询结果】回答用户的问题。

====================
【任务要求】
====================

1. 回答必须基于数据库查询结果,严禁编造数据
2. 如果查询结果为空,请回答:
   “未查询到相关数据”
3. 回答要:
   - 简洁清晰
   - 贴近用户问题
   - 用自然语言表达,不要SQL术语
4. 如果结果是统计类数据(如COUNT / SUM / 排名):
   - 必须给出明确结论
   - 可适当总结趋势(如“最多的是…”)
5. 如果结果是列表数据:
   - 进行适当整理(如Top N、分类描述)
   - 不要逐行机械复述
6. 禁止输出:
   - SQL语句
7. 如果问题涉及排序(如“最多/最少”):
   - 明确指出第一名或关键结论

====================
【输出风格】
====================

- 用一句话或几句话回答
- 优先给结论,再补充说明
- 语言自然,像一个数据分析师

====================
【示例】
====================

示例输入:
用户问题:哪个城市用户最多?
查询结果:
[{"city": "北京", "user_count": 120},
 {"city": "上海", "user_count": 98}]

示例输出:
根据查询结果,北京的用户最多,共120人,其次是上海,有98人。

用户提示词:

数据库查询结果:
{{#17752206371160.text#}}
用户问题为:
{{#sys.query#}}

5、直接回复节点-根据数据分析结果回复

根据查询的数据分析结果进行回复。

img

四 预览并测试

进行预览并测试,效果如下

img

五 本节总结

本节完成了一个完整的数据分析工作流:

1、自动获取数据库结构(表 + 字段 + 示例数据)

2、大模型根据问题生成 SQL

3、执行查询并输出分析结果

实现效果:用户用自然语言提问 → 自动查数据库 → 返回分析结论