之前有小伙伴留言询问:Dify不支持直接连接数据库,那该如何通过自然语言让大模型输出准确的查询结果?收到这个问题后,一个清晰的解决方案逐渐成型。下面就把完整的实现流程拆解开来,分享给有同样需求的朋友。
整体思路如下:
第一步:用DeepSeek准备数据库表结构与测试数据
首先借助DeepSeek快速生成建表语句和示例数据,为后续自然语言转SQL做好基础准备。
具体的建表语句和测试数据如下:
# 创建班级表
CREATE TABLE classes (
class_id INT AUTO_INCREMENT PRIMARY KEY,
class_name VARCHAR(50) NOT NULL
);
# 创建用户表
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
class_id INT,
FOREIGN KEY (class_id) REFERENCES classes(class_id)
);
# 插入班级数据
INSERT INTO classes (class_name) VALUES
('Class A'),
('Class B'),
('Class C'),
('Class D');
# 插入用户数据
INSERT INTO users (username, email, class_id) VALUES
('Alice', 'alice@example.com', 1),
('Bob', 'bob@example.com', 2),
('Charlie', 'charlie@example.com', 3),
('Da vid', 'da vid@example.com', 4),
('Eve', 'eve@example.com', 1),
('Frank', 'frank@example.com', 2),
('Grace', 'grace@example.com', 3),
('Hank', 'hank@example.com', 4),
('Ivy', 'ivy@example.com', 1),
('Jack', 'jack@example.com', 2);
第二步:用DeepSeek生成查询接口(Python服务)
接下来让DeepSeek编写一个轻量的Python查询服务,对外暴露RESTful接口,以便Dify工作流调用。
整理后的Python代码:
from flask import Flask, request, jsonify
import pymysql
import re
# 创建 Flask 应用
app = Flask(__name__)
# 数据库连接配置
DB_CONFIG = {
'host': 'localhost',
'user': 'test', # 替换为你的数据库用户名
'password': '123456', # 替换为你的数据库密码
'database': 'test', # 替换为你的数据库名称
'cursorclass': pymysql.cursors.DictCursor
}
# 定义接口:执行 SQL 查询
@app.route('/query', methods=['POST'])
def execute_query():
# 获取客户端传递的 SQL 语句
data = request.json
if not data or 'sql' not in data:
return jsonify({'error': 'Missing SQL statement in request body'}), 400
sql = data['sql']
# 简单的 SQL 语句验证(防止恶意操作)
if not re.match(r'^SELECTs', sql, re.IGNORECASE):
return jsonify({'error': 'Only SELECT queries are allowed'}), 400
try:
# 连接数据库
connection = pymysql.connect(**DB_CONFIG)
with connection.cursor() as cursor:
# 执行 SQL 查询
cursor.execute(sql)
result = cursor.fetchall()
return jsonify(result)
except pymysql.MySQLError as e:
return jsonify({'error': str(e)}), 500
finally:
if connection:
connection.close()
# 启动服务
if __name__ == '__main__':
app.run(debug=True)
直接在编辑器中运行,或通过命令行执行:
python server.py
第三步:在Dify中配置工作流
创建知识库
新建一个独立的知识库,将建表语句作为知识文档存入。可以使用txt或markdown格式,演示中直接放入建表语句即可。建议添加适当注释,便于后续大模型理解表结构并生成精准的SQL。
创建工作流
创建一个空白工作流,作为自然语言转SQL的核心流程。
在【开始】节点添加输入字段,命名为content,用于接收用户的自然语言查询。
接着添加【知识检索】节点,用于从知识库中获取与用户查询相关的表结构信息。
再添加【LLM】节点,将知识检索结果作为上下文,并结合用户输入来生成SQL。
将【知识检索】节点的输出设置为上下文,并在系统提示词中引用【开始】节点的content字段,让大模型理解用户意图。
提示词配置如下:
你是一个数据分析师,根据用户输入的{content}需求以及检索到{上下文},生成对应的查询SQL,SQL必须经过严格的校验。
## 你可以使用的其他方法
用户输入类似于“求和”或“总和”时,则在sql语句中使用SUM()。
用户输入类似于“平均数”或“平均”时,在在sql语句中使用A VG()。
## 要求
1.如果用户输入的内容无法生成为sql语句,请直接说“抱歉,该命令无法形成数据库查询操作”。
2.当可以生成sql语句时,请确保输出的内容为完整正确的sql语句,不要输出此外的其他任何字符,确保你生成的内容用户可以直接执行查询操作。
3.对于字符串内容的查询请使用LIKE操作而不是等于操作。
4.请不要在回复中包括除sql语句之外的任何内容。
5.禁止中间过程输出。
6.输出的sql为一整行。
添加HTTP请求节点
在【LLM】节点后添加【HTTP请求】节点,配置API地址和请求参数。参数名称"sql"需与前面Python接口中接收的字段名保持一致,这样才能正确将生成的SQL发送到查询服务。
注意:如果Dify是通过Docker部署的,并且Python查询服务运行在本地,接口地址不能写127.0.0.1,而应改为host.docker.internal,确保容器能访问宿主机服务。
添加结束节点
在【HTTP请求】节点之后,添加【结束】节点,输出内容直接取HTTP请求的返回结果(JSON格式)。当然,也可以将JSON数据进一步处理成表格或更友好的展示形式,这里不再展开。感兴趣的朋友完全可以在当前基础上继续优化,实现更丰富的交互体验。
感谢小伙伴们的提问。以上只是其中一种实现思路——另一种方案是直接用Python代码连接Dify SDK,结合知识库解析自然语言并推导出SQL,然后由Python脚本执行查询。两种方案的底层逻辑大同小异,都能达到同样的效果,你可以根据实际技术栈选择合适的方式。
当然,这里提供的只是一个简单的demo,核心目的是跑通整个自然语言转SQL的链路。如果要在生产环境中使用,还需要补充大量的边界限制,例如对生成的SQL进行二次校验、增加条件分支处理、权限控制等,以确保准确性和安全性。不过作为起点,这套方案已经足够清晰,可以快速验证想法。
