关于 create-cubes
为数据工程工作流提供的技能,可将现有 dbt gold 模型转换为 Cube.dev 语义模型 YAML,供 Cube 查询。它强调关系验证和用户确认,不负责构建 gold 模型。
主要功能
- 01发现并筛选 gold 模型
- 02分析字段、键与关联
- 03验证关联键和匹配率
- 04生成维度与度量定义
- 05按项目约定生成 Cube YAML
适用场景
- 01将 BigQuery gold 表暴露为 Cube 模型
- 02为多个模型配置并确认关联
- 03从 JSON 数组关系建立桥接模型
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ revosai/ skills --skill create-cubes安装后在 Claude Code 中输入/create-cubes确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/bq-pk-fk-conventions.mdcube-examples.mdhubspot-entities.mdjira-entities.mdkey-patterns.mdnetsuite-entities.mdstripe-entities.mdvalidation-queries.md详细介绍
创建 Cube
技能依赖
此技能将 dbt 相关知识委派给 create-dbt-transformations:
项目布局、查找 gold 模型、将 dbt 模型名称解析为 BigQuery 表引用、
从 JSON 数组创建桥接模型,以及 dbt 验证命令。
如果未安装 create-dbt-transformations:直接使用
find dbt/models/gold -name "*.sql" 查找 gold 模型,并跳过桥接模型委派。
警告用户:“未安装 create-dbt-transformations 技能 — 桥接模型创建和 dbt 验证能力有限。”
如果需要探索 BigQuery(列出表、检查架构、预览行),
则按需加载 explore-lakehouse 技能。
用途
将现有 dbt gold 模型公开为可查询的 Cube.dev 语义模型,无需手动编写 YAML 样板代码。Gold 模型可以是表或视图。
每个 cube 都是存储在 cubes/ 中的完整独立定义。不进行修补或合并——文件中的内容就是将要部署的内容。
此技能不会构建 gold 模型。如果缺少所需的 gold 模型,请交由 create-dbt-transformations 处理。
命名约定
为 cube 名称和文件名去掉 gold_ 前缀。在 sql_table(物理表)中保留 gold_。
Cube 标识符是 spec.name(Cube.dev 的 definition.name)——编译器解析的名称,也是 ${CUBE} 和关联所引用的名称。它必须是有效的 SQL/JS 标识符:snake_case(字母、数字、下划线),不能使用连字符——spec.name 中的连字符会导致编译器返回通用的 500 错误,且不提供字段级消息。必须指定 spec.name。
metadata.name 是本地 IaC slug——cubes/<name>.yml 文件名,以及其他文件引用此文件时使用的地址。它永远不会发送到 API,按照惯例使用 kebab-case(hubspot-companies),与其他所有资源的 slug 风格一致。因此,一个 cube 同时具有两种名称:kebab-case slug 和 snake_case 标识符。关联引用 snake_case 标识符(${hubspot_companies}),而不是 slug。
gold SQL file: dbt/models/gold/gold_hubspot_companies.sql
BigQuery table: gold_hubspot_companies
cube file: cubes/hubspot-companies.yml
metadata.name: hubspot-companies (local slug — kebab-case)
spec.name: hubspot_companies (cube identifier — snake_case, required)
join reference: ${hubspot_companies} (references spec.name)
sql_table: "`<dataset>.gold_hubspot_companies`"
桥接 cube 也遵循同样的规则:gold_deals_companies -> cube 名称 deals_companies,文件 cubes/deals_companies.yml。
Cube sql_table 引用
直接引用仓库中的物理表。Cube 不理解 Jinja——不要使用 dbt ref()。
使用第 2 阶段解析出的字面 dataset 值。用 BigQuery 反引号括起:
sql_table: "`<dataset>.gold_hubspot_companies`"
在 refresh_key.sql 中采用相同的完整限定格式。
用户确认节点
确认节点 1:Gold 模型选择
发现 gold 模型后,展示可用模型并询问用户希望纳入哪些模型。用户选择之前不要继续。例外:如果用户指定了某一个模型,则视为已选中。
确认节点 2a:连接模型审批
当所选模型未直接连接时,搜索其余 gold 模型,查找连接模型。展示连接路径,并在添加前征求用户同意。
确认节点 2b:桥接 / 支持模型审批
检测到多对多关系且不存在合适的桥接模型时,询问是否创建一个。如果用户同意,则委派给 create-dbt-transformations。
确认节点 3:关系确认
展示已验证的关系、关联方向、基数和匹配率。生成 cube 文件前,请用户确认。不要将未经验证的关联标记为已确认——应标记为 validation pending。
确认节点 4:度量确认
生成默认的 count 度量,建议其他度量,并请用户确认或定义自定义度量。
工作流
按顺序执行以下阶段。不要跳步。
阶段 1:发现 Gold 模型并选择范围
- 使用
find dbt/models/gold -name "*.sql"发现 Gold 模型。 - 如果没有发现任何模型,则停止,并告知用户先通过
create-dbt-transformations创建 Gold 模型。 - 检查
cubes/中 1-2 个现有 cube 文件,识别惯例(extends:、public:、refresh_key风格)。将识别出的惯例应用于新 cube。始终使用扁平的单 cube YAML(绝不使用cubes:或views:根节点)。 - 如果用户指定了某个模型,则查找该模型。如果未找到,则停止。
- 否则,列出发现的所有 Gold 模型,并询问用户希望纳入哪些模型(检查点 1)。
- 保留完整的发现列表,以供第 3 阶段搜索连接模型。
阶段 2:分析所选模型的架构和键
先解析环境变量
在生成任何 SQL 或 YAML 之前,将 $REVOS_BQ_DATASET 解析为字面值:
echo "DATASET=$REVOS_BQ_DATASET"
如果为空,则停止并请用户设置该值。在后续所有步骤中都使用这个字面值。
架构发现
检查每个所选 Gold 模型的列和类型。必要时使用 explore-lakehouse。
检查是否存在 _airbyte_extracted_at(refresh_key 所需,也是唯一要公开的 Airbyte 维度)。
键检测
检测主键、次级键、外键以及 JSON/数组键。 有关常见模式和检测规则,请参阅 references/key-patterns.md。
使用 SQL 验证主键的唯一性。请参阅 references/validation-queries.md 的第 1 节。
按照 key-patterns.md 中的格式,为每个模型输出架构摘要。
阶段 3:检测候选关系
构建候选关系图。这些仅为候选关系,必须在第 4 阶段进行验证。
单模型情况
如果只选择了一个模型,且它没有 JSON/数组关系列,则跳至第 6 阶段。如果它有 JSON/数组列,则检查是否需要桥接模型/联结模型。
关系类型和方向
使用 Cube 类型:one_to_one、one_to_many、many_to_one、many_to_many。方向始终以当前 cube 为参照。
基数规则
- 源外键可重复,目标键唯一 ->
many_to_one/ 反向为one_to_many。 - 两侧均唯一 ->
one_to_one。 - 两侧均可重复,或通过桥接模型关联 ->
many_to_many。 - 如果无法确定,则先验证再提出。
直接联接检测
查找外键到主键的匹配、次级键匹配、现有桥接模型以及 JSON/数组关系字段。
连接模型搜索
如果所选模型之间不连通:
- 在所有已发现的 Gold 模型中搜索连接路径(先搜索长度为 2 的路径,再搜索长度为 3 的路径)。
- 检查未选中的模型,仅用于发现关系——这不会将其纳入范围。
- 展示连接路径并征求用户批准(检查点 2a)。
- 如果获批,则将其纳入范围并进行完整的架构发现。如果未获批,则记录不连通的模型。
桥接模型/联结模型检测
如果在 dbt/models/gold/ 中发现现有桥接模型:
- 检查其架构,并验证它是否包含预期的键列。
- 如果符合条件,则使用该模型。如果不完全符合,则展示不匹配之处并提供选项(按原样使用、创建新的模型或中止)。
如果不存在桥接模型,且用户批准创建一个(检查点 2b),则委托给 create-dbt-transformations。创建完成后,生成一个 public: false 的桥接 cube。
第 4 阶段:验证候选关系
使用 SQL 对照 BigQuery 验证候选联接是否有效,以及方向是否正确。
对每个候选关系,验证:
- 键的唯一性
- 外键匹配率(LEFT JOIN + 匹配百分比)
- 反向聚合计数
- 桥接边完整性(两侧)
- JSON 数组提取匹配率
- 通过 INFORMATION_SCHEMA 检查类型兼容性
所有 SQL 模板请参阅 references/validation-queries.md。
尽可能验证每个候选关系的两个方向。
不要将未经验证的联接标记为已确认。如果无法运行验证,请标记为 validation pending。
第 5 阶段:呈现已验证的关系
向用户呈现所有已验证的关系:所选模型、已批准的连接器、键、具有基数信息的联接、匹配率和验证证据。
请用户确认或修改(检查点 3)。确认前不要生成文件。
如果某个关系无法验证,但用户仍决定继续,请在生成的 YAML 中为其添加 # UNVALIDATED: <reason> 标记。
第 6 阶段:生成维度
将每个选定的 gold 模型中的所有业务列公开为 Cube 维度。
主要规则:
- 包含 PK,并设置
primary_key: true。对于复合 PK,使用合成CONCAT维度 — 参见 references/cube-examples.md 中的“复合主键”部分。 - 将次级键、名称、状态、时间戳和数值属性作为维度。
- 对于
_airbyte_*列,仅将_airbyte_extracted_at作为维度airbyte_extracted_at纳入(引用为${CUBE}._airbyte_extracted_at)。排除所有其他_airbyte_*列。 - 不要仅仅因为业务列看起来暂时没有用处就将其移除。
- 用于关系的 JSON/数组列应通过桥接模型表示。
- 如果模型包含超过 50 个业务列,请在生成前询问用户。
类型映射和维度示例请参阅 references/cube-examples.md。
第 7 阶段:建议并确认度量值
- 始终包含默认的
count度量值。 - 根据列名建议有用的其他度量值。请参阅 references/cube-examples.md 中的“度量值建议”部分。
- 在 FK 所属的 Cube 中定义 FK 列上的
count_distinct,而不是在父 Cube 中定义。联接会产生扇出,从而扭曲不同计数。 - 请用户确认建议的度量值或定义自定义度量值(检查点 4)。
- 如果自定义度量值定义不明确,请要求用户澄清。
阶段 8:生成 Cube 文件
在 cubes/ 中创建 Cube.dev YAML 文件。遵循阶段 1 中识别的现有样式。
主要规则:
- 每个文件一个 cube,采用 IaC 格式。 每个 cube 文件都是单个文档:
apiVersion/kind: Cube/metadata/spec,cube 定义直接放在spec下(并将spec.name设为标识符)。不要在根级别用cubes:或views:包装。 - 文件名 =
metadata.name(kebab-case slug,不带gold_前缀)+.yml;spec.name是 snake_case 标识符。 sql_table使用带gold_前缀的完全限定 BigQuery 引用。- 每个已确认的关系都要在两个方向上添加 joins。
- 桥接/联结 cube 使用
public: false。 - 每个 cube 必须包含基于 SQL 的
refresh_key。使用SELECT MAX(<timestamp_col>),并按以下优先级选择列:_airbyte_extracted_at(所有 Airbyte 数据源都有)、updated_at/modified_at(CDC 流)、created_at(仅插入事实表)。只有当表中不存在任何时间戳列时,才将every: <interval>作为最后手段——添加 YAML 注释说明原因(例如:# no timestamp column available)。 refresh_key.sql引用的表必须与sql_table相同。- 对未经验证的 joins 添加
# UNVALIDATED: <reason>。 - 对于源自 Connection 摄取数据的 cube(即 gold 模型可追溯至通过对
Connection执行revos apply生成的 bronze 表),设置meta.abConnectionId: <connection-id>。这样可在 UI 中按来源 connection 对 cube 进行分组。使用revos connections list --json解析 connection id——根据 gold 模型读取的 bronze 表前缀与spec.prefix匹配。基于 connection 来源模型构建的桥接/联结 cube 继承相同的abConnectionId。源自纯本地数据的 cube(例如,没有上游 connection 的手写 silver/gold 模型)省略abConnectionId。 - 对于行具有自然且易读标签的 cube(公司、联系人、交易、工单、用户、项目等),设置
meta.nameDimension: <short-dimension-name>。该值是简短的维度键(不带${CUBE}.前缀,也不带 cube 名称前缀),例如:properties_name、displayName、dealname。将 cube 添加为表格时,前端会用它选择作为实体名称显示的列(参见前端中的useCubeFromMeta)。选择用户一眼就能认出是“此对象名称”的维度;如果不存在这样的单一列(纯 join/桥接 cube、事实表、事件日志),则省略nameDimension。该维度必须存在于此 cube 的dimensions:下。 - 仅在需要时设置
meta.icon——请参阅下方的**“为每个 cube 选择图标”**。 meta是封闭的:只允许使用abConnectionId、nameDimension和icon。如果这些字段都不适用,则省略整个meta块。
有关规范 cube、桥接 cube、join 方向示例和 refresh key 变体,请参阅 references/cube-examples.md。
为每个 cube 选择图标
桥接/联结 cube(public: false)始终省略 meta.icon。
对于所有其他 cube,判断是否需要 meta.icon:
-
cube 有
meta.abConnectionId——检查此 connection 背后的数据源是否有品牌图标。abConnectionId的值是 RevOS connection ID(与规则 9 中解析出的相同)。 运行revos connections get <abConnectionId> --json | jq '.spec.source.id'获取 source id, 然后运行revos sources get <source-id> --json | jq '.icon'。icon是非空字符串 → UI 会自动显示集成 Logo。省略meta.icon。icon为 null、空值或字段不存在 → 使用下方目录设置meta.icon。
-
cube 没有
meta.abConnectionId→ 始终使用下方目录设置meta.icon。
目录键
| 键 | 含义 | 典型 Cube 名称 |
|---|---|---|
users | 终端用户、客户、账户持有人 | *users*、*customers*、*accounts* |
orders | 采购订单、交易 | *orders*、*purchases*、*transactions* |
events | 行为事件、活动日志 | *events*、*activity*、*logs* |
products | 产品、SKU、商品 | *products*、*items*、*skus* |
sessions | Web/应用会话 | *sessions*、*visits* |
revenue | 收入、付款、发票 | *revenue*、*payments*、*invoices* |
companies | B2B 公司、组织 | *companies*、*organizations*、*accounts* |
contacts | 个人 / CRM 联系人 | *contacts*、*people*、*persons* |
deals | 销售交易、商机 | *deals*、*opportunities* |
tickets | 支持工单、问题 | *tickets*、*issues*、*cases* |
campaigns | 营销活动 | *campaigns*、*ads* |
emails | 电子邮件 | *emails*、*messages* |
leads | 销售线索 | *leads* |
tasks | 任务、待办事项 | *tasks*、*todos* |
三种可接受的形式
meta:
icon: "users" # catalog key (preferred)
# — or —
icon: "url:https://cdn.example.com/icon.svg" # explicit external URL
# — or —
icon: "data:image/svg+xml;base64,…" # inline SVG data URI
尽可能使用目录键。只有目录未涵盖的自定义品牌图标才使用 url: 或 data:。
格式错误的值会导致 revos apply 拒绝文件,并显示明确的错误。
阶段 9:验证生成的文件
- 如果已调用
create-dbt-transformations(桥接模型),它已验证 dbt 模型。否则运行dbt parse。 - 验证 BigQuery 中的物理表是否存在:
bq show <dataset>.<table_name>。如果不存在,请记录为待处理。 - 验证生成的 Cube 文件是否符合规范:扁平 YAML、命名正确、
sql_table正确、包含所有维度、包含refresh_key,并且连接关系是双向的。
最终回复格式
Created cube definitions.
Selected gold models:
- dbt/models/gold/<gold_model_1>.sql
Approved connector models:
- dbt/models/gold/<connector_model>.sql
Bridge/support models created (via create-dbt-transformations):
- dbt/models/gold/<bridge_model>.sql
Cube files:
- cubes/<entity_1>.yml (cube name: <entity_1>)
- cubes/<bridge_entity>.yml (cube name: <bridge_entity>, public: false)
Validated relationships:
- <entity_a>.<key> -> <entity_b>.<key> (<relationship_type>)
Measures:
- count
- <approved_measure_1>
Validation:
- dbt: <passed / pending / not run>
- physical tables: <passed / pending>
- join validation: <passed / pending>
- semantic validation: <passed / pending>
Unvalidated joins (tagged with # UNVALIDATED):
- <cube>.<join_target>: <reason>
Assumptions:
- <assumption>
Pending items:
- <pending_item>
Next step:
revos apply
如果验证尚未完成,请准确说明还有哪些事项待处理。