BI as Code × Gemini でダッシュボード更新ログを自動生成する
はじめに
BIダッシュボードの更新履歴管理は、多くのデータチームにとって手作業の負担が大きい課題です。本ドキュメントでは、BI as Code のアプローチと Gemini API、GitHub Actions を組み合わせて、ダッシュボードの変更ログを自動生成する仕組みについて紹介します。
背景と課題
従来の課題
ダッシュボードの変更内容を手動で記録する運用コスト
「いつ、何が変わったのか」を後から追跡できない
チームメンバーや利用者への変更通知が漏れる
ダッシュボードが増えるほど管理が破綻する
BI as Code とは
BI as Code は、ダッシュボードの定義をコード(YAML / JSON 等)として Git リポジトリで管理するアプローチです。これにより:
バージョン管理: Git タグやコミット履歴で変更を追跡
差分検出: 任意の2時点間の構造差分をプログラムで抽出可能
レビュープロセス: Pull Request ベースで変更をレビュー
多くの BI ツール(ThoughtSpot TML、Looker LookML、Tableau Pulseなど)が、ダッシュボード定義のコード化をサポートしています。
Communeの新分析画面(ThoughtSpot TML)に関する技術については、以前共有されています。
アーキテクチャ概要

処理フロー
Step 1: ダッシュボード定義の Git 管理
BI ツールのダッシュボード定義(YAML/JSON)を Git リポジトリで管理し、定期的にエクスポートしてタグを付けます。
dashboard-definitions/
├── liveboard_A.yaml
├── liveboard_B.yaml
└── ...各タグ(例: rev.20250101, rev.20250201)がある時点のダッシュボード状態のスナップショットとなります。
Step 2: 構造化された差分データの抽出
ダッシュボードの YAML 定義を、以下のようなメタデータテーブルに変換し、2つのバージョン間の差分を検出します。

差分検出では、dbt audit スタイルの比較ロジックを使います:
ここでは、dbt auditの出力形式を参考にしています。追加、削除、変更の3つのパターンを追跡し、後続のGemini処理にデータの根拠を提供しています。
def audit_compare(current_df, latest_df, primary_keys, compare_columns):
"""
2つの DataFrame を主キーでマージし、
各行を added / removed / modified / identical に分類する
"""
merged = current_df.merge(latest_df, on=primary_keys, how='outer', indicator=True)
# left_only → removed(旧バージョンにのみ存在)
# right_only → added(新バージョンにのみ存在)
# both → compare_columns の値を比較して modified / identical を判定
return diff_df
出力は CSV 形式で、各テーブルの差分データを保存します:
target/diff_data/
├── tab_master_diff.csv
├── visualization_master_diff.csv
├── filter_master_diff.csv
├── formula_master_diff.csv
├── column_master_diff.csv
└── parameter_master_diff.csvStep 3: Gemini API による更新ログの生成
差分 CSV を Gemini API に渡し、人間が読みやすい更新ログを自動生成します。
プロンプト設計のポイント
テーブルスキーマの説明を埋め込む: 各カラムの意味をプロンプトに含め、Gemini が差分の意味を正確に理解できるようにする
テーブルごとに専用テンプレートを用意: 例えば column_master の変更は table_name でグループ化して表示するなど、テーブルの性質に応じた出力を指定
低い temperature(0.3)を設定: レポートの一貫性と正確性を重視
CSV の切り詰め処理: 大量の差分データがある場合、トークン制限に収まるよう自動で切り詰め(ヘッダー行は保持)
# プロンプトテンプレートの概念例
PROMPT_TEMPLATE = """
以下は {table_name} テーブルの差分データです。
## テーブルスキーマ
{schema_description}
## 差分データ (CSV)
{diff_csv_content}
上記データを分析し、以下の3つのセクションに分けて更新ログを作成してください:
1. 追加された項目
2. 削除された項目
3. 変更された項目(変更前後の値を含む)
"""後ほどプロンプト設計のノウハウ(Prompt Design 深掘り)について詳しくご紹介しますので、皆さんのお役に立てればと思います。
サマリー生成
全テーブルの個別ログを生成した後、それらを統合して全体サマリーを生成します。
これにより、「今回のリリースで何が変わったか」を一目で把握できます。
Step 4: GitHub Actions による自動化
name: Dashboard Update Report
on:
schedule:
- cron: '0 17 * * 0' # 毎週定期実行
workflow_dispatch: # 手動実行も可能
jobs:
generate-report:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
# uv / pip 等でセットアップ
- name: Clone dashboard definitions
# BI 定義リポジトリを取得
- name: Get latest tag
run: |
LATEST_TAG=$(git tag --sort=-version:refname | head -1)
- name: Extract diff and generate report
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
# 対象ダッシュボードごとにループ
for DASHBOARD in $TARGET_DASHBOARDS; do
# 1. 現在のドキュメントからバージョンタグを取得
# 2. 差分データを抽出
python extract_diff.py \\
--dashboard "$DASHBOARD" \\
--from "$CURRENT_TAG" \\
--to "$LATEST_TAG"
# 3. Gemini で更新ログを生成
python generate_report.py \\
--dashboard "$DASHBOARD" \\
--diff-dir ./target/diff_data
done
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
commit-message: "Update dashboard changelog to ${{ env.LATEST_TAG }}"
branch: auto/update-dashboard-docs
title: "Update dashboard changelog to ${{ env.LATEST_TAG }}"
Step 5: ドキュメント管理
生成されたログは Markdown ファイルとして管理し、追記式(最新の変更が先頭)で更新します。ファイル名にバージョンタグを含めることで、現在のバージョンが一目で分かります。
docs/dashboard_docs/
├── Dashboard_A rev.20250201.md
└── Dashboard_B rev.20250201.mdドキュメントの構成:
# Dashboard_A rev.20250101 → rev.20250201
**生成日時**: 2025-02-01 10:00:00
## 更新サマリー
フィルターの追加と一部ビジュアライゼーションのチャートタイプが変更されました。
## 主な変更点
- タブ「概要」に新しいグラフが2つ追加
- 日付フィルターのデフォルト値が変更
- 計算式「成長率」のロジックが更新
## 詳細
<details>
<summary>visualization_master の変更</summary>
...
</details>
<details>
<summary>filter_master の変更</summary>
...
</details>
---
(以下、過去のバージョンの変更ログが続く)

導入のメリット

設計上の工夫
1. メタデータテーブルへの正規化
BI 定義ファイル(YAML)をそのまま diff するのではなく、意味のあるメタデータテーブルに正規化してから比較します。これにより:
YAML の構造変更(キーの順序変更等)によるノイズを排除
主キーベースの正確なマッチング
テーブルごとに適切な比較カラムを指定可能
2. dbt audit スタイルの差分検出
データエンジニアリングでよく使われる dbt audit パターンを採用。added / removed / modified / identical の4ステータスで分類し、変更の種類を明確に区別します。
3. テーブル特性に応じたプロンプト分岐
全テーブルに同じプロンプトを使うのではなく、テーブルの特性に合わせてプロンプトを変えます。例えば、カラム定義の変更はテーブル名でグループ化して表示する方が読みやすいため、専用のテンプレートを用意します。
4. CSV 切り詰めによるトークン管理
大量の差分データがある場合でも、ヘッダー行を保持しながら自動的に切り詰めることで、API のトークン制限内に収めます。
Prompt Design 深掘り
設計原則:「LLM にデータの意味を理解させる」
CSV の差分データだけを渡しても、LLM は chart_type: TREEMAP → COLUMN が何を意味するのか理解できません。
ドメイン知識をプロンプトに埋め込むことが、品質の高いレポートを生成する鍵です。
心得 1: スキーマ説明の埋め込み — コンテキストウィンドウを「辞書」として使う
各テーブルのカラム定義をプロンプトに含めることで、LLM が差分データの各フィールドの意味を正確に理解できます。
TABLE_SCHEMA_DESCRIPTIONS = {
"visualization_master": """
## ビジュアライゼーション情報
- tab_name: 所属タブ名
- visualization_name: ビジュアライゼーション名
- display_mode: 表示モード(CHART_MODE/TABLE_MODE)
- chart_type: チャートタイプ(TREEMAP/COLUMN/PIVOTなど)
- ordered_column: 使用カラムのリスト
- custom_name: カラムのカスタム表示名
- visualization_description: ビジュアライゼーションの説明文
""",
"filter_master": """
## フィルター情報
- filter_id: フィルターID
- filter_column: フィルター対象カラム
- default_values: デフォルト値のリスト
- included_visualization_names: 適用先ビジュアライゼーションのリスト
- filter_description: フィルターの説明文
""",
# ... 他テーブルも同様
}なぜ効果的か:LLM は「display_modeが CHART_MODEから TABLE_MODEに変わった」→「グラフ表示からテーブル表示に切り替わった」と、ユーザー視点での意味を推論できるようになります。
心得 2: 差分データのセマンティクスを明示する — 「audit カラム」の意味を教える
差分 CSV には dbt_audit_row_status や dbt_audit_in_a / dbt_audit_in_b といった監査用カラムが含まれます。
これらの意味をプロンプト内で明示的に説明します。
# 差分データの共通カラム説明
- dbt_audit_in_a: True の場合、旧バージョンに存在するレコード
- dbt_audit_in_b: True の場合、新バージョンに存在するレコード
- dbt_audit_row_status: 変更ステータス
- added: 新規追加されたレコード(in_a=False, in_b=True)
- removed: 削除されたレコード(in_a=True, in_b=False)
- modified: 変更されたレコード(in_a と in_b の両方に存在するが内容が異なる)心得: LLM は CSV の値だけ見ても added/ removed/ modifiedの意味を推測できますが、in_a/ in_bがどちらのバージョンを指すかは曖昧です。明示することで誤解を防ぎます。
心得 3: テーブル特性に応じたプロンプト分岐 — 「One Size Fits All」の罠を避ける
全テーブルに同一のプロンプトを使うと、出力の読みやすさが大きく低下します。
テーブルの性質に応じてプロンプトを分岐させます。
デフォルトテンプレート(tab_master, visualization_master, filter_master など):
# 出力形式
以下の形式で更新ログを作成してください:
#### 追加された項目
- (追加された内容を箇条書きで記載)
#### 削除された項目
- (削除された内容を箇条書きで記載)
#### 変更された項目
- (変更前→変更後の形式で記載)column_master 専用テンプレート(カラム変更は table_nameでグループ化が必須):
# 出力形式
**重要**: 変更内容は `table_name`(データソーステーブル名)でグループ化して記載してください。
#### テーブル別の変更一覧
##### [table_name_1]
- 追加されたカラム: column_name1, column_name2, ...
- 削除されたカラム: column_name3, ...
- 変更されたカラム: column_name4(変更内容の説明)
##### [table_name_2]
- ...なぜ分岐が必要か
column_masterでは 1 つのダッシュボードに数十〜数百のカラムが存在し、それぞれが異なるテーブルに属します。
フラットな箇条書きでは可読性が著しく低下するため、テーブル名でのグループ化が不可欠です。
def get_prompt_template_for_table(table_name: str) -> str:
"""テーブルの特性に応じたプロンプトを選択"""
if table_name == "column_master":
return get_column_master_prompt_template()
return get_default_prompt_template()心得 4: ロールの設定 — 「視点」を指定する
プロンプトの冒頭で LLM に役割を与えます:
あなたはダッシュボードの開発者です。ダッシュボードを更新した際に、
関連データに変化があることを発見しました。
以下の差分データを分析し、更新ログを作成してください。「ダッシュボード開発者」という役割を与えることで:
技術的な詳細ではなく、ユーザー影響を重視した記述になる
変更の意図を推測して補足説明を追加してくれる
心得 5: 「注意事項」セクションで出力品質をコントロール
プロンプト末尾の注意事項で、出力の方向性を微調整します:
注意事項:
- 技術的な詳細よりも、ユーザーに影響のある変更を優先して記載してください
- 変更の意図が推測できる場合は、簡潔に補足してください
- 差分データが空の場合は「変更なし」と記載してください心得: これがないと、LLM は CSV の全行を機械的に列挙しがちです。「ユーザー影響を優先」と明示することで、重要な変更をハイライトし、些末な変更は省略してくれます。
心得 6: CSV データのインジェクション対策 — <csv_data> タグで境界を明示
差分データは外部入力なので、プロンプトインジェクションのリスクがあります。XML タグで明確にデータ境界を示します:

サマリー生成のプロンプト:
全テーブルの更新ログを総括し、ダッシュボード全体の更新サマリーを作成してください。
## 出力形式
## 更新サマリー
(全体的な変更内容を2-3文で簡潔にまとめる)
## 主な変更点
- (ユーザーに影響のある重要な変更を箇条書きで記載)メリット:
各テーブルに最適なプロンプトを適用できる
トークン制限に引っかかりにくい(1テーブルずつ処理するため)
サマリー生成は既に要約済みのテキストを入力とするので、高品質な要約が得られる
心得 8: パラメーターチューニング — 正確性と創造性のバランス
TEMPERATURE = 0.3 # 低め:事実の正確な記述を重視
MAX_TOKENS = 8192 # 十分な出力長を確保
MAX_CSV_CHARS = 60000 # 入力CSV の切り詰め上限
CSV 切り詰めの実装ポイント
単純に先頭 N 文字で切るとヘッダーが欠損し、LLM がカラムの意味を理解できなくなります。
必ずヘッダー行を保持した上で、データ行を行単位で切り詰めます。
def truncate_csv_content(content: str, max_chars: int) -> str:
lines = content.split('\\n')
header = lines[0] # ヘッダー行は必ず保持
truncated = header + '\\n'
for line in lines[1:]:
if len(truncated) + len(line) > max_chars - 100: # 余裕を持たせる
break
truncated += line + '\\n'
truncated += f"\\n... (truncated, original: {len(content)} chars)"
return truncated応用可能なシナリオ
この仕組みは、BI ツールに限らず以下のようなケースにも応用できます:
Terraform の plan 結果を AI で要約し、インフラ変更の影響を通知
データベースマイグレーションの変更内容を自然言語で説明
設定ファイル(Feature Flags 等)の変更を追跡・通知
まとめ
BI as Code + Gemini + GitHub Actions の組み合わせにより、以下を実現しました:
Git タグによるダッシュボードのバージョン管理
構造化された差分抽出によるノイズのない変更検出
Gemini API による人間が読みやすい更新ログの自動生成
GitHub Actions + PR による変更通知とレビューフローの統合
この仕組みにより、ダッシュボードの変更管理にかかる手作業をほぼゼロにしつつ、利用者への透明性を向上させることができます。
最後
現時点ではまだ多くの改善点があります。プロンプトの改善を中心に、さらに深く開発を進めていくことが可能です。
ご意見がございましたら、ぜひコメントをいただき、一緒に交流できればと思います。本noteが皆さんのお役に立てれば幸いです。
We are hiring!
コミューンデータチームでは一緒に働く仲間を探しています。
