SQL Agent
本教程将指导您构建一个智能SQL代理,该代理能够与数据库交互,生成SQL查询,验证查询,执行查询,并在出现错误时自我纠正。
概述
SQL代理流实现了一个健壮的数据库交互系统,该系统:
检索数据库模式信息
根据用户问题生成SQL查询语句
验证生成的查询是否存在常见错误
对数据库执行查询
检查结果是否有误,并在必要时进行自我纠正
根据查询结果提供自然语言回复

步骤1:设置起始节点
首先,在画布上添加一个Start节点。这将成为SQL代理的入口点。

配置:
输入类型:选择“聊天输入”以接受用户问题
Flow State:添加一个键为“sqlQuery”且值为空的状态变量
Start节点使用一个空的sqlQuery变量来初始化流状态,该变量将在整个过程中存储生成的SQL查询。
步骤2:检索数据库模式
添加一个自定义函数节点,并将其连接到开始节点。

配置:
Javascript函数:这是一个示例函数,用于连接到您的数据库并检索完整的模式,包括表结构、列定义和示例数据。
const { DataSource } = require('typeorm');;
const HOST = 'localhost';;
const USER = 'testuser';;
const 密码 = 'testpwd';;
const DATABASE = 'testdatabase';;
const PORT = 5432;;
let sqlSchemaPrompt = '';;
const AppDataSource = new DataSource({
类型:'postgres',
主机:HOST,
端口:PORT,
用户名:USER,
密码:PASSWORD,
数据库:DATABASE,
同步:否,
日志记录:否,
});
异步函数 getSQLPrompt() {
尝试 {
等待 AppDataSource 初始化完成;
const queryRunner = AppDataSource.createQueryRunner();;
// 获取所有用户定义的表
const tablesResult = await queryRunner.query(`
选择表名
来自information_schema.tables
WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
`);
对于(tablesResult中的每个)表格行(tableRow) {
const tableName = tableRow.table_name;;
const schemaInfo = await queryRunner.query(`
选择列名、数据类型、是否可以为空
从information_schema.columns表中选择
在表名(table_name)等于'${tableName}'的情况下
`);
const createColumns = [];;
const columnNames = [];;
对于 schemaInfo 中的每个列(column)
const name = column.column_name;;
const type = column.data_type.toUpperCase();;
const notNull = column.is_nullable === 'NO' ? 'NOT NULL' : '';;
columnNames.push(name);;
`${name} ${type} ${notNull}` 添加到 createColumns 数组中;
}
常量sqlCreateTableQuery定义为`CREATE TABLE ${tableName} (${createColumns.join(', ')})`;
常量sqlSelectTableQuery定义为:`SELECT * FROM ${tableName} LIMIT 3`;
将所有值赋值为一个空数组;
尝试 {
const rows = await queryRunner.query(sqlSelectTableQuery);;
allValues = rows.map(row =>
`columnNames.map(col => row[col]).join(' ')`
);
} catch (err) {
allValues.push('[获取行时出错]');;
}
sqlSchemaPrompt +=
sqlCreateTableQuery + '\n' +
sqlSelectTableQuery + '\n' +
列名数组使用空格连接后换行符 + '\n' +
所有值用换行符连接,然后加上两个换行符;
}
等待 queryRunner 释放资源;
} catch (err) {
console.error(err);;
抛出错误;
}
}
等待获取SQL提示;
返回sqlSchemaPrompt;步骤 3:生成 SQL 查询
添加一个与“获取数据库模式”节点相连的LLM节点。

配置:
消息:添加一条系统消息:
你是一个旨在与SQL数据库交互的代理。给定一个输入问题,创建一个语法正确的sqlite查询来运行,然后查看查询结果并返回答案。除非用户指定了他们希望获得的特定数量的示例,否则请始终将查询结果限制在最多5个。你可以按相关列对结果进行排序,以返回数据库中最有趣的示例。切勿查询特定表中的所有列,而应根据问题只查询相关列。切勿对数据库执行任何数据操作语言(DML)语句(如INSERT、UPDATE、DELETE、DROP等)。
以下是相关的表格信息:
{{ customFunctionAgentflow_0 }}
注:
- 仅生成一个SQL查询JSON结构化输出:在此,我们指示模型仅返回结构化输出,以防止大型语言模型(LLM)包含除SQL查询外的其他文本。
键:“
sql_query”类型:“字符串”
描述:“SQL查询”
更新流状态:将键“
sqlQuery”设置为值{{ output.sql_query }}
该节点利用数据库模式信息,将用户的自然语言问题转换为结构化的SQL查询。
步骤 4:验证 SQL 查询语法
添加一个与“生成SQL查询”大型语言模型(LLM)相连接的条件代理节点。

配置:
说明:
你是一位注重细节的SQL专家。请仔细检查SQL查询是否存在常见错误,包括:
- 使用NOT IN与NULL值
- 本应使用UNION ALL时却使用了UNION
- 使用 BETWEEN 指定独占范围
- 谓词中的数据类型不匹配
- 正确引用标识符
- 为函数使用正确数量的参数
- 转换为正确的数据类型
- 使用正确的列进行连接输入:
{{ $flow.state.sqlQuery }}场景: 场景1:“SQL查询正确且不包含错误”
场景2:“SQL查询包含错误”
这个验证步骤会在执行前发现常见的SQL错误。
步骤5:处理查询重新生成(错误路径)
对于来自上一个条件代理节点的错误查询(输出1),请添加一个循环节点。

配置:

循环回溯至:“生成SQL查询”
最大循环次数:设置为5
这形成了一个反馈循环,使系统能够在验证失败时重新尝试生成查询。
步骤 6:执行有效的 SQL 查询
对于正确的查询(输出为0),请添加一个自定义函数节点。

配置:

输入变量:在此,我们将生成的SQL查询作为变量传入,以在函数中使用。
变量名:“sqlQuery”
变量值:
{{ $flow.state.sqlQuery }}
Javascript函数:此函数对数据库执行经过验证的SQL查询,并对结果进行格式化。
/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
const { DataSource } = require('typeorm');;
const HOST = 'localhost';;
const USER = 'testuser';;
const 密码 = 'testpwd';;
const DATABASE = 'testdatabase';;
const 端口 = 5432;;
const sqlQuery = $sqlQuery;;
const AppDataSource = new DataSource({
类型:'postgres',
主机:HOST,
端口:PORT,
用户名:USER,
密码:PASSWORD,
数据库:DATABASE,
同步:否,
日志记录:否,
});
let formattedResult = '';;
异步函数 runSQLQuery(query) {
尝试 {
等待 AppDataSource 初始化完成;
const queryRunner = AppDataSource.createQueryRunner();;
const rows = await queryRunner.query(query);;
console.log('行数 =', rows);;
如果 (rows.length === 0) {
格式化结果 = '[无结果返回]';;
} else {
const columnNames = Object.keys(rows[0]);;
const header = columnNames.join(' ');;
const values = rows.map(row =>
`columnNames.map(col => row[col]).join(' ')`
);
格式化结果 = 查询 + '\n' + 头部 + '\n' + 值.join('\n');;
}
等待 queryRunner 释放资源;
} catch (err) {
console.error('[错误]', err);;
格式化结果 = `[执行查询时出错]:${err}`;
}
返回格式化结果;
}
等待执行SQL查询(sqlQuery);
返回 formattedResult;步骤7:检查查询执行结果
添加一个与“运行SQL查询”功能相连接的条件代理节点。

配置:
说明:“您是一位SQL专家。请检查查询结果是否正确或是否存在错误。”
输入:
{{ customFunctionAgentflow_1 }}场景: 场景1:“结果正确且不包含错误”
场景2:“结果查询包含错误”
这一步骤验证执行结果,并确定是否需要进一步修正。
第8步:生成最终响应(成功路径)
为了获得成功的结果(条件代理输出0),请添加一个LLM节点。

配置:
输入消息:
{{ customFunctionAgentflow_1 }}
该节点根据查询结果生成自然语言回复。
步骤9:处理查询重新生成(运行时错误路径)
对于执行失败的情况(条件代理输出1),请添加一个LLM节点。

配置:

消息:添加与步骤3相同的系统消息
输入消息:
给定生成的SQL查询:{{ $flow.state.sqlQuery }}
我遇到了以下错误:{{ customFunctionAgentflow_1 }}
重新生成一个能修复错误的新的SQL查询JSON结构化输出:与步骤3相同
更新流状态:将键“
sqlQuery”设置为值{{ output.sql_query }}
此节点用于分析运行时错误并生成已更正的SQL查询。
步骤10:添加第二个环回
添加一个与“重新生成SQL查询”LLM(大型语言模型)相连接的循环节点。

配置:
循环回溯至:“检查SQL查询”
最大循环次数:设置为5
这为运行时错误纠正创建了第二个反馈循环。
完整流程结构
{"name": "SQL Agent", "description": "SQL Agent 是一个用于管理 SQL 数据库的工具。", "version": "1.0.0", "author": "zhangjing", "license": "MIT"}摘要
开始 → 获取数据库结构
获取数据库结构 → 生成SQL查询
生成SQL查询 → 检查SQL查询
检查SQL查询(是否正确)→ 运行SQL查询
检查SQL查询(不正确)→ 重新生成查询(回环)
运行SQL查询 → 查看结果
检查结果(成功)→ 返回响应
检查结果(错误)→ 重新生成SQL查询
重新生成SQL查询 → 重新检查SQL查询(循环回溯)
测试您的SQL代理
用各种类型的数据库问题来测试你的代理:
简单查询:“显示所有客户”
复杂查询:“销售额最高的前5个产品是什么?”
分析查询:“按月份计算平均订单价值”

此SQL代理流为数据库交互提供了一个健壮的、具有自我纠正功能的系统,能够处理自然语言中的SQL查询。
Last updated