关于 di-agent-query-substrait
将自然语言数据需求转换为可编译的 Substrait JSON,供使用项目数据资产的分析流程生成查询计划。该技能从资产元数据核验列名、类型和可空性,并通过 DSL 编译验证结果。
主要功能
- 01将自然语言需求转为 Substrait DSL
- 02从项目资产核验表结构
- 03映射列类型与可空性
- 04支持连接、筛选和聚合
- 05编译检查并按错误修正
- 06按需执行查询或转换为 Elyra JSON
适用场景
- 01根据实际资产结构生成查询计划
- 02为多表连接和聚合编写查询
- 03将已验证的 DSL 转为 Elyra 流水线 JSON
MCP 相关
工作流调用 Substrait 相关 MCP 工具检索示例、读取规范与项目资产、编译 DSL,并可按要求执行或转换。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ibm/ ibm-watsonx-data-integration-skills --skill di-agent-query-substrait安装后在 Claude Code 中输入/di-agent-query-substrait确认已加载。
附带文件examples/aggregate-with-sort.mdexamples/join-with-filter.md
详细介绍
生成 Substrait DSL
通过 Substrait DSL 将自然语言数据请求转换为可执行的 Substrait JSON。
必需输入
我们需要流程描述和输入架构。正确获取输入架构非常重要,并且它应与资源浏览器中的名称和类型一致。使用 list_project_assets 按名称查找相关资源,并使用资源 ID 调用 inspect_project_asset,以获取权威的列名、类型和可空性。不要使用少镜头示例或先验知识等其他信息来猜测架构——必须从项目资源中推导架构,以确保生成的 Substrait 计划对实际数据有效。
如果用户提供了表架构(一个或多个源表的列名和 Substrait 类型),请使用 list_project_assets 和 inspect_project_asset 对照项目中的实际资源进行验证。如果存在不一致之处,请告知用户。除非用户明确指定要覆盖,否则以资源工具提供的架构为准。
如果用户未提供表架构,请直接通过调用 list_project_assets 和 inspect_project_asset 从项目资源中推导架构。
获取资源后,通过将资源映射到 DSL 类型来构建一个 NamedStruct,映射关系如下:
资源类型映射
从检查过的资源构建 NamedStruct 时,请按以下方式将资源列类型映射为 DSL 类型:
| 资源类型 | DSL 类型 |
|---|---|
longvarchar、varchar、char、text | string |
bigint、int8 | i64 |
integer、int、int4 | i64 |
smallint、int2 | i16 |
real、float4 | fp32 |
numeric、decimal | fp64 |
double precision、float8 | fp64 |
boolean、bool | boolean |
date | date |
timestamp、timestamp without time zone | timestamp |
对于资源元数据中 nullable: true 的列,请在 DSL 类型后添加 ?(例如,string?)。
工作流
按照以下步骤,根据自然语言请求生成 Substrait 计划。
1. 获取少镜头示例
调用 get_substrait_dsl_examples 获取相关 DSL 示例。
关键规则——user_request 参数必须是用户的完整原始消息,逐字复制,不得进行任何修改。 检索系统使用句子级语义嵌入,需要完整上下文才能正确匹配。传入关键词或摘要会返回无关示例,并导致后续步骤失败。
get_substrait_dsl_examples(user_request="<FULL VERBATIM USER MESSAGE — EVERY WORD, NO SUMMARIZATION>", collection="draft_generation", n=5)
错误(关键词/摘要):user_request="join two tables aggregate count sum divide cast round NPS score"
正确(完整原文):user_request="Given a fct_reviews table (listing_id, review_date, reviewer_name, review_text, review_sentiment) and a dim_listings table (listing_id, listing_name, minimum_nights, host_id, room_type, price, created_at, updated_at), produce a per-listing NPS aggregation result set. For each listing: listing_id, listing_name, room_type, nps_total (overall NPS in [-100, 100] across all reviews of that listing, computed as (positive - negative) / total * 100, rounded to 0 decimals), reviews_total (total review count). Inner join on listing_id; only include listings that have at least one review."
user_request 字符串的长度应与用户消息的长度一致。如果你的 user_request 比用户消息短,就说明做错了。
仔细研究返回的示例,以了解 DSL 语法。切勿使用少镜头示例推导任何输入架构,即使示例看起来更合适——架构必须按下一步所述从项目资源中获取。
2. 从资产验证架构
必须使用资产工具验证架构。否则,生成的计划将无效且无法执行!
- 调用
list_project_assets,按名称查找项目中的资产 - 使用资产 ID 调用
inspect_project_asset,并设置asset_type="data_asset",以获取列元数据 - 对每一列,根据上方的 资产类型映射 表将资产类型映射为 DSL 类型
- 必须在可空列的类型后追加
?(例如,string?) - 将得到的架构用作
ReadTable的NamedStruct
资产浏览器中找到的架构优先于少样本示例中提及的任何架构。如果与用户提供的架构不一致,请指出差异并询问用户要使用哪一个。
3. 生成 DSL
调用 get_substrait_dsl_spec 获取语言规范。编写任何 DSL 代码前,请仔细研读规范。根据用户的请求,使用已验证的表架构编写 DSL 查询,并遵循规范中关于如何构造查询、命名和引用列以及使用别名的规则。
- 使用经过 Constructs 转换的不可变 VirtualTable 对象
- 每行采用以下形式:
variable = Construct(...) - 以
return <vtable>结束 - 表达式必须内联——不要使用表达式变量
- 在 Join 条件中使用
left.和right.前缀,且只能在 Join 条件中使用 - 在聚合函数和分组表达式中使用
alias
4. 通过 compile_substrait_dsl 编译
调用 compile_substrait_dsl MCP 工具并传入生成的 DSL:
compile_substrait_dsl(substrait_dsl_code="<your_dsl>", read_tables=[...])
仅当 compile_substrait_dsl 成功时才能继续。如果成功,响应中将包含 Substrait JSON——继续执行第 6 步。如果失败,则继续执行第 5 步。
5. 自行纠错(最多 3 次尝试)
发生错误时:
- 仔细阅读错误消息
- 可选:调用
get_substrait_dsl_examples,并设置collection="generation_with_error_correction",获取纠错示例 - 根据错误反馈修正 DSL
- 再次调用
compile_substrait_dsl
常见错误及修复方法:
- 找不到列:检查每次构造后的 vtable 架构——只使用现有列
- 类型不匹配:使用
cast()转换类型,或检查字面量类型 - 作用域错误:同一构造的
exprs列表中的别名无法相互引用——再串接一个 Select/Project - Join 列错误:使用
left.和right.前缀
如果 3 次尝试均失败:向用户报告最终错误,展示最后一次 DSL 尝试,并建议用户完善查询或检查表架构。
6. 执行或转换
根据用户的请求执行或转换 DSL。只有用户明确要求时,才执行该请求。
-
执行 Substrait DSL(如果用户要求运行):
有两种执行工具可用。两者都会编译 DSL 并运行生成的流程。只有在
compile_substrait_dsl验证成功后,才能调用其中任一工具。run_substrait_dsl(substrait_dsl_code="<dsl>", project_id="<project_id>", source_asset_ids=["<id1>", ...])run_substrait_dsl_static(substrait_dsl_code="<dsl>", project_id="<project_id>")如果其中一个失败,则使用另一个工具重试作为后备方案——在某些情况下,一个工具会失败,而另一个可以成功。
-
转换为 Elyra 流水线 JSON(如果用户提出此请求):
convert_substrait_dsl_to_elyra(substrait_dsl_code="<dsl>", read_tables=[...])返回
{"success": bool, "elyra_json": dict|null, "errors": str|null}。
7. 返回结果
向用户提供:
- 成功编译得到的 Substrait JSON
- 生成的 DSL 代码(以便了解过程)
输出格式
### Generated DSL
\`\`\`query
<DSL code, excluding ReadTable lines>
\`\`\`
### Substrait JSON
\`\`\`json
<substrait_json from compile_substrait_dsl>
\`\`\`
重要说明
get_substrait_dsl_examples的 user_request 参数:必须将用户完整且未经修改的消息作为user_request值传入。不要提取关键词、概括或以任何方式缩短消息。另外,始终传入collection="draft_generation"和n=5。违反此规则会导致示例不相关。- 生成任何 DSL 代码之前,必须调用
get_substrait_dsl_spec并研读规范。 该规范是所有构造、表达式、类型和作用域规则的权威参考;语法细节不能只依赖少量示例或既有知识 Select只保留列出的列;Project会保留所有列并添加新列- 聚合度量不得用
cast()包裹 - 最终输出的列名不得包含点号;请使用带别名的
Select重命名
运行时注意事项
- 可空性:资产元数据中标记为
nullable: true的任何列都必须使用可空类型后缀(例如string?、i64?)。如果将 NULL 值读入不可空字段,DataStage 会在运行时崩溃。 - 不区分大小写的筛选:筛选文本/枚举列时,使用
lower()进行不区分大小写的比较(例如equal(lower(col("status")), literal("pending", "string"))),不要假设数据使用特定大小写。 - 列消歧:联接多个表时,在联接前通过
Select预先重命名重叠列(例如,使用源自表名的前缀,将customer_id重命名为orders_customer_id)。除 Join 条件外,不要依赖left./right.前缀。