自然语言 SQL 生成(NL2SQL)
⚠️ 能力范围说明:本 Skill 当前仅负责 SQL 生成与分析建议,不直接连接集群执行 SQL。生成的 SQL 语句需由用户自行复制到 TCHouse-C 控制台 SQL 工作区(DMS)或其他 ClickHouse 客户端执行。执行后如需图表可视化,用户可将结果数据回传给 Agent,Agent 会用
show_widget渲染图表并给出结论摘要。
概述
本 Skill 提供 TCHouse-C(ClickHouse)集群的自然语言 SQL 生成能力,包含三个子能力:
- 自然语言转 SQL(NL2SQL):理解用户自然语言描述的分析需求,结合表结构生成对应的 ClickHouse SQL
- 智能图表可视化推荐:根据用户描述的分析意图和预期结果特征,推荐合适的图表类型(用户回传数据后可直接用
show_widget渲染) - 中文业务结论摘要撰写建议:针对预期结果给出结论撰写模板,用户执行 SQL 后可基于模板输出面向业务人员的结论
依赖与运行环境
本 Skill 的所有调用通过 MCP Tool 完成(云 API 类工具由平台封装为 MCP Tool,Agent 直接调用工具名即可)。
依赖工具清单:
| # | Tool 名称 | 能力定位 |
|---|---|---|
| 1 | TCHouseCDescribeInstance | 集群基本信息获取(用于确认集群可用性) |
| 2 | TCHouseCDescribeInstanceNodes | 获取集群数据节点 IP 列表(TCHouseCDescribeTableSchema 的必要前置依赖,见步骤 1.5) |
| 3 | TCHouseCDescribeTableSchema | 根据表名和数据节点 IP 获取建表 DDL(提供 SQL 生成上下文) |
| 4 | ask_user | 向用户询问确认信息(WorkBuddy 中为 AskUserQuestion) |
| 5 | show_widget | 用户回传结果数据后,渲染 Chart.js 图表 |
凭证 / 环境变量
instance_id:集群实例 ID,需通过ask_user(WorkBuddy 中为AskUserQuestion)向用户询问获取region_id:地域信息,可能是RegionId数字、Region字符串或中文地域名;缺失时通过ask_user询问用户获取
⚠️ 地域参数强制规则:本 Skill 依赖的全部工具(
TCHouseCXxx系)都只接受Region字符串(如ap-guangzhou)。任何工具调用前都必须先按 地域映射表 将上下文中的地域信息(无论是中文名、英文串还是RegionId数字)统一转为Region字符串后再传入,禁止凭记忆填写。详见 工具传参形式速查。
💡 多平台兼容说明:本文档中所有提到的
ask_user工具,在 WorkBuddy 平台中对应为AskUserQuestion。后文不再重复标注。
地域映射与缓存机制
地域映射规则
⚠️ 核心原则:本 Skill 依赖的全部工具都只接受
Region字符串。无论用户提供的是中文名、英文串还是RegionId数字,都必须按 地域映射表 统一转为Region字符串后再使用。
当用户提供地域信息时,使用 地域映射表 进行统一处理:
RegionId数字输入:如上下文中region_id为1、8等数字,直接按映射表查出对应的Region字符串(1→ap-guangzhou、8 →ap-beijing)Region字符串输入:如已为ap-guangzhou,直接使用,无需转换- 精确匹配优先:如果用户给出的地域名称能精确匹配到地域映射表中的"地域名称"列,直接使用对应的
Region值 - 常见简称映射:支持常见地域简称(如"广州"→
ap-guangzhou、"上海"→ap-shanghai、"北京"→ap-beijing) - 金融区识别:用户提到"金融"、"金融区"时,优先匹配带
-fsi后缀的地域 - 所属地区模糊匹配:如果用户只说了"华南地区"等大区名称,且该大区下有多个地域,需通过
ask_user让用户确认具体地域
地域选择优化流程
步骤 0.1:地域参数确认与映射
判断逻辑:
- ✅ 参数齐全(region_id 已提供)→ 按映射表转为
Region字符串后进入步骤 1 - ❌
region_id缺失但用户问题中包含地域信息(中文名/英文串/数字 ID)→ 按映射表统一转为Region字符串后进入步骤 1 - ❌
region_id缺失且用户问题中无地域信息 → 调用ask_user询问用户确认地域
询问话术示例: "请确认您要分析的 TCHouse-C 集群所在地域(如:广州、上海、北京等)"
缓存机制:
- 用户确认的地域信息(
Region字符串)在当前会话中缓存,避免重复询问 - 如果地域调用返回
ResourceNotFound,提示用户确认地域是否正确,而非自动尝试其他地域
核心工作流
步骤 0:参数确认
必需参数:
instance_id(集群 ID)region_id(地域)
可选参数(从用户问题中提取,缺失时使用默认值,不自行假设):
- 数据库名:从用户问题中提取,未指定 → 步骤 2 中让用户告知
- 表名:从用户问题中提取,未指定 → 步骤 2 中让用户告知
- 时间范围:从用户问题中提取(如"过去7天"、"本月"),未指定 → 询问用户
- 分析维度/指标:从用户问题中提取
判断逻辑:
- ✅ 参数齐全(
instance_id和region_id均已提供)→ 强制按 地域映射表 将地域信息统一转为Region字符串(任何输入形式都要过这一步:中文名、英文串、数字 ID 都不例外),转换后进入步骤 1 - ❌
instance_id缺失 → 调用ask_user询问集群实例 ID - ❌
region_id缺失且用户问题中无任何地域信息 → 调用ask_user询问用户地域 - ❌ 地域信息在映射表中匹配不到(或大区模糊,如"华南地区")→ 调用
ask_user确认后再转换
步骤 1:确认集群信息
调用 TCHouseCDescribeInstance 获取集群基本信息,确认目标集群存在且可用。
判断逻辑:
- ✅ 集群状态为
Serving→ 进入步骤 1.5 - ❌ 集群状态异常 → 告知用户集群当前不可用,但可继续基于用户提供的表结构信息生成 SQL(本 Skill 不实际执行 SQL)
- ❌ 调用失败(AuthFailure)→ 报告错误,提示检查权限
- ❌ 调用失败(ResourceNotFound)→ 检查 instance_id 格式(应为
cdwch-前缀),格式错则修正重试,格式对则请用户确认
⚠️ 重要提醒:
TCHouseCDescribeInstance返回的AccessInfo中的 IP 是 VIP/代理地址,不是数据节点 IP,不能用于步骤 2 的TCHouseCDescribeTableSchema调用(传入会得到Exists=false)。数据节点 IP 必须通过步骤 1.5 单独获取。
步骤 1.5:获取数据节点 IP(步骤 2 的必要前置)
目的:TCHouseCDescribeTableSchema 的 NodeIp 参数要求传入数据节点真实 IP,必须先通过本步骤获取。
调用方式:
- 调用
TCHouseCDescribeInstanceNodes,传参NodeRole=DATA(可加ForceAll=true一次性拿全) - 从返回的
InstancesList中任选一个Status正常的节点Ip作为后续TCHouseCDescribeTableSchema的NodeIp入参 - 本轮分析中该 IP 可缓存复用,避免每次表结构查询都重复调用
判断逻辑:
- ✅ 成功拿到至少一个可用数据节点 IP → 进入步骤 2
- ❌ 返回节点列表为空或全部异常 → 告知用户集群数据节点当前不可用,可请用户直接提供表 DDL(走步骤 2.3 兜底)
- ❌ 调用失败(AuthFailure/ResourceNotFound)→ 按错误码表处理
⚠️ 禁止事项:
- 禁止把
TCHouseCDescribeInstance的AccessInfoIP 当作NodeIp(那是 VIP,DescribeTableSchema会返回Exists=false)- 禁止凭记忆或猜测填 IP
步骤 2:收集表结构信息
目的:了解用户目标表的库表结构,为 SQL 生成提供上下文。
由于本 Skill 不直接连接集群执行 SHOW DATABASES / SHOW TABLES,表结构信息通过以下方式获取(按优先级):
2.1 快速路径:直接调用 DescribeTableSchema
如果用户已明确 数据库名 + 表名:
- 调用
TCHouseCDescribeTableSchema获取表的建表 DDL,其中NodeIp必须使用步骤 1.5 获取到的数据节点 IP(禁止使用DescribeInstance返回的 VIP) - 从 DDL 中提取列名、类型、注释、排序键、分区键等关键信息
- 如返回
Exists=false,优先怀疑NodeIp传错(是否误用了 VIP),核对后重试;仍为 false 再向用户确认库表名
2.2 参数缺失时的兜底流程
如果用户未明确数据库名或表名:
- 通过
ask_user一次性询问用户 数据库名 + 表名(避免多轮追问) - 询问话术示例:"请告知需要分析的数据库名和表名(例如
db_analytics.orders)。如果不确定具体表名,可以先在 TCHouse-C 控制台 SQL 工作区执行SHOW TABLES FROM 数据库名查看后再告诉我。" - 用户回复后进入 2.1
⚠️ 禁止基于用户描述的维度/指标猜测表名(如"渠道支付金额"→ payments/orders、"用户注册数"→ users 等猜测均不可靠)。表名必须由用户明确提供。
2.3 用户直接提供 DDL 的情况
用户可能会直接把建表 DDL 粘贴过来。此时:
- 直接从用户提供的 DDL 中解析列信息,跳过
TCHouseCDescribeTableSchema调用 - 进入步骤 3
步骤 3:理解需求与生成 SQL
3.1 需求理解:
从用户自然语言中提取:
- 分析目标:统计什么(如"支付金额"、"用户数")
- 时间范围:什么时间段(如"过去7天"、"本月")
- 分组维度:按什么维度汇总(如"按天"、"按渠道")
- 过滤条件:有什么限制(如"只看VIP用户")
- 排序/限制:TOP N、升序/降序
- 可视化意图:趋势图、对比图、占比图等(用于步骤 4 图表推荐)
3.2 SQL 生成:
基于表结构和需求理解,生成 ClickHouse SQL。遵循 SQL 生成规范。
关键原则:
- 必须使用分区键过滤(避免全表扫描)
- 只 SELECT 需要的列(ClickHouse 列式存储,SELECT * 性能差)
- 时间函数使用 ClickHouse 原生函数(toDate/toYYYYMM/toStartOfDay 等)
- 大表 JOIN 时小表放右侧
- 聚合查询必须有 GROUP BY
- 结果行数建议控制在 1000 行以内(默认加
LIMIT 1000,超过时告知用户)
3.3 SQL 输出规范:
向用户交付 SQL 时必须包含以下内容:
- 完整 SQL 语句:使用 Markdown 代码块(
sql ...)包裹,方便用户复制 - 占位符标注:如 SQL 中包含需用户按实际情况调整的常量(如日期范围、过滤条件的具体值),使用
-- TODO: ...注释明确标出 - 执行方式提示:在 SQL 下方附一句执行指引:
请将上述 SQL 复制到 TCHouse-C 控制台「SQL 工作区(DMS)」执行;执行完成后如需生成图表和结论摘要,可将结果数据(表格或 JSON 格式)回传给我。
- 设计说明:简述 SQL 关键设计点(分区键命中情况、聚合逻辑、性能注意事项)
步骤 4:图表可视化推荐
根据用户描述的分析意图和 SQL 预期返回的数据结构(列数、维度类型),推荐合适的图表类型。详见 可视化推荐规则。
图表选择决策树:
| 数据特征 | 分析意图 | 推荐图表 |
|---|---|---|
| 时间序列 + 数值 | 趋势变化 | 📈 折线图 |
| 分类 + 数值(≤ 10 类) | 对比大小 | 📊 柱状图 |
| 分类 + 占比(≤ 8 类) | 占比分布 | 🥧 饼图/环形图 |
| 两个数值维度 | 相关性 | 散点图 |
| 时间 + 分类 + 数值 | 多系列趋势 | 📈 多折线图 |
| 分类 + 多指标 | 多维对比 | 📊 分组柱状图 |
| 单一数值 | 关键指标 | 🔢 数字卡片 |
| 排名(TOP N) | 排序对比 | 📊 横向柱状图 |
输出方式:
- 场景 A(用户仅要 SQL):在 SQL 输出下方以文字形式给出推荐图表类型及理由,例如:"建议使用多折线图展示各渠道的每日支付金额趋势"
- 场景 B(用户回传了 SQL 执行结果数据):直接调用
show_widget用 Chart.js 渲染图表,并附 Markdown 结果表格
💡 show_widget 图表生成要点(仅场景 B):
- 使用 Chart.js 库渲染图表
- 根据数据特征配置合适的图表选项(标题、坐标轴标签、图例、颜色方案等)
- 标签使用中文
步骤 5:业务结论摘要建议
场景 A(用户仅要 SQL):给出结论撰写模板,说明用户执行完 SQL 后可按此模板整理结论。
场景 B(用户回传了结果数据):直接基于数据生成中文业务结论。详见 结论生成规范。
结论结构:
- 核心发现(1-2 句话概括最重要的结论)
- 数据支撑(关键数字和对比)
- 趋势判断(上升/下降/平稳,环比/同比变化)
- 异常提示(如有明显异常值或突变)
- 建议行动(基于数据的业务建议,可选)
输出要求:
- 使用中文,面向非技术人员
- 数字使用千分位分隔(如 1,234,567)
- 百分比保留 2 位小数
- 金额标注单位(元/万元/亿元)
- 避免使用技术术语(如"聚合"、"JOIN")
频率控制
| 限制 | 阈值 | 说明 |
|---|---|---|
| 工具总调用频率 | ≤ 15 次/分钟 | 避免触发平台限流 |
| TCHouseCDescribeTableSchema 调用 | ≤ 5 次/轮分析 | 避免重复拉取相同表结构 |
超限处理:连续收到 RequestLimitExceeded → 等 5 秒重试,连续 3 次仍失败 → 降低调用频率,告知用户被限流。
错误码与处理策略
| 错误码/场景 | Agent 行为 |
|---|---|
AuthFailure.* |
报告鉴权失败,提示用户检查集群访问权限 |
ResourceNotFound |
检查 ID 格式(cdwch- 前缀);格式错 → 修正重试;格式对 → 请用户确认 |
InvalidParameter.* |
检查参数格式,尝试修正后重试 1 次;无法修正 → 报告具体问题 |
UnsupportedRegion |
该地域未开通 TCHouseC 产品。不重试、不自动切换地域,必须调用 ask_user 让用户确认地域。详见 error-handling.md §1 |
InternalError |
等 3 秒重试,最多 3 次;仍失败 → 报告错误码 + RequestId |
RequestLimitExceeded |
等 5 秒重试;连续 3 次 → 降低频率,告知被限流 |
| 表/列不存在 | 提示用户确认表名和数据库名,重新获取表结构 |
| 网络超时 | 等 3 秒重试,最多 3 次;仍失败 → 告知用户服务暂时不可用 |
| 兜底(未列出错误码) | 报告完整错误信息 + RequestId |
安全规则
- 本 Skill 仅生成 SELECT 查询:生成的 SQL 必须是 SELECT 语句,严禁生成 INSERT/UPDATE/DELETE/DROP/ALTER/TRUNCATE 等写操作
- SQL 注入防护:用户输入不直接拼接到 SQL 中,通过参数化或严格校验处理
- 数据量控制:SQL 中默认加
LIMIT 1000,避免用户执行时返回海量数据 - 敏感数据提示:如果 SQL 可能涉及个人隐私字段(手机号、身份证等),在输出前提醒用户注意数据安全
- 不直接执行:本 Skill 只生成 SQL,不连接集群执行;用户在自行执行前应确认 SQL 无误
检查清单(各步骤执行前自动验证)
步骤 0:参数确认检查清单
- 确认
instance_id和region_id参数是否齐全 - 无论用户提供的是中文地域名、英文
Region字符串还是RegionId数字,是否已按地域映射表统一转为Region字符串 - 是否需要通过
ask_user询问缺失参数
步骤 1.5:数据节点 IP 检查清单
- 是否已通过
TCHouseCDescribeInstanceNodes(NodeRole=DATA)获取到至少一个可用数据节点 IP - 是否没有使用
TCHouseCDescribeInstance的AccessInfoIP(VIP)作为NodeIp
步骤 2:表结构收集检查清单
- 是否已明确数据库名和表名(否则需
ask_user询问) - 是否已通过
TCHouseCDescribeTableSchema获取表结构,或用户已提供 DDL - 调用
TCHouseCDescribeTableSchema时NodeIp是否使用步骤 1.5 拿到的数据节点 IP - 是否已提取列名、类型、注释、分区键、排序键等关键信息
步骤 3:SQL 生成检查清单
- WHERE 条件是否包含分区键过滤(避免全表扫描)
- 是否避免使用
SELECT *(只选需要的列) - 时间范围是否使用动态函数(
today()、now()而非硬编码) - 中文列名是否用反引号包裹
- 非聚合查询是否添加了
LIMIT - SQL 是否用 Markdown 代码块包裹便于用户复制
- 是否附上执行方式提示(引导用户到控制台 SQL 工作区执行)
步骤 4:可视化检查清单
- 图表类型是否匹配数据特征和分析意图
- 用户仅要 SQL 时是否用文字形式给出推荐图表类型
- 用户回传结果数据时是否用
show_widget直接渲染 - 图表标签是否使用中文
步骤 5:结论生成检查清单
- 结论是否使用中文面向业务人员
- 数字是否使用千分位分隔
- 是否包含核心发现、数据支撑、趋势判断
- 是否避免使用技术术语
高频经验提醒
| 经验 | 触发时机 | 说明 |
|---|---|---|
| 本 Skill 不直接执行 SQL | 每次交付 SQL 时 | 必须提醒用户到 TCHouse-C 控制台 SQL 工作区(DMS)自行执行;如需生成图表可回传结果数据 |
| 时间过滤必须命中分区键 | 步骤 3 生成 SQL 时 | WHERE 条件必须包含分区键字段,优先使用 today() 等动态函数 |
| 中文列名需要反引号 | 步骤 3 生成 SQL 时 | ClickHouse 中文列名必须用反引号包裹,否则语法错误 |
| 表名不能猜测 | 步骤 2 收集表结构时 | 禁止基于用户描述的维度/指标猜测表名,必须由用户明确提供 |
| NodeIp 只能用数据节点 IP | 步骤 1.5 / 步骤 2 | TCHouseCDescribeTableSchema 的 NodeIp 必须传 TCHouseCDescribeInstanceNodes 返回的数据节点 IP;DescribeInstance 的 AccessInfo 是 VIP,传入会返回 Exists=false |
| 默认加 LIMIT 1000 | 步骤 3 生成 SQL 时 | 非明确要求全量的场景,SQL 默认加 LIMIT 1000,避免用户执行时返回海量数据 |
| 地域缺失必须询问 | 步骤 0 参数确认时 | 不要自动猜测地域;无论用户提供中文名、英文串还是 RegionId 数字,都必须按地域映射表统一转为 Region 字符串 |