本文基于 mystu 项目中的 structured-query-pack,说明「结构化智能问数」的完整实现逻辑、Skill 如何被大模型发现与使用、如何封装为可复用 pack,以及在其他 Agent 项目中如何接入。
适用读者:需要在 deepagents / LangGraph Agent 上落地 Text-to-SQL、且希望工作流可拷贝复用的开发者。


一、什么是「智能问数」

智能问数指:用户用自然语言提问(如「青岛港 PB 粉最新库存和环比多少?」),由 LLM 驱动的 Agent 自动完成:

  1. 识别这是需要具体数字、聚合、排名的结构化问题;
  2. 查看数据库 schema;
  3. 生成并执行 只读 SQL
  4. 把查询结果转成带口径说明的自然语言回答。

技术链路:LLM 写 SQL → 服务端 sqlglot 校验 → MySQL 只读执行 → LLM 解读结果。全程不使用向量 / Embedding


二、整体架构

数据层

工具层 structured_query_pack

Skill 磁盘目录

deepagents Agent

用户

启动时注入 skill 摘要

按需

read_file

不会自动

tool call

自然语言问题

系统提示词

SkillsMiddleware

DeepSeek LLM

read_file 内置工具

structured-query/SKILL.md

references/iron-ore.md overlay

sql_db_list_tables

sql_db_schema

sql_db_query_checker

sql_db_query + sql_guard

只读 MySQL

view_port_inventory 等白名单视图

三层分工:

层级 职责 代码/文件位置
Skill(工作流) 告诉 LLM「何时用、按什么顺序调工具、如何解释结果」 structured-query-pack/skills/structured-query/SKILL.md
Toolkit(能力) 提供 LangChain 标准 SQL 四工具 + sqlglot 护栏 structured-query-pack/structured_query_pack/
Host 接入(装配) CompositeBackend、工具注入、系统提示词补充 mystu 的 deepagent.py

三、大模型如何发现并使用 Skill(含 iron-ore.md 说明)

这是理解整个问数链路的关键:哪些文件会自动进上下文,哪些不会

3.1 SkillsMiddleware:只扫描 SKILL.md 的 frontmatter

Agent 配置了 skills=["/skills/"] 后,SkillsMiddleware 在会话开始时:

  1. 通过 CompositeBackend 列出 /skills/ 下子目录(如 structured-query/);
  2. 仅读取 每个目录里的 SKILL.md
  3. 解析 YAML frontmatter(namedescriptionallowed-tools);
  4. 把 skill 摘要追加到系统提示词,例如:
- **structured-query**: 铁矿石结构化数据智能问数:使用 SQLDatabaseToolkit 查询数值指标...
  -> Allowed tools: sql_db_list_tables, sql_db_schema, sql_db_query, sql_db_query_checker
  -> Read `/skills/structured-query/SKILL.md` for full instructions

这叫做 渐进式披露(Progressive Disclosure):大模型先看到「有哪些 skill、干什么用」,不会在启动时把 SKILL.md 全文塞进上下文。

3.2 大模型何时读 SKILL.md 全文

deepagents 在系统提示词中指示大模型:

  1. 判断用户问题是否匹配某个 skill 的 description(如数值、环比类问题 → structured-query);
  2. 需要时调用内置 read_file,路径为 skill 列表里给出的 /skills/structured-query/SKILL.md
  3. 按 SKILL.md 中的工作流调用 sql_db_* 工具。
sql_db_* 工具 read_file SkillsMiddleware 大模型 用户 sql_db_* 工具 read_file SkillsMiddleware 大模型 用户 注入 structured-query 摘要(name/description/path) 青岛港 PB 粉最新库存? read_file("/skills/structured-query/SKILL.md") 返回完整工作流与示例 sql_db_schema → sql_db_query 查询结果 自然语言回答

3.3 iron-ore.md 不会自动加载

路径:

/skills/structured-query/references/iron-ore.md

磁盘对应:

structured-query-pack/skills/structured-query/references/iron-ore.md

重要事实:

文件 是否自动进上下文 说明
SKILL.md frontmatter 摘要 SkillsMiddleware 启动时注入系统提示词
SKILL.md 全文 大模型按需 read_file
references/iron-ore.md SkillsMiddleware 不扫描 references/ 目录

iron-ore.md 是 mystu 的领域 overlay 文档,内容包括表名说明、字段口径、示例问句等。它存在于 skill 目录旁,供人和拷贝 pack 时参考;运行时不会自动推送给大模型

当前 SKILL.md 正文仅泛化提及「若 host 提供 references/domain.md」,没有写死「请先读 iron-ore.md」,因此大模型默认不会去读它。

3.4 mystu 中铁矿石领域知识实际从哪来

在不读 iron-ore.md 的情况下,问数仍能工作,因为领域信息已通过其他途径注入:

来源 注入方式 内容
configure.py --preset iron-ore 渲染进 SKILL.md 正文 view_port_inventory、青岛港示例 SQL、字段名
系统提示词 每条消息始终可见 何时走 structured-query、工具名列表(见 iron_ore_forecast.md 中结构化查数段落)
iron-ore.md 不自动 可选;需大模型主动 read_file 或你在 SKILL/提示词里显式引导

3.5 若希望大模型「必定使用」iron-ore.md

SKILL.md 的「领域补充」一节增加显式指令,例如:

## 领域补充

执行结构化查数前,请先阅读:
`/skills/structured-query/references/iron-ore.md`
其中包含白名单表说明、字段口径与示例问句。

或在 host 项目的系统提示词里增加同一路径。这样大模型在 read_file SKILL.md 后会被引导再读 overlay。


四、一次完整问数的执行逻辑

以用户问题「青岛港 PB 粉最新库存和环比?」为例:

4.1 阶段 0:Agent 启动时装配

Web 服务启动时(mystu/controller/__init__.py lifespan)会:

  1. 调用 build_agent() 构建 deep agent;
  2. tools 列表中注入 get_sql_toolkit_tools(model) 返回的四个 SQL 工具;
  3. 设置 backend=CompositeBackend(...),把虚拟路径 /skills/ 映射到 pack 磁盘目录;
  4. 设置 skills=["/skills/"],启用 SkillsMiddleware。

相关代码(mystu 参考实现):

# mystu/buildagent/agent/deepagent.py(节选)
def _build_agent_backend() -> CompositeBackend:
    return CompositeBackend(
        default=StateBackend(),
        routes={
            "/skills/": FilesystemBackend(
                root_dir=str(AGENT_SKILLS_DIR),
                virtual_mode=True,
            ),
        },
    )

tools = [*_TOOLS, *MEMORY_TOOLS, *get_sql_toolkit_tools(model), ...]

return create_deep_agent(
    model=model,
    tools=tools,
    system_prompt=load_iron_ore_forecast_prompt(),
    backend=_build_agent_backend(),
    skills=["/skills/"],
)

4.2 阶段 1:匹配 skill 并读取工作流

大模型根据 SkillsMiddleware 注入的摘要,判断问题属于数值/聚合类 → 匹配 structured-queryread_file 读取 SKILL.md 全文。

4.3 阶段 2:按 Skill 工作流调用工具

步骤 工具 作用
1 sql_db_list_tables 列出可查询对象(已被 include_tables 限制为白名单)
2 sql_db_schema 查看 view_port_inventory 的列与样例行
3 sql_db_query_checker (可选)LLM 检查 SQL 语法/逻辑
4 sql_db_query 执行 SELECT

LLM 可能生成的 SQL 示例:

SELECT stat_date, port_name, ore_type,
       inventory_wet_10k_tons, wow_change_10k_tons, data_source
FROM view_port_inventory
WHERE port_name = '青岛港' AND ore_type = 'PB粉'
ORDER BY stat_date DESC
LIMIT 1

4.4 阶段 3:sql_guard 服务端护栏

sql_db_query 在到达 MySQL 之前,会被 sql_guard 拦截校验(structured_query_pack/sql_guard.py):

  1. sqlglot 解析为 AST,只允许 SELECT / UNION
  2. 表白名单:SQL 中出现的表名必须在 SQL_ALLOWED_TABLES 内;
  3. 禁止 DML/DDL 关键字;
  4. 自动 LIMIT:若 SQL 无 LIMIT,追加 LIMIT {SQL_MAX_ROWS}(默认 100)。

校验失败时,工具返回 Error: ... 字符串(不抛异常),LLM 可读错误信息改写 SQL 重试。

4.5 阶段 4:生成最终回答

LLM 根据 sql_db_query 返回的行数据,用自然语言回答,并注明统计日、单位(万吨湿吨)、数据来源。数值必须来自 SQL 结果,不得编造。


五、工具层实现细节(structured_query_pack)

pack 目录结构:

structured-query-pack/
├── structured_query_pack/     # Python 包
│   ├── config.py              # SQL_READONLY_DSN 等 env
│   ├── sql_guard.py           # sqlglot 护栏
│   └── sql_toolkit.py         # SQLDatabaseToolkit 封装
├── skills/
│   └── structured-query/
│       ├── SKILL.md.template
│       ├── SKILL.md           # configure 渲染产物
│       └── references/
│           ├── README.md      # overlay 说明(不自动加载)
│           └── iron-ore.md    # mystu 领域 overlay(不自动加载)
├── configure.py
├── INSTALL.md
├── CHECKLIST.md
└── wiring/deepagent_example.py

5.1 配置加载(config.py)

环境变量 说明
SQL_READONLY_DSN 只读 MySQL 连接串,如 mysql://user:pass@host:3306/agent
SQL_ALLOWED_TABLES 逗号分隔白名单,如 view_port_inventory
SQL_MAX_ROWS 自动 LIMIT 上限,默认 100

未配置 DSN 或白名单为空时,get_sql_toolkit_tools() 返回 空列表,Agent 仍可启动(优雅降级)。

5.2 SQLDatabase 构建(sql_toolkit.py)

核心函数 get_sql_toolkit_tools(model)

  1. 读取配置,构建 SQLDatabase(LangChain);
  2. 使用 SQLDatabaseToolkit(db, llm=model) 生成四工具;
  3. 仅对 sql_db_query 外包一层 sql_guard;
  4. 返回工具列表供 Agent 注入。

两个重要的兼容性处理:

问题 原因 处理
白名单是 VIEW 却报 not found LangChain 默认 view_support=False 设置 view_support=True
MySQL 报 NotImplementedError view_support=True 时会调 get_materialized_view_names(),MySQL 方言未实现 临时包装 Inspector,捕获后返回 []

5.3 与 mystu 的集成方式

mystu 通过 editable 依赖 pack,不重复维护工具逻辑:

# pyproject.toml
dependencies = ["structured-query-pack", ...]

[tool.uv.sources]
structured-query-pack = { path = "structured-query-pack", editable = true }

mystu/buildagent/agent/sql_toolkit.py 仅为薄转发:

from structured_query_pack.sql_toolkit import (
    AGENT_SKILLS_DIR,
    SKILLS_VIRTUAL_PREFIX,
    get_sql_toolkit_tools,
)

六、数据层:表、视图与样例数据

示例 DDL 见 scripts/sql/port_inventory.sql

  • 底层表:port_inventory_stat不在 Agent 白名单内,Agent 不可直接查);
  • 对外视图:view_port_inventory在白名单内,Agent 只能查视图);
  • 内置两周测试数据,便于验证环比。

.env 示例:

SQL_READONLY_DSN=mysql://industry_user:密码@192.168.169.14:3306/agent
SQL_ALLOWED_TABLES=view_port_inventory
SQL_MAX_ROWS=100

建议为 Agent 使用 只读 MySQL 账号,与业务写库账号分离。


七、为什么封装成 deepagents Skill

7.1 Skill 解决什么问题

若只有工具、没有 Skill 加上 Skill 之后
LLM 可能跳过 schema 直接写 SQL Skill 强制「先 list/schema 再 query」
工作流散落在系统提示词里,难复用 Skill 是独立 Markdown,可拷贝到其他项目
工具描述偏技术,缺领域示例 模板 + overlay 分离通用流程与业务表名
升级 SQL 工具不影响工作流文档 Skill 与 Toolkit 解耦

7.2 Skill 与 Cursor Skill 的区别

deepagents Skill(本项目) Cursor Skill(.cursor/skills/
运行环境 Agent 运行时(FastAPI / LangGraph) Cursor IDE 里的 AI 助手
加载方式 SkillsMiddleware + /skills/ 虚拟路径 用户手动 attach
内容 工作流 + allowed-tools IDE 编程指南

二者名称相似,不是同一套东西

7.3 通用模板 + 领域 overlay

设计原则:

  • pack 内 SKILL.md.template:占位符 {{DOMAIN_NAME}}{{EXAMPLE_TABLE}} 等;
  • references/iron-ore.md:mystu 领域 overlay,不自动加载;拷贝到其他项目时可删或改为 domain.md
  • 领域示例也可通过 configure.py --preset iron-ore 直接渲染进 SKILL.md

渲染命令:

# 通用项目
python structured-query-pack/configure.py

# mystu 铁矿石预设(把表名、示例 SQL 写入 SKILL.md)
python structured-query-pack/configure.py --preset iron-ore

八、Skill 文件结构说明

8.1 Frontmatter

---
name: structured-query
description: 铁矿石结构化数据智能问数:...
allowed-tools:
  - sql_db_list_tables
  - sql_db_schema
  - sql_db_query
  - sql_db_query_checker
---
  • name:skill 目录名,对应 /skills/structured-query/
  • allowed-tools:SkillsMiddleware 用于约束 LLM 在本 skill 上下文内可调用的工具;
  • 必须与 get_sql_toolkit_tools() 注入的工具名 完全一致

8.2 正文章节

章节 作用
何时使用 帮 LLM 识别数值/聚合类问题
可用工具 四工具职责表
推荐工作流 6 步标准流程
安全与约束 只读、白名单、不得编造数字
示例 占位符渲染后的领域问句 + SQL
常见错误处理 工具 Error 字符串 → 下一步动作
领域补充 可指向 references/*.md(需显式 write_file 引导才生效)

九、如何在其他项目中使用这个 Skill

9.1 拷贝 pack

将整个 structured-query-pack/ 复制到目标仓库根目录。

9.2 安装 Python 包

pip install -e ./structured-query-pack

9.3 配置环境变量

至少配置 SQL_READONLY_DSNSQL_ALLOWED_TABLES(见第五节表格)。

9.4 渲染 SKILL.md

python structured-query-pack/configure.py

9.5 接入 deepagents(最小示例)

参考 structured-query-pack/wiring/deepagent_example.py

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend
from deepagents.backends.filesystem import FilesystemBackend
from structured_query_pack import (
    AGENT_SKILLS_DIR,
    SKILLS_VIRTUAL_PREFIX,
    get_sql_toolkit_tools,
)

def build_backend():
    return CompositeBackend(
        default=StateBackend(),
        routes={
            SKILLS_VIRTUAL_PREFIX: FilesystemBackend(
                root_dir=str(AGENT_SKILLS_DIR),
                virtual_mode=True,
            ),
        },
    )

model = your_chat_model()
tools = [*your_other_tools, *get_sql_toolkit_tools(model)]

agent = create_deep_agent(
    model=model,
    tools=tools,
    system_prompt="你的系统提示词(说明何时走结构化查数)",
    backend=build_backend(),
    skills=[SKILLS_VIRTUAL_PREFIX],
)

9.6 编写领域 overlay(可选)

skills/structured-query/references/domain.md 写表白名单业务含义、字段口径。记住:该文件不会自动加载;若希望大模型使用,须在 SKILL.md 或系统提示词中写明 read_file 路径。

9.7 验收清单

structured-query-pack/CHECKLIST.md,至少确认:

  • configure.py 渲染后无残留 {{...}}
  • 启动日志有 SQLDatabaseToolkit 已加载工具
  • 未配 DSN 时 Agent 仍能启动;
  • 对话中能完成 list → schema → query 链路。

十、安全模型

层级 机制
账号 只读 MySQL 用户,无 WRITE 权限
连接 独立 SQL_READONLY_DSN,可与业务库同实例不同账号
元数据 include_tables 限制 SQLDatabase 可见对象
执行前 sqlglot AST:仅 SELECT、表白名单、禁 DML/DDL
执行后 自动 LIMIT,控制返回行数
Agent 沙箱 deepagents 默认 StateBackend,内置文件工具不触达宿主机;真实数据风险在本 SQL 工具链

SQL 查数为只读操作,配置 HITL 人工审批。


十一、常见问题排查

11.1 启动日志:SQLDatabase 初始化失败

日志会打印:typemessage、脱敏 dsnallowed_tablescatalog(当前账号可见的表/视图列表)及完整堆栈。

现象 常见原因
include_tables ... not found 且 catalog 无该视图 DSN 连错库,或视图未建
catalog 有视图但仍失败 MySQL + view_support + materialized view 兼容问题(pack 已处理)
catalog=探测失败 网络、账号密码、防火墙

11.2 有配置但日志写「跳过 SQLDatabaseToolkit」

说明 _build_sql_database() 返回了 None,SQL 四工具未注入。按 11.1 查 ERROR 日志。

11.3 Skill 未生效

检查:

  1. skills=["/skills/"] 是否传入 create_deep_agent
  2. CompositeBackend 是否把 /skills/ 路由到 AGENT_SKILLS_DIR
  3. skills/structured-query/SKILL.md 是否存在(需先运行 configure.py);
  4. frontmatter allowed-tools 与注入工具名是否一致。

11.4 iron-ore.md 写了但模型好像没用

预期行为:overlay 不会自动加载。确认是否在 SKILL.md 或系统提示词里写了「请先 read_file …/iron-ore.md」。领域内容也可通过 configure.py --preset iron-ore 直接烘焙进 SKILL.md,不依赖 overlay 文件。

11.5 工具返回 Error: 访问未授权表

LLM 生成的 SQL 使用了白名单外的表名。应引导 LLM 先 sql_db_list_tables,且只查 SQL_ALLOWED_TABLES 内的视图。


十二、扩展与演进

方向 说明
多表白名单 SQL_ALLOWED_TABLES=view_a,view_b
新领域项目 拷贝 pack → 改 configure 占位符 → 可选写 overlay
非 MySQL 需调整 DSN 转换与 sqlglot read= 方言
SQL 超时 SQL_QUERY_TIMEOUT_SEC 已读取,执行层待后续接入
独立 PyPI 包 当前采用「复制文件夹」分发

十三、相关文档与代码索引

资源 路径
可拷贝 pack structured-query-pack/
接入指南 structured-query-pack/INSTALL.md
mystu Agent 装配 mystu/buildagent/agent/deepagent.py
领域 overlay(不自动加载) structured-query-pack/skills/structured-query/references/iron-ore.md
样例 DDL + 测试数据 scripts/sql/port_inventory.sql
需求与 pack 设计 docs/brainstorms/2026-06-26-structured-query-skill-pack-requirements.md
实现计划 docs/plans/2026-06-26-001-feat-structured-query-skill-pack-plan.md

十四、小结

智能问数的本质是 「LLM 编排 + 标准 SQL Toolkit + 服务端 sqlglot 护栏 + Skill 工作流文档」

  1. Toolkit 提供 SQL 能力与安全边界;
  2. Skill 提供可拷贝的工作流;SkillsMiddleware 只注入摘要,全文靠 read_file 按需加载;
  3. references/iron-ore.md 等 overlay 不会自动加载,领域信息应写入渲染后的 SKILL.md,或在 SKILL/提示词中显式引导 read_file
  4. pack 把 Toolkit + Skill 打成可复制单元,host 项目负责 CompositeBackend 与工具注入。

structured-query-pack/INSTALL.md 接入后,任何 deepagents 项目均可获得同构的结构化问数能力。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐