はじめに
同じDWHから 「人が見る用のマート」 と 「AIが読む用のマート」 を分岐させたら、ダッシュボードの使い方がだいぶ変わった。
人用のダッシュボードで全体を掴んで、LLMで深堀りする。この2つの出力を並べると、片方だけでは見えなかった示唆が出てくる。
デモデータには UCI Online Retail Dataset(英国ECサイト、約54万件)を使った。
アプリそのものを公開する予定はないので、本記事では設計の考え方と、AIライクな開発プロセスで何が変わったかを共有する。
メタデータ設計
従来、テーブル定義書はExcelやConfluenceに書いて人が参照するものだった。今回はこれを LLMが読む入力データ として扱った。
# config/metadata.yaml
tables:
raw_transactions:
description: "EC小売サイトの全取引データ(生データ)"
columns:
invoice_no:
type: "VARCHAR"
description: "請求書番号。6桁の一意な取引識別子。先頭が'C'の場合はキャンセル取引"
role: "identifier"
quantity:
type: "INTEGER"
description: "取引あたりの商品数量。マイナスはキャンセルまたは返品"
role: "measure"
customer_id:
type: "VARCHAR"
description: "顧客ID。5桁の一意な顧客識別子。NULLの場合は未登録顧客"
role: "identifier"
descriptionに業務知識を埋め込み、roleで分析上の役割を明示する。YAMLなのでGitで管理できる。
こうしておくと、メタデータがドキュメントではなくパイプラインの「入力」になる。以降のステップは基本的にここが起点になっている。
人用マートとAI用マート
人用: mart_human_monthly_sales
正常な取引だけを対象にした、月別・国別の売上サマリーである。
SELECT
TO_CHAR(invoice_date, 'YYYY-MM') AS year_month,
country,
SUM(quantity * unit_price) AS total_revenue,
COUNT(DISTINCT invoice_no) AS total_orders,
COUNT(DISTINCT customer_id) AS total_customers,
SUM(quantity * unit_price)
/ NULLIF(COUNT(DISTINCT invoice_no), 0) AS avg_order_value
FROM raw_transactions
WHERE invoice_no NOT LIKE 'C%'
AND quantity > 0 AND unit_price > 0
GROUP BY year_month, country;
人がグラフで傾向を掴むための設計である。
AI用: mart_ai_enriched
LLMに渡して示唆を出すためのマートである。派生指標を事前に計算して1テーブルに集約した。
| 追加カラム | 意図 |
|---|---|
prev_month_revenue / revenue_change_pct
|
LLMに前月比を計算させると精度が落ちやすいので事前計算 |
cancel_orders / cancel_rate_pct
|
人用マートでは除外したキャンセルデータ |
top_customer_revenue_pct |
上位1顧客の売上構成比 |
unique_products |
商品ポートフォリオの変化検出 |
人用マートに cancel_rate_pct のような指標を入れてもグラフが増えるだけで活用されにくい。AI用マートはLLMがパターンを検出するための入力データとして割り切った。
ズレの検知
人用ダッシュボードで見えるのは、月別売上推移やKPI(総売上£10.6M / 総注文19,960件 / 総顧客13,058人)、国別構成比といった全体像である。
AI用マートをLLMに渡すと、BIだけでは気づきにくいパターンが出てきた。
オランダの収益が"ほぼ1顧客"に依存
2011年1月〜8月の各月でtop_customer_revenue_pctが97〜100%。売上推移グラフでは「売上がある」としか見えないが、構造的には単一顧客依存だった。
キャンセル率と売上の逆相関
スイス: 2011年8月にcancel_rate=62.5%。ドイツ・ポルトガルは慢性的にキャンセル率が高い。BIの売上グラフからは読み取れない。
フィンランドの商品ポートフォリオ急変動
ユニーク商品数が12→210→37と月単位で乱高下していた。
人の目とLLMの示唆を並べると、こういうズレが見える。
| Streamlit(人の目) | LLM(AIの示唆) |
|---|---|
| 「オランダは安定して売上がある」 | 「97%が1顧客依存」 |
| 「12月に売上急落」 | 「キャンセル率が28.6%に急騰」 |
| 「フィンランドは売上が小さい」 | 「商品数12→210→37で戦略がブレてる」 |
BIが「何が起きたか」を見せて、LLMが「なぜ」「何が隠れているか」を拾ってくる。この組み合わせは思った以上に相性が良かった。
プロンプト設計
示唆出しのプロンプトはYAMLで管理した。
# prompts/insight_template.yaml
templates:
monthly_insight:
system: |
あなたはデータアナリストです。
与えられたデータからビジネス上の示唆を日本語で出してください。
- 数値の根拠を必ず示す
- 「異常値」「トレンド変化」「リスク」の3カテゴリで整理
- 各カテゴリ最大3項目
- 示唆ごとに確信度(高/中/低)を付ける
user: |
## メタデータ(各カラムの意味)
{metadata}
## データ
{data}
LLMにはメタデータとデータを両方渡している。メタデータがあると cancel_rate_pct のようなカラムの意味をLLMが正しく解釈してくれる。
開発プロセス
ここが今回やってみて一番よかったところである。
Streamlit agent skills × Claude Code
Streamlitには公式でAgent skillsが配信されており、AIコーディングエージェントがStreamlitアプリの構造を認識・操作できる。https://github.com/streamlit/agent-skills
これとClaude Codeを組み合わせると、以下の流れが1セッションで回る。
metadata.yamlを読ませればマートのスキーマを理解した上でStreamlitコードを生成してくれるし、「キャンセル率の推移をもっと目立たせて」と言えばレイアウトも変わる。メタデータがAIに読める形式で存在するので、ダッシュボードの生成・修正をそのまま任せられた。
Playwright CLIによるGUI検証の自動化
以前はStreamlit上でダッシュボードの表示を手動で確認していた。グラフが正しく出ているか、データが欠落していないか、レイアウトが崩れていないか。地味に手間がかかる作業である。
Playwright CLI を使うと、これがCLI上で自律的にできるようになった。GUIベースのアプリケーションであっても、CLI経由でページの状態を取得してAIに渡せる。
# ページのスクリーンショットを取得
playwright screenshot http://localhost:8501 dashboard.png
# アクセシビリティツリーを取得
playwright pdf http://localhost:8501 dashboard.pdf
Claude Codeがこれを読んで、バグがあれば自分でコードを修正し、再度検証する。このサイクルが自動で回るのが大きかった。
人がブラウザを開いて目視する工程がなくなった。GUIの検証をCLIで完結できるのは、AIエージェントとの相性がとても良い。
開発サイクルの全体像
メタデータの変更を起点に、この一連の流れがかなり自律的に回った。
従来との違い
今回の開発を通して感じた違いを整理した。
| 観点 | 従来 | 今回 |
|---|---|---|
| メタデータ | Excel/Confluenceのドキュメント | YAMLでGit管理。パイプラインの入力 |
| マート設計 | 汎用マートを1つ | 人用とAI用で目的別に分岐 |
| 深堀り | 人がSQLを書く | LLMが網羅的にスキャンして示唆 |
| ダッシュボード変更 | エンジニアに依頼→開発→デプロイ | agent skills経由で対話的に変更 |
| プロンプト | (存在しない) | YAMLテンプレートで管理 |
| GUI検証 | ブラウザで目視確認 | Playwright CLIでAIが自律検証・自動修正 |
| 開発サイクル | 人が各ステップを実行 | メタデータ起点で自律的に回る |
構成
ai-data-pipeline/
├── config/
│ └── metadata.yaml ← AIが読むメタデータ
├── prompts/
│ └── insight_template.yaml ← 示唆出し用プロンプトテンプレート
├── scripts/
│ ├── 01_fetch_data.py ← データ取得 → PostgreSQL(DWH)
│ ├── 02_create_marts.py ← DWH → 人用マート + AI用マート
│ └── 03_generate_insights.py ← AI用マート → LLM示唆
├── streamlit_app/
│ └── app.py ← 人用BIダッシュボード
└── requirements.txt
おわりに
メタデータをAIの入力として設計し直したことで、こういう流れができた。
- 人用マートとAI用マートを分岐させる
- 人が全体を見て、LLMが深堀りする
- 両者のズレから示唆が生まれる
- Streamlit agent skills × Claude Code でダッシュボードの生成・修正が回る
- Playwright CLI でGUI検証から自動修正まで自律的に完結する
ダッシュボードが「見るだけのもの」から「対話で動かすもの」に近づいた感触がある。その起点はメタデータの設計だった。
