mcpField
P
powerbi-to-sl

powerbi-to-sl

github.com/keboolaデータ・データベース17173 回インストール1 日前に更新
リポジトリ

powerbi-to-sl について

powerbi-to-slは、既存のPower BIアーティファクトをKeboola Semantic Layer用のJSONペイロードに移行するスキルです。既存モデルを移行するチーム向けで、構造を機械的に対応付け、DAXをレビュー用に保持し、確認後のプッシュに対応します。

主な機能

  1. 01TMDLとテーブル別JSONの入力を判定
  2. 02テーブル、メジャー、リレーションを対応付け
  3. 03DAX式を保持し警告を提示
  4. 04JSON Schemaで出力を検証
  5. 05確認後のプッシュまたはsl-toolkitへの引き継ぎ

活用シーン

  1. 01Power BIモデルをKeboola SLへ移行
  2. 02SQL書き換え前にDAXメジャーを確認
  3. 03セマンティックレイヤーのペイロードを作成・検証

MCP 対応

必要に応じてMicrosoft Power BI Modeling MCPの読み取り専用モードでTMDLを生成できます。公開処理をsl-toolkitに引き継ぐこともできます。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/keboola/ai-kit --skill powerbi-to-sl

インストール後、Claude Code で/powerbi-to-slを入力して読み込まれたか確認します。

詳細

powerbi-to-sl — Power BI → Keboola Semantic Layer の移行

既存の PowerBI アーティファクトを読み込み → Keboola SL のペイロードにマッピング → JSON ファイルに書き込み → ユーザーが確認 → sl-toolkit または直接 REST 経由でプッシュします。sl-toolkit(グリーンフィールド)の補完ツールであり、こちらはブラウンフィールド向けの方法です。


ステップ 0 — 入力を特定する

PowerBI アーティファクトの場所をユーザーに尋ねてから、形式を自動検出します。

INPUT_DIR="$(read -p 'Path to PowerBI artifacts: ' x; echo "$x")"
python3 -c "
import os, sys
p = sys.argv[1]
tmdl = [f for f in os.listdir(p) if f.endswith('.tmdl')] if os.path.isdir(p) else []
jsons = [f for f in os.listdir(p) if f.endswith('_semantic_layer.json')] if os.path.isdir(p) else []
if tmdl: print('tmdl')
elif jsons: print('per-table-json')
else: print('unknown')
" "$INPUT_DIR"

unknown の場合は、ユーザーに確認を求めるか、Microsoft の Power BI Modeling MCP を --readonly でデータセットに対して実行し、まず TMDL を生成してもらいます。


ステップ 1 — ビジネス上の質問(マッピングの前に確認)

「簡単な質問が 3 つあります。

  1. これらのテーブルに使用する Keboola バケットのプレフィックスは何ですか?(例: in.c-pbi-migration — 各 semantic-dataset の tableId の構築に使用します)
  2. セマンティックモデル名と表示名は何ですか?(例: acme-pbi-migration / "Acme Power BI Migration")
  3. Snowflake と BigQuery のどちらの方言を使用しますか?(デフォルト:Snowflake)」

回答を BUCKET_PREFIX、MODEL_NAME、MODEL_DISPLAY、DIALECT として保存します。


ステップ 2 — マイグレーターを実行する

python3 scripts/migrate.py \
  --input "$INPUT_DIR" \
  --input-format "$FORMAT" \
  --bucket-prefix "$BUCKET_PREFIX" \
  --model-name "$MODEL_NAME" \
  --model-display "$MODEL_DISPLAY" \
  --dialect "$DIALECT" \
  --output ./out/

出力レイアウト:

out/
  semantic-model.json
  semantic-dataset/
    <bucket-prefix>.<table>.json   # one per PowerBI table
  semantic-metric/
    <measure-slug>.json            # one per PowerBI measure
  semantic-relationship/
    <from>__<to>.json              # one per PowerBI relationship
  WARNINGS.md                      # DAX-not-translated, unmapped types, etc.

ステップ 3 — ユーザーと WARNINGS.md を確認する

マイグレーターは DAX メジャー式を semantic-metric.sql にそのまま保持します。ユーザーに WARNINGS.md を見せ、次のどれにするか尋ねます。

  • 後回しにする — DAX はそのままにし、後続の Kai(または人間)が必要に応じて SQL に書き換えます。
  • 簡単なケースを自動翻訳する — SUM('Table'[Col]) → SUM("Table"."Col")、 COUNT、DISTINCTCOUNT、AVERAGE。CALCULATE、フィルターコンテキスト、 RELATED、時間インテリジェンス、または変数を含むものには引き続きフラグを付けます。
  • 人手で対応する — WARNINGS のリストを開き、1 行ずつ書き換えます。

デフォルト:後回しにしてリストを表示します。簡単なケースの翻訳はオプトインです。


ステップ 4 — Keboola SL スキーマに対して検証する(jsonschema)

python3 -c "
import json, jsonschema, glob, sys, os
schemas_dir = os.environ['SCHEMAS_DIR']
schemas = {
    name: json.load(open(f'{schemas_dir}/semantic-{name}_schema_1.0.0.json'))
    for name in ['model','dataset','metric','relationship']
}
errs = 0
for kind, schema in schemas.items():
    pattern = './out/semantic-model.json' if kind == 'model' else f'./out/semantic-{kind}/*.json'
    for f in glob.glob(pattern):
        try:
            jsonschema.validate(json.load(open(f)), schema)
        except jsonschema.ValidationError as e:
            errs += 1
            print(f'❌ {f}: {e.message}')
print(f'{errs} validation errors' if errs else '✅ all valid')
"

同じ検証は tests/test_smoke.py の pytest アサーションとしても実行されます。Keboola metastore の semantic-* JSON スキーマを含むディレクトリを SCHEMAS_DIR に設定してください。


ステップ 5 — プッシュする(任意、ユーザーの確認後に実行)

書き込みを行う前に、必ずユーザーに確認します。方法は 2 つあります。

方法 A — sl-toolkit 経由(そのプラグインがインストールされている場合に推奨。標準的な生成–検証–プッシュのパイプラインを担います):

「sl-toolkit に引き継ぎますか? SL モデルの標準的なプッシュパイプラインを担います。それとも、メタストアの REST API に直接プッシュしますか?」

sl-toolkit が選択された場合は、--source ./out/ を指定して、そのプッシュステップを実行します。

方法 B — 直接 REST(sl-toolkit が利用できない場合):

import json, os, urllib.request, glob
from concurrent.futures import ThreadPoolExecutor
TOKEN = os.environ['KBC_STORAGE_TOKEN']
METASTORE = os.environ['KBC_METASTORE_URL']  # e.g. https://metastore.us-east4.gcp.keboola.com

def post(kind, payload):
    req = urllib.request.Request(
        f'{METASTORE}/api/v1/repository/semantic-{kind}',
        data=json.dumps(payload).encode(),
        headers={'X-StorageAPI-Token': TOKEN, 'Content-Type': 'application/json'},
        method='POST')
    return urllib.request.urlopen(req, timeout=30).read()

# Model first — get the UUID, propagate to children
model_uuid = json.loads(post('model', json.load(open('./out/semantic-model.json'))))['data']['id']
for kind in ['dataset','metric','relationship']:
    payloads = []
    for f in glob.glob(f'./out/semantic-{kind}/*.json'):
        p = json.load(open(f))
        p['modelUUID'] = model_uuid
        payloads.append(p)
    with ThreadPoolExecutor(max_workers=10) as ex:
        list(ex.map(lambda p: post(kind, p), payloads))

マッピングの参照

Power BIKeboola SL
tables[].namesemantic-dataset.name + tableId
tables[].descriptionsemantic-dataset.description
tables[].columns[].namesemantic-dataset.fields[].name
tables[].columns[].dataTypesemantic-dataset.fields[].type *
tables[].columns[].descriptionsemantic-dataset.fields[].description
主キー列のヒントsemantic-dataset.primaryKey
tables[].measures[].expression (DAX)semantic-metric.sql(そのまま)
tables[].measures[].descriptionsemantic-metric.description
relationships[]semantic-relationship

型のマッピング: string→string、int64/integer→integer、 double/decimal/currency→decimal、dateTime/date→datetime/date、 boolean→boolean。不明な型は string にフォールバックし、ログに記録されます。


既知の注意点

  • テーブルごとの JSON では Power Query M のステップが失われます。 以前の get_semantic_model の出力では M 式を取得できません。完全な 忠実性が必要な場合は、Microsoft の Power BI Modeling MCP を --readonly フラグ付きで再実行して TMDL を生成してください。TMDL では DAX と M がネイティブに取得されます。
  • DAX ≠ SQL です。 デフォルトではそのまま保持し、後続の Kai または 人間が変換します。CALCULATE、RELATED、時系列分析、変数は 単純な変換では維持できません。
  • PowerBI のテーブル名には空白や非 ASCII 文字が含まれます。 ファイル名にはスラッグ化した名前を使い、name/displayName には元の名前を保持してください。UTF-8 のパスは macOS/Linux では問題ありませんが、ファイルシステムに癖のある環境では注意してください。
  • PK の検出はベストエフォートです。 Power BI では PK が明示的にマークされていないことがあります。マイグレーターは、(a)TMDL の明示的な isKey マーカー、(b)ヒューリスティックとしてのリレーションシップの to 列、(c)空の primaryKey とユーザーに選択を求める WARNINGS エントリへのフォールバック、を使用します。
  • リレーションシップのカーディナリティ。 manyToOne と oneToOne → inner、 oneToMany → 「多」側からの left です。manyToMany の場合は WARNINGS エントリが生成されます。SL モデルはスター・スキーマとの親和性を想定しています。

2 つのスキルが存在する理由(powerbi-to-sl と sl-toolkit)

観点sl-toolkitpowerbi-to-sl(このスキル)
方向新規構築(Keboola のテーブル → SL)既存環境(Power BI → SL)
入力Keboola ストレージ + SQL 変換TMDL フォルダーまたはテーブルごとの JSON
生成スキーマ + KPI に基づく LLM 主導構造を機械的に変換
検証自動修正 + LLM による批評jsonschema による検証 + WARNINGS
プッシュプッシュパイプラインを管理プッシュを sl-toolkit に引き継ぐ

両方がインストールされている場合、このスキルは SL ペイロードを生成し、プッシュを sl-toolkit に委任します。重複ではなく、再利用です。

コメント