智能体+MCP+NL2SQL构建一个智能数据分析应用(一)

通过Dify智能体,结合MCP工具能力,可以很轻松的构建基于数据库的查询问答,对用户输出的问题,通过Dify的Agent节点,自动调用合适的工具来获取数据并回答问题。下面以一个具体的数据例子来介绍如何完成。

创建示例数据库

首先准备一些示例数据,这里以一个数字音乐商店的数据为例,可以在Github仓库GitHub - lerocha/chinook-database: Sample database for SQL Server, Oracle, MySQL, PostgreSQL, SQLite, DB2上下载相应的数据库创建脚本,创建数据库。这个数据库有以下的数据表,其结构如下图。

以Postgresql数据库为例,首先通过docker启动postgres服务。

bash 复制代码
docker run -d \
  --name postgres \
  -e POSTGRES_PASSWORD=abc123 \
  -p 5432:5432 \
  -v /home/abc/docker/volumes/postgres:/var/lib/postgresql \
  postgres:latest

将Github仓库下载的sql脚本通过docker cp拷贝到容器中,然后连接到数据库。

bash 复制代码
docker exec -it postgres psql -U postgres

运行sql脚本创建数据库

bash 复制代码
\i /Chinook_PostgreSql.sql

创建完成后,可以通过命令\dt查看导入的数据表, \d tablename查看具体某个表的结构。

通过以下命令导出所有的表结构数据。

bash 复制代码
docker exec -it postgres pg_dump -U postgres -d chinook -s -f /datatables.sql

然后将其保存到宿主机

bash 复制代码
docker cp postgres:/datatables.sql ./

保存好的sql文件后续可以在智能体工作流中传入给大模型,帮助大模型理解数据库的结构,从而按照用户的提问生成相应的SQL查询语句。

除了用sql格式来描述数据库结构,也可以采用M-Schema规范来描述数据库结构,这是一种用于自然语言转SQL(NL2SQL)​ 任务的、半结构化的数据库模式表示规范。它由阿里巴巴的团队提出,是其 XiYan-SQL 框架的核心组成部分,旨在解决大模型在理解复杂、专业的数据库结构时面临的挑战,具体介绍可以参见https://github.com/XGenerationLab/XiYan-DBDescGen.git

通过以下代码自动生成M-Schema文件。

python 复制代码
import os
from sqlalchemy import create_engine

database_url = 'postgresql://postgres:abc123@localhost:5532/chinook'
engine = create_engine(database_url)

from schema_engine import SchemaEngine

db_name = 'chinook'
schema_engine = SchemaEngine(engine=engine, db_name=db_name)
mschema = schema_engine.mschema
mschema_str = mschema.to_mschema()
print(mschema_str)
mschema.save(f'./{db_name}.json')

创建MCP服务

数据库创建完成后,需要对外提供一个MCP服务,使得大模型可以调用该服务进行数据库的查询。这里采用fastmcp这个库来构建MCP服务,如以下代码。

python 复制代码
from fastmcp import FastMCP
from sqlalchemy import create_engine, text

database_url = 'postgresql://postgres:roy2000@localhost:5532/chinook'

app = FastMCP("Database Query Server") 

def execute_safe_query(sql):
    """执行SQL并返回结果,包含基础安全校验"""
    # 1. 安全检查:禁止执行非SELECT语句或包含危险关键词的操作
    #sql_upper = sql.replace("\n", "").strip().upper()
    sql_upper = sql.strip().upper()
    if not sql_upper.startswith('SELECT'):
        raise ValueError("Only SELECT queries are allowed for safety.")
    if any(keyword in sql_upper for keyword in ['DROP', 'DELETE', 'INSERT', 'UPDATE', ';--']):
        raise ValueError("Potentially dangerous operation detected and blocked.")

    # 2. 连接数据库并执行查询
    with engine.connect() as connection:
        try:
            result = connection.execute(text(sql))
            data = result.mappings().all()
            serializable_result = [dict(row) for row in data]
            return {"status": "success", "data": serializable_result}
        except Exception as e:
            return {"status": "error", "message": str(e)}

# 使用装饰器将函数注册为MCP工具
@app.tool()
def query_database(sql_query: str) -> dict:
    """
    根据提供的SQL查询语句,从数据库中检索信息。
    参数:
        sql_query (str): 要执行的SELECT查询语句。
    """
    print(f"Sql execute code: {sql_query}")
    return execute_safe_query(sql_query)

if __name__ == "__main__":
    engine = create_engine(database_url)
    # 以标准输入输出(stdio)模式运行服务器,这是最常见的与客户端通信的方式
    app.run(transport="sse", host="127.0.0.1", port=8000)

运行该Python脚本,即可启动一个MCP服务,提供数据库查询服务。

创建智能体

在Dify中,单击"工具"菜单,然后选择"MCP",最后单击"添加一个MCP服务",在设置中填入MCP服务的URL,之前启动的MCP服务的URL是http://127.0.0.1:8000/sse,因为我的Dify是在容器中运行的,所以这里的URL设置为http://host.docker.internal:8000/sse,设置后如下图。

现在可以创建Dify智能体了,在新建一个Chatflow工作流,并按如下方式编排节点。

这里面的文档提取器节点用于对上传的数据库sql格式的文件进行解析,以获取文档的内容。Agent节点在工具列表中添加之前配置的MCP服务,并设置指令,如下图。

设置完成后,单击预览,进行测试。

在对话窗口中上传之前创建的数据库格式的sql文件,然后询问"当前有多少首歌曲",Agent节点将基于数据库的格式,自动生成对应的SQL查询语句,然后进行回复。从MCP服务打印出的SQL语句"SELECT COUNT(*) FROM track;"来看,Agent节点的大模型正确的把用户的问题转换为数据库的查询语句,运行结果如下图所示。

现在问一个稍微复杂一点的问题,"按歌曲的风格来统计歌曲数量并进行排序,列出排名前十位的歌曲风格及其歌曲数量", MCP服务打印出的SQL语句是SELECT genre.name, COUNT(track.track_id) as count FROM track JOIN genre ON track.genre_id = genre.genre_id GROUP BY genre.genre_id ORDER BY count DESC LIMIT 10;", 运行结果如下。

可见工作流可以准确的把用户的问题翻译为SQL语句,并在查询后给出结果。后续将进行功能的进一步丰富和优化。

相关推荐
智能相对论6 分钟前
CES深度观察丨智能清洁的四大关键词:变形、出户、体验以及生态协同
大数据·人工智能
齐齐大魔王10 分钟前
Pascal VOC 数据集
人工智能·深度学习·数据集·voc
程途拾光15819 分钟前
幻觉抑制:检索增强生成(RAG)的优化方向
人工智能
野豹商业评论21 分钟前
千问发力:“AI家教”开始抢教培生意?
人工智能
程序员佳佳33 分钟前
【万字硬核】从零构建企业级AI中台:基于Vector Engine整合GPT-5.2、Sora2与Veo3的落地实践指南
人工智能·gpt·chatgpt·ai作画·aigc·api·ai编程
weixin_4379881235 分钟前
范式推出面向AGI的Phanthy平台
人工智能·agi
Hcoco_me1 小时前
RNN(循环神经网络)
人工智能·rnn·深度学习
踏浪无痕1 小时前
AI 时代架构师如何有效成长?
人工智能·后端·架构
AI 智能服务1 小时前
第6课__本地工具调用(文件操作)
服务器·人工智能·windows·php
clorisqqq1 小时前
人工智能现代方法笔记 第1章 绪论(1/2)
人工智能·笔记