今天介绍如何使用 n8n 来实现数据问答智能体,可以连接 MySQL、Postgres、SQLite 等数据库,然后实现基于自然语言的数据库问答功能。
本期内容:
• 数据问答智能体• Chat Trigger 节点• Agent 节点• 工具使用• 自动获取数据库和表• 数据问答测试和过程分析• 6种 n8n 智能体类型介绍• n8n SQL Agent 提示词研究
流程本身非常简单(如下),但是构建数据问答类智能体的过程以及要点都在下面了。大家即使不用 n8n,也可以用任意自己喜欢的框架来 搭建一个数据问答智能体。
新建一个流程,添加一个 Chat Trigger
聊天触发器在为聊天机器人和其他聊天界面构建 AI 工作流时,可以使用聊天触发器(Chat Trigger)节点,可以发送消息给工作流,从而触发工作流的执行, 并返回工作流的执行结果。
然后添加一个 Agent
节点,来实现对数据库的操作。
效果如下:
重点来了,
首先设置 Agent 类型为 Tool Agent
,
如果你的 Agent 节点没有类型选择,那么它会默认 Tool Agent
类型。 直接使用就行。
n8n 的 Agent 类型有六种类型(Agent 节点文档[1]):
• 工具代理 利用结构化工具模式进行精确和可靠的工具选择与执行。推荐用于需要准确和一致工具使用的复杂任务,但仅适用于支持工具调用的模型。• 对话代理 描述系统提示中的工具,并解析工具调用的 JSON 响应。更灵活,但可能不如工具代理可靠。适合较简单的交互或不支持结构化模式的模型。• OpenAI 函数代理 利用 OpenAI 的函数调用能力精确选择和执行工具。非常适合需要结构化输出的任务,尤其是在使用 OpenAI 模型时。• 计划和执行代理 为复杂任务创建高层次计划,然后执行每个步骤。适合多阶段问题或需要战略方法的情况。• ReAct 代理 在迭代过程中结合推理和行动。适用于需要仔细分析和逐步解决问题的任务。• SQL 代理 专注于与 SQL 数据库交互。理想用于数据分析任务、生成查询或从结构化数据中提取洞察。
最常用的就是工具代理,因为我们构建AI代理的核心就是让 AI 与其他系统调用,也就是使用工具。
ReAct 代理 和 LangChain 代理一样,会自己进行推理和行动。
SQL 代理是 n8n 的特殊代理,它可以直接与数据库进行交互,然后返回结果给我们。但是我简单测试下来效果并不好(注意是简单测试哦), 而且轮询的次数比较多,文章最后我会给大家演示一下。
Agent 性能好坏很重要的一点就是提示词的质量。
我们今天的任务也不例外,给 Agent增加系统提示词,传统的数据问答提示词我们一般这样写:
你是数据库助手。你需要根据用户请求在数据库中运行查询。运行自定义 SQL 查询以聚合数据并响应用户。确保在 SQL 查询中每个表都有模式前缀,你可以通过“获取数据库模式和表列表”工具获取。如有需要,提取所有数据以进行分析。工具:...列出所有的工具
不过在 n8n 中我们的提示词也可以不写工具的调用提示, n8n 会帮我们自动处理好工具调用,这样提示词就可以简化成:
你是数据库助手。你需要根据用户请求在数据库中运行查询。运行自定义 SQL 查询以聚合数据并响应用户。确保在 SQL 查询中每个表都有模式前缀,你可以通过“获取数据库模式和表列表”工具获取。如有需要,提取所有数据以进行分析。
Agent 的 Chat Model
增加一个大模型,选择你喜欢的模型,比如 DeepSeek 或者 QWen,不需要过多的设置。
如果把提示词比作智能体的灵魂,那么工具调用就是智能体的双手。
添加节点搜索 Postgres
数据库,
选择执行SQL查询的动作,SQL 语句从 AI 中获取,
获取数据库和表的工具,这样我们就可以自动获取数据库和表了,然后让 AI 选择合适的表来回答问题。
SELECT table_schema, table_nameFROM information_schema.tablesWHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')ORDER BY table_schema, table_name;
会后是列出数据库表字段的工具,AI 会自动调用这些工具来获取表数据,自动生成 SQL 查询语句。
select c.column_name, c.data_type, c.is_nullable, c.column_defaultfrom information_schema.columns cwhere c.table_name = '{{ $fromAI("table_name") }}' AND c.table_schema = '{{ $fromAI("schema_name") }}'order by c.ordinal_position
最终的配置结果如下:
早期的 AI 数据问答,大家都多是把数据库表信息定义给 AI 作为上下文,这样的好处是简单, 坏处也很明显,如果上下文太多的话,处理起来会比较麻烦。(我2023年的时候就是这样做的,也写文章给大家分享过)
解决上述问题也很简单,随着 RAG 的兴起,数据问答上下文的问题很自然也被 RAG 解决了, 比如 Vanna 的 RAG-to-SQL,它可以通过查询向量库来拼接上下文。
而向量库里面存储的东西就很自由了,比如常规的表结构、业务文档、常用的SQL问答示例等。
我们使用 n8n 实现 数据问答也是同样的思路,
• 同样使用向量库进行• 大家也可以在上述流程之上扩展,比如增加业务文档,常用的SQL问答示例作为训练数据
我们的改进点就是,
• 让 Agent 调用大模型选择工具,按需自动获取表结构
下面测试下刚刚搭建的智能体流程,我们先问一下有多少数据表。
提示词有哪些数据表
从下图中可以看到:
• 获取数据库和表的工具被调用了• 在日志窗口可以看到整个对话背后的执行过程:1. 获取对话历史2. Agent 调用大模型选择工具3. 执行工具4. 获取工具返回结果5. Agent 调用大模型生成回答• 生成的回答被返回给聊天
由于这个是我前面一个备份的 n8n 数据库,接下来我们在测试下其他问题。
测试前刷新开启一个新对话,
提示词有哪些工作流
我们可以看到 Agent 依次:
• 获取数据库和表• 获取表定义• 执行SQL查询
结果中返回了 工作流的 ID 和名称:
n8n Agent 几种类型已经弃用了,新版本统一建议使用 Tool Agent。
可以在文档上看到各种 Agent 的说明:
• https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/[2]
SqlAgent 是不需要配置工具的,直接使用即可。我们测试一下。
提示词有哪些用户
我们发现他执行了很多次推理,仍然没有成功。
刷新重新试一下,依然找不到。
应该是我的使用方法不对。
我们来看下 SQL 代理官方写的提示词,非常值得我们学习借鉴。
首先是任务说明,
任务说明你是一个被设计用来与 SQL 数据库交互的助手。 给定一个输入问题,创建一个语法正确的 SQLite 查询来运行,然后查看查询结果并返回答案。 除非用户指定了他们希望获得的具体示例数量,否则始终使用 LIMIT 子句将查询结果限制在最多 10 条。 你可以通过相关列对结果进行排序,以返回数据库中最有趣的示例。 永远不要查询特定表的所有列,只询问与问题相关的少数几列。 你可以使用工具与数据库进行交互。 只能使用以下工具。只能使用以下工具返回的信息来构建最终答案。 在执行查询之前,你必须仔细检查你的查询。如果在执行查询时遇到错误,请重写查询并重试。不要对数据库执行任何 DML 语句(INSERT、UPDATE、DELETE、DROP 等)。如果问题似乎与数据库无关,则只返回“我不知道”作为答案。
上面说明中把 SQL 问答中一些最佳实践都列出来了,比如:
• 查询结果限制在最多 10 条• 让AI选择对结果进行排序• 不要查询表所有列• 不要使用 DML 语句
下面是工具说明,等后面找到相应工具的实现再和大家分享。
工具说明• query-sql:此工具的输入是一个详细且正确的 SQL 查询,输出是数据库的查询结果。 如果查询不正确,将返回错误消息。 如果返回错误,请重写查询,检查查询,然后重试。• info-sql:此工具的输入是以逗号分隔的表列表,输出是这些表的模式和示例行。 通过首先调用 list-tables-sql 来确保这些表实际存在! 示例输入:“table1, table2, table3.”• list-tables-sql:此工具的输入是一个空字符串,输出是数据库中以逗号分隔的表列表。• query-checker:在执行查询之前,使用此工具仔细检查你的查询是否正确。 在执行带有 query-sql 的查询之前,务必使用此工具!
ReACT 格式的回复格式,也和我么刚才测试的思索过程相匹配。
格式说明在你的回复中使用以下格式:• Question: 你必须回答的输入问题• Thought: 你应该总是思考该做什么• Action: 要采取的行动,应该是 [["query-sql","info-sql","list-tables-sql","query-checker"]] 之一• Action Input: 该行动的输入• Observation: 该行动的结果• ... (这个 Thought/Action/Action Input/Observation 可以重复 N 次)• Thought: 我现在知道最终答案• Final Answer: 原始输入问题的最终答案
最后不得不夸一句 n8n 关于智能体的设计真的是太棒了, 我现在给别人讲智能体概念的时候,都拿着 n8n 的图来讲,简单明了。 非技术人员也基本都能理解。
[1]
Agent 节点文档: https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/[2]
: https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/
有话要说...