构建 NL2SQL 专用 Agent¶
本文以一个“自然语言查数据库”的场景为例,说明如何构建一个只负责 NL2SQL 的专用 Agent。这个案例适合用户问题本身就是查数、统计、分组、排序或筛选,不需要主 Agent 再做复杂任务规划的场景。
NL2SQL 专用 Agent 的重点不是工具编排,而是把自然语言问题转成 SQL,并完成校验、执行和结果返回。
1. 适用场景¶
| 适用 | 不适用 |
|---|---|
| 用户问题可以直接落到数据库查询。 | 任务需要先拆解多个步骤,再决定是否查数据库。 |
| 只需要一个 NL2SQL 链路完成 schema 感知、SQL 生成、执行与结果返回。 | 任务需要调用多个工具,例如查文件、生成报告、调用外部 API 后再查数据库。 |
| 希望用固定配置验证某个业务库的 NL2SQL 效果。 | 希望把 NL2SQL 作为主 Agent 的一个能力按需调用。 |
如果你的目标是“主 Agent 先理解任务,只有遇到数据库查询时才调用 NL2SQL”,请看另一个案例:构建数据分析 Agent。
2. 整体架构¶
专用 NL2SQL Agent 的运行链路如下:
用户自然语言问题
│
▼
NL2SQLAgent(AGENT_CONFIG.type = nl2sql)
│
├─ Perceptor:读取数据库 schema、字段语义、join 信息
├─ Generator:生成候选 SQL
├─ Validator:做 SQL explain、关键词或值匹配校验
├─ Executor:执行 SQL,返回结果
├─ Reflector:必要时反思修正
└─ Selector:选择最终 SQL 与结果
其中 MetaVisor 提供表、字段、字段描述、join 关系和值匹配等增强元数据。本文不展开 MetaVisor 的完整部署流程,部署和数据导入请参考:
完成部署后,你需要拿到三个关键信息:
| 信息 | 用途 |
|---|---|
DATABASE.db_id |
MetaVisor 中注册的数据库标识。 |
METAVISOR.metavisor_url |
MetaVisor 元数据服务地址。 |
METAVISOR.valuematch_url |
ValueMatch 服务地址,用于字面值匹配。 |
3. 准备工作¶
开始前确认以下内容:
- 已完成项目安装,并能在仓库根目录执行
uv run ...。 - 已配置模型环境变量,例如
BAILIAN_BASE_URL和BAILIAN_API_KEY。 - 已准备业务数据库。SQLite 场景需要本地
.sqlite文件;MySQL/PostgreSQL 场景需要服务可连接。 - 已完成 MetaVisor/Semantic Service 部署和元数据导入,并确认服务地址可访问。
如果只是本地快速验证,建议先使用 SQLite 数据库文件;如果要复现更完整的业务数据流程,再结合后续部署教程准备 MySQL、PostgreSQL、Elasticsearch 和 MetaVisor。
4. 编写 NL2SQL Agent 配置¶
仓库内置配置位于:
dataagent/agents/nl2sql/nl2sql_agent.yaml
你可以直接修改该文件,也可以复制一份作为自己的业务配置。核心配置包括五部分。
| 配置块 | 作用 |
|---|---|
AGENT_CONFIG |
指定 Agent 类型。专用 NL2SQL 必须使用 type: "nl2sql"。 |
MODEL |
指定用于 SQL 生成和修正的 chat 模型。 |
CORE |
配置 NL2SQL 内部节点和阈值。 |
DATABASE |
指定数据库标识、数据库类型和连接参数。 |
METAVISOR |
指定增强元数据和值匹配服务地址。 |
示例配置:
AGENT_CONFIG:
name: "NL2SQL Agent"
backend: "langgraph"
type: "nl2sql"
MODEL:
deepseek:
model_type: "chat"
provider: "bailian"
params:
model: "Qwen3.6-Plus"
temperature: 0.0
CORE:
coordinator: {}
perceptor:
user_schema: null
user_evidence: null
user_sql_rules: "sql_rules_bird"
user_few_shot_examples: null
generator:
strategies: ["prompt"]
num_workers: 1
num_samples: 3
validator:
db_explain: true
keyword_match: false
metadata_match: false
reflector:
threshold: 0.9
executor:
limit: -1
preview_limit: 5
selector:
threshold: 0.9
DATABASE:
db_id: "demo_db"
engine: "sqlite"
sql_service_engine: null
config:
path: "/absolute/path/to/demo_retail.sqlite"
METAVISOR:
metavisor_url: "http://host:32000"
valuematch_url: "http://host:8000"
配置时重点检查:
DATABASE.db_id必须和 MetaVisor 中导入的数据库标识一致。DATABASE.engine要和实际数据库一致,例如sqlite、mysql、postgres。- SQLite 的
DATABASE.config.path建议使用绝对路径,避免从不同目录启动时找不到文件。 - 模型的
api_key不建议写入 YAML,优先放到.env中。
5. 运行专用 Agent¶
可以通过 SDK 直接加载配置并调用:
import asyncio
from pathlib import Path
from dataagent.interface.sdk.agent import DataAgent
async def main():
project_dir = Path(__file__).resolve().parents[2]
config_path = project_dir / "dataagent" / "agents" / "nl2sql" / "nl2sql_agent.yaml"
agent = DataAgent.from_config(config_path)
result = await agent.chat("每月订单量是多少")
print(result)
if __name__ == "__main__":
asyncio.run(main())
仓库中也提供了端到端示例脚本:
uv run tests/e2e/test_nl2sql.py
如果你复制了自己的 YAML,可以把脚本中的 config_path 改成你的配置文件路径。
6. 查看结果¶
agent.chat() 返回最终状态。排查 NL2SQL 效果时,优先查看这些字段:
| 字段 | 说明 |
|---|---|
messages |
消息流和最终回答。 |
sql |
最终选择的 SQL。 |
columns / rows / rows_preview |
查询结果字段、完整结果和预览结果。 |
generation_results |
候选 SQL 生成结果。 |
validation_results |
SQL 校验结果。 |
execution_results |
SQL 执行结果。 |
confidence |
Selector 给出的结果置信度。 |
如果返回结果为空,先判断是 SQL 没生成、SQL 执行失败,还是数据库本身没有匹配数据。
7. 常见问题¶
7.1 模型 Key 没读到¶
检查运行目录下是否存在 .env,并确认变量名和 provider 对应。例如 provider: "bailian" 会读取 BAILIAN_BASE_URL 和 BAILIAN_API_KEY。
7.2 SQLite 文件找不到¶
优先把 DATABASE.config.path 写成绝对路径。相对路径会跟随当前执行命令的工作目录变化。
7.3 MetaVisor 连接失败¶
先用 curl 验证 METAVISOR.metavisor_url 是否可访问,再确认 DATABASE.db_id 是否已经导入 MetaVisor。完整部署、初始化和导入流程请参考 Semantic Service 部署指南。
7.4 生成 SQL 和业务口径不一致¶
把用户问题写得更明确,补充实体定义、指标公式、过滤条件、统计粒度和排序要求。NL2SQL Agent 适合处理明确的查询问题,不适合替用户补全缺失的业务规则。
8. 小结¶
专用 NL2SQL Agent 的关键是:
AGENT_CONFIG.type使用nl2sql。DATABASE指向真实业务库。METAVISOR指向已完成元数据导入的 Semantic Service。- 用户问题尽量明确业务对象、指标口径和查询条件。
当你需要让一个主 Agent 同时处理任务规划、报告组织和按需查库时,不要把这些逻辑塞进专用 NL2SQL Agent,而应使用主 Agent 调用 NL2SQL 子 Agent 的模式。