关于 visualize-semantic-model
visualize-semantic-model 可将 Cube.dev YAML 定义转换为深色有向图 PNG。它解析关联和基数、识别事实主干,并调用随附渲染器生成图表。
主要功能
- 01解析 Cube.dev YAML 定义
- 02识别事实主干和关联
- 03标注关联键及基数
- 04渲染深色 PNG 图表
- 05在对话中内嵌显示生成图像
适用场景
- 01检查 Cube 模型之间的关系
- 02查看事实与维度的连接
- 03根据 cube YAML 文件生成图表
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ revosai/ skills --skill visualize-semantic-model安装后在 Claude Code 中输入/visualize-semantic-model确认已加载。
附带文件scripts/render_graph.py
详细介绍
可视化语义模型
解析 Cube.dev 模型的 cube YAML 文件,检测事实主干,然后调用捆绑的渲染器并传入 JSON 规范,渲染深色主题的有向图。
渲染器(scripts/render_graph.py)只负责布局和绘图——它从标准输入接收图规范,并输出 PNG。将其捆绑在项目中,可确保每次运行都生成视觉风格一致的结果,也无需每次都重新编写 matplotlib 代码。
步骤 1:确定 cubes 文件夹
如果用户传入了文件夹参数,就使用该文件夹。否则,默认使用 cubes/。如果文件夹不存在,请先询问用户 cube 定义所在的位置,再继续。
find <folder> -name "*.yml" -not -name "model-graph.*" | sort
步骤 2:解析 cube 图
对于每个 .yml 文件,提取:
spec.name— 由${CUBE}和 joins 引用的 cube 标识符(metadata.name是本地 slug,通常与之相同;如果缺少spec.name,则回退使用它)spec.meta.icon— 如果存在,则为图标键(目录键、url:…或data:…);不存在时为nullspec.joins—target_cube → { relationship, sql }映射- 从每个 join 的
sql中解析出的简短 join 键标签
Join 键标签规则。 移除 ${CUBE}. 和 ${<target>}. 前缀。对于单个等式,使用左侧列名。对于复合键(包含多个 AND),将左侧列名用 + 连接。
sql: "${CUBE}.user_id = ${users}.user_id"
# → "user_id"
sql: "${CUBE}.traffic_source = ${rev}.traffic_source AND ${CUBE}.order_date = ${rev}.order_date"
# → "traffic_source + order_date"
基数(边始终从 一 侧指向 多 侧):
| 在此 cube 上声明 | 此 cube 所在一侧 | 另一个 cube 所在一侧 |
|---|---|---|
many_to_one | ∞ | 1 |
one_to_many | 1 | ∞ |
one_to_one | 1 | 1 |
事实主干检测。 拥有最多 many_to_one joins 的 cube(即持有外键的 cube)就是主干。如果数量相同,优先选择名称中包含 enriched、fact 或 items 的 cube。如果没有 cube 包含任何 many_to_one joins(例如,模型中所有关系都是从某个中心 cube 发出的 one_to_many),则回退到出向 joins 数量最多的 cube。如果仍无法确定,请询问用户应将哪个 cube 视为主干。
边界情况——停止并告知用户,不要渲染:
- 文件夹中少于 2 个 cube → 至少需要两个 cube。
- 任意位置都没有找到
joins→ 没有可绘制的关系。
步骤 3:构建图规范
构建渲染器可识别的 JSON 对象:
{
"title": "Semantic Model — <project_name>",
"fact_spine": {
"name": "<fact_cube>",
"icon": "<catalog_key_or_null>",
"pk": "<pk_col>",
"fks": ["fk_a", "fk_b", "fk_c", "fk_d"]
},
"dimensions": [
{
"name": "<dim_cube>",
"icon": "<catalog_key_or_null>",
"pk": "<pk_col>",
"extras": ["metric1", "metric2"]
}
],
"edges": [
{
"from": "<dim_cube>",
"to": "<fact_cube>",
"label": "<join_key>",
"from_card": "1",
"to_card": "∞"
}
]
}
from_card / to_card 是渲染在箭头两端的标签——"1" 或 "∞"。对于 one_to_one joins,两端都为 "1"。
icon 字段会保留在规范中,供渲染器未来支持时使用——当前的 render_graph.py 尚不绘制图标。请包含该字段,以便升级渲染器时可使用这些数据。
无论 YAML 中声明的关系方向如何,箭头始终从维度指向事实。
步骤 4:渲染
python3 -c "import matplotlib" 2>/dev/null || python3 -m pip install matplotlib --quiet
python3 .claude/skills/visualize-semantic-model/scripts/render_graph.py \
--output <folder>/model-graph.png \
<<'EOF'
{ ... the JSON spec from Step 3 ... }
EOF
如果 <folder>/model-graph.png 已存在,且用户未明确要求重新生成,请在覆盖前征求同意。
步骤 5:显示结果
对 PNG 路径使用 Read 工具(不是 Python 的 Read() 调用——Read 是 Claude Code 工具),以便在聊天中内嵌显示图像:
Read
<folder>/model-graph.png
最终回复模板
Generated: <folder>/model-graph.png
Cubes visualized: <n>
Fact spine: <cube_name>
Dimensions: <dim1>, <dim2>, ...
Edges: <dim1> → <fact> (<join_key>) [1:∞]
<dim2> → <fact> (<join_key>) [1:∞]
规则
- 始终解析 YAML——绝不对 cube 名称或关系进行硬编码。
- 边的方向始终为 维度 → 事实(箭尾位于维度一侧,箭头位于事实一侧)。
1和∞标记的位置由渲染器根据from_card/to_card确定;请根据上方的基数表正确设置。- 未经确认,不要覆盖现有的
model-graph.png。 - 保存后,始终使用 Read 工具在聊天中内嵌显示图像。