mcpField
A
answering-natural-language-questions-with-dbt

answering-natural-language-questions-with-dbt

github.com/dbt-labs数据与数据库7471.0k 次安装1 周前更新
代码仓库

关于 answering-natural-language-questions-with-dbt

用于借助 dbt 回答业务数据问题的技能,优先使用语义层,并按需转向 SQL、模型发现或本地工件分析。它根据可用工具引导分析流程,并将开发和模型测试任务排除在数据问答之外。

主要功能

  1. 01通过语义层查询指标
  2. 02按需调整编译后的指标 SQL
  3. 03发现模型并检查模型详情
  4. 04分析 manifest 和 catalog 工件
  5. 05优先使用集市模型而非暂存模型

适用场景

  1. 01回答销售额或客户相关问题
  2. 02按筛选条件或维度查询指标
  3. 03没有语义层时探索模型
  4. 04根据本地 dbt 工件编写 SQL

MCP 相关

该技能描述了使用 list_metrics、query_metrics、get_model_details 和 execute_sql 等可用 MCP 工具的流程。没有 MCP 服务时,可分析本地 manifest 和 catalog 工件。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dbt-labs/dbt-agent-skills --skill answering-natural-language-questions-with-dbt

安装后在 Claude Code 中输入/answering-natural-language-questions-with-dbt确认已加载。

详细介绍

使用 dbt 回答自然语言问题

概述

使用当前最佳方法回答数据问题:优先使用语义层,然后修改 SQL,再发现模型,最后分析清单。始终穷尽所有选项,再说“无法回答”。

适用于: 用户提出的需要数据答案的业务问题

  • “上个月的总销售额是多少?”
  • “我们有多少活跃客户?”
  • “按地区显示收入”

不适用于:

  • 开发期间验证模型逻辑
  • 测试 dbt 模型或语义层定义
  • 构建或修改 dbt 模型
  • dbt run、dbt test 或 dbt build 工作流

决策流程

flowchart TD
    start([Business question received])
    check_sl{Semantic layer tools available?}
    list_metrics[list_metrics]
    metric_exists{Relevant metric exists?}
    get_dims[get_dimensions]
    sl_sufficient{SL can answer directly?}
    query_metrics[query_metrics]
    answer([Return answer])
    try_compiled[get_metrics_compiled_sql<br/>Modify SQL, execute_sql]
    check_discovery{Model discovery tools available?}
    try_discovery[get_mart_models<br/>get_model_details<br/>Write SQL, execute]
    check_manifest{In dbt project?}
    try_manifest[Analyze manifest/catalog<br/>Write SQL]
    cannot([Cannot answer])
    suggest{In dbt project?}
    improvements[Suggest semantic layer changes]
    done([Done])

    start --> check_sl
    check_sl -->|yes| list_metrics
    check_sl -->|no| check_discovery
    list_metrics --> metric_exists
    metric_exists -->|yes| get_dims
    metric_exists -->|no| check_discovery
    get_dims --> sl_sufficient
    sl_sufficient -->|yes| query_metrics
    sl_sufficient -->|no| try_compiled
    query_metrics --> answer
    try_compiled -->|success| answer
    try_compiled -->|fail| check_discovery
    check_discovery -->|yes| try_discovery
    check_discovery -->|no| check_manifest
    try_discovery -->|success| answer
    try_discovery -->|fail| check_manifest
    check_manifest -->|yes| try_manifest
    check_manifest -->|no| cannot
    try_manifest -->|SQL ready| answer
    answer --> suggest
    cannot --> done
    suggest -->|yes| improvements
    suggest -->|no| done
    improvements --> done

快速参考

优先级条件方法工具
1语义层已启用直接查询指标list_metrics、get_dimensions、query_metrics
2语义层已启用,但需要少量修改(缺少维度、自定义筛选、case when、不同的聚合方式)修改编译后的 SQLget_metrics_compiled_sql,然后使用 execute_sql
3没有语义层,发现工具已启用探索模型并编写 SQLget_mart_models、get_model_details,然后使用 show/execute_sql
4没有 MCP,位于 dbt 项目中分析构件并编写 SQL读取 target/manifest.json、target/catalog.json

方法 1:查询语义层

当 list_metrics 和 query_metrics 可用时:

  1. list_metrics - 查找相关指标
  2. get_dimensions - 确认所需维度存在
  3. query_metrics - 使用适当的筛选条件执行查询

如果语义层无法直接回答(缺少维度、需要自定义逻辑)→ 转到方法 2。

方法 2:修改编译后的 SQL

当语义层中已有该指标,但需要少量修改时:

  • 缺少维度(join + group by)
  • 自定义筛选条件无法作为维度使用
  • 用于自定义分类的 case when 逻辑
  • 与定义不同的聚合方式
  1. get_metrics_compiled_sql - 获取将要运行的 SQL(返回原始 SQL,而非 Jinja)
  2. 修改 SQL,补充所需内容
  3. 使用 execute_sql 运行原始 SQL
  4. 始终建议:如果该修改可复用,则更新语义模型
-- Example: Adding sales_rep dimension
WITH base AS (
    -- ... compiled metric logic (already resolved to table names) ...
)
SELECT base.*, reps.sales_rep_name
FROM base
JOIN analytics.dim_sales_reps reps ON base.rep_id = reps.id
GROUP BY ...

-- Example: Custom filter
SELECT * FROM (compiled_metric_sql) WHERE region = 'EMEA'

-- Example: Case when categorization
SELECT
    CASE WHEN amount > 1000 THEN 'large' ELSE 'small' END as deal_size,
    SUM(amount)
FROM (compiled_metric_sql)
GROUP BY 1

注意: 编译后的 SQL 包含解析完成的表名,而不是 {{ ref() }}。请直接使用返回的原始 SQL。

方法 3:发现模型

当没有语义层,但 get_all_models/get_model_details 可用时:

  1. get_mart_models - 从集市模型开始,而不是暂存模型
  2. 对相关模型使用 get_model_details - 了解架构
  3. 使用 {{ ref('model_name') }} 编写 SQL
  4. 使用 show --inline "..." 或 execute_sql

优先选择集市模型,而非暂存模型 - 集市模型已应用业务逻辑。

方法 4:分析清单/目录

当位于 dbt 项目中,但没有 MCP 服务时:

  1. 检查是否存在 target/manifest.json 和 target/catalog.json
  2. 先筛选,再读取 - 这些文件可能很大
# Find mart models in manifest
jq '.nodes | to_entries | map(select(.key | startswith("model.") and contains("mart"))) | .[].value | {name: .name, schema: .schema, columns: .columns}' target/manifest.json

# Get column info from catalog
jq '.nodes["model.project_name.model_name"].columns' target/catalog.json
  1. 根据发现的架构编写 SQL
  2. 说明:“这段 SQL 应可在你的数据仓库中运行。由于我无法访问数据库,因此无法执行它。”

建议改进

位于 dbt 项目中时,回答后(或无法回答时)建议修改语义层:

缺口建议
指标不存在“向语义模型添加指标定义”
缺少维度“将 dimension_name 添加到语义模型的维度列表中”
没有语义层“考虑为这些数据添加语义层”

建议仅限于语义层级别。 不要建议:

  • 修改数据库架构
  • 修改 ETL 流水线
  • “请数据工程团队帮忙……”

需要抵制的自我说服

你的想法……实际情况
“语义层不支持这个确切的查询”获取编译后的 SQL 并修改它(方法 2)
“没有 MCP 工具,帮不上忙”检查本地是否有清单或目录
“用户急需结果,跳过系统性检查”系统性方法才是最快的途径
“直接写 SQL 更快”语义层存在自有其道理——优先使用它
“数据中不存在这个维度”它可能存在,只是未配置在语义层中

危险信号——立即停止

  • 未检查语义层能否回答,就编写 SQL
  • 未尝试全部 4 种方法,就声称“无法回答”
  • 针对语义层缺口提出数据库层面的修复方案
  • 未经筛选就读取整个 manifest.json
  • 在存在 mart 模型时使用 staging 模型
  • 用这种方式验证模型是否正确,而不是回答业务问题

常见错误

错误修正方法
语义层(SL)无法直接回答时就放弃获取编译后的 SQL 并修改它
查询 staging 模型先使用 get_mart_models
读取完整的 manifest.json使用 jq 进行筛选
建议修改 ETL将建议限定在语义层
未检查工具是否可用先列出可用工具,再选择方法

评论

支持 Markdown