exploring-llm-clusters について
LLMトレース、生成、評価のクラスタを調査するPostHogスキルです。オブザーバビリティを扱うユーザーが利用パターンや指標を比較し、代表的なトレースを詳しく確認できます。
主な機能
- 01クラスタリングジョブと実行履歴の一覧
- 02トレース・生成・評価クラスタの確認
- 03コスト・レイテンシ・トークン・エラー指標の算出
- 04代表的なトレースの確認
- 05実行間のクラスタ比較
活用シーン
- 01LLMトラフィックの傾向把握
- 02コストやレイテンシが高いクラスタの特定
- 03エラーが多いクラスタの調査
- 04期間ごとのクラスタ傾向の比較
MCP 対応
PostHog MCPツールを使い、クラスタリングジョブの一覧表示、SQLによるクラスタイベントの検索、LLMトレースの確認を行います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ skills --skill exploring-llm-clustersインストール後、Claude Code で/exploring-llm-clustersを入力して読み込まれたか確認します。
同梱ファイルscripts/print_clusters.py
詳細
LLM クラスターの調査
AI オブザーバビリティのクラスターを調査する際にこのスキルを使用します。 AI/LLM トラフィックにどのようなパターンがあるかを把握し、 クラスターの動作を比較して、個々のクラスターを詳しく調べます。
ツール
| ツール | 目的 |
|---|---|
posthog:llma-clustering-job-list | チームのクラスタリングジョブ設定の一覧を取得する |
posthog:llma-clustering-job-get | ID を指定してクラスタリングジョブを取得する |
posthog:execute-sql | クラスター実行イベントをクエリし、メトリクスを算出する |
posthog:query-llm-traces-list | クラスターに属するトレースを検索する |
posthog:query-llm-trace | 特定のトレースの詳細を調べる |
クラスタリングの仕組み
PostHog は、埋め込みの類似度に基づいて LLM トレース、個々の生成、または評価イベントをクラスター化します。
Temporal ワークフローが定期的またはオンデマンドで実行され、クラスターイベントを生成します。イベントは
$ai_trace_clusters(トレースレベル)、$ai_generation_clusters(生成レベル)、または
$ai_evaluation_clusters(評価レベル)として保存されます。
各クラスターイベントには以下が含まれます。
$ai_clustering_run_id— 一意の実行 ID(形式:<team_id>_<level>_<YYYYMMDD>_<HHMMSS>[_<job_id>])$ai_clustering_level—"trace"、"generation"、または"evaluation"$ai_window_start/$ai_window_end— 分析対象データの時間範囲$ai_total_items_analyzed— 処理されたトレース、生成、または評価の数$ai_clusters— クラスターオブジェクトの JSON 配列$ai_clustering_params— 使用されたアルゴリズムのパラメーター
分析対象の時間範囲は実行開始時に終了し、クラスターイベントは実行完了後に生成されます。
そのため、クラスターイベント自体のtimestampは、数秒から数時間後まで、常に$ai_window_endより後になります。
分析されたトレース、生成、評価を絞り込む場合にのみ、この時間範囲を使用してください。
クラスターイベント自体を見つけるには、最近の時間範囲を指定して$ai_clustering_run_idで絞り込みます。
クラスターオブジェクトの形式($ai_clusters内)
{
"cluster_id": 0,
"size": 42,
"title": "User authentication flows",
"description": "Traces involving login, signup, and token refresh operations",
"traces": {
"<trace_or_generation_id>": {
"distance_to_centroid": 0.123,
"rank": 0,
"x": -2.34,
"y": 1.56,
"timestamp": "2026-03-28T10:00:00Z",
"trace_id": "abc-123",
"generation_id": "gen-456"
}
},
"centroid_x": -2.1,
"centroid_y": 1.4
}
cluster_id: -1はノイズ/外れ値クラスターです(どのクラスターにも適合しなかったアイテム)traces内のアイテムは、トレース ID(トレースレベル)、生成イベント UUID(生成レベル)、または評価イベント UUID(評価レベル)をキーとしますrankは重心への近さでアイテムを並べます(0 = 最も近い)x、yは可視化用の2次元座標です(UMAP/PCA/t-SNEで次元削減)
クラスタリングジョブ
各チームは最大10件のクラスタリングジョブを設定できます。ジョブでは以下を定義します。
- name — 人が読みやすいラベル
- analysis_level —
"trace"、"generation"、または"evaluation" - event_filters — 対象に含めるアイテムを絞り込むプロパティフィルター
- enabled — ジョブをスケジュールに従って実行するかどうか
"Default - traces"、"Default - generations"、"Default - evaluations"という名前のデフォルトジョブは自動作成されます。
同じレベルのカスタムジョブを作成すると、デフォルトジョブは無効になります。
ワークフロー:クラスターを調べる
ステップ1 — 最近のクラスタリング実行を一覧表示する
posthog:execute-sql
SELECT
toString(properties.$ai_clustering_run_id) AS run_id,
toString(properties.$ai_clustering_level) AS level,
toString(properties.$ai_clustering_job_id) AS job_id,
toString(properties.$ai_clustering_job_name) AS job_name,
toString(properties.$ai_window_start) AS window_start,
toString(properties.$ai_window_end) AS window_end,
toFloat64OrNull(toString(properties.$ai_total_items_analyzed)) AS total_items,
timestamp
FROM events
WHERE event IN ('$ai_trace_clusters', '$ai_generation_clusters', '$ai_evaluation_clusters')
AND timestamp >= now() - INTERVAL 14 DAY
ORDER BY timestamp DESC
LIMIT 10
ステップ2 — 特定の実行からクラスターを取得する
posthog:execute-sql
SELECT
toString(properties.$ai_clustering_run_id) AS run_id,
toString(properties.$ai_clustering_level) AS level,
toString(properties.$ai_clustering_job_id) AS job_id,
toString(properties.$ai_clustering_job_name) AS job_name,
toString(properties.$ai_window_start) AS window_start,
toString(properties.$ai_window_end) AS window_end,
toFloat64OrNull(toString(properties.$ai_total_items_analyzed)) AS total_items,
properties.$ai_clusters AS clusters,
properties.$ai_clustering_params AS params,
timestamp
FROM events
WHERE event IN ('$ai_trace_clusters', '$ai_generation_clusters', '$ai_evaluation_clusters')
AND timestamp >= now() - INTERVAL 14 DAY
AND toString(properties.$ai_clustering_run_id) = '<run_id>'
ORDER BY timestamp DESC
LIMIT 1
実行についてステップ1で報告されたtimestampを含むよう、検索対象の時間範囲を十分に広く設定してください。
このクエリを$ai_window_start/$ai_window_endで絞り込まないでください。
クラスターイベントは時間範囲の終了後に生成されるため、これらの境界を使うと行が0件になります。
clustersフィールドは JSON 配列です。解析すると、クラスターのタイトル、サイズ、説明、任意のmetrics、および各クラスターのtracesマップを確認できます。
重要: クラスター JSON は非常に大きくなる場合があります(座標を含む、数千件のトレース、生成、または評価 ID)。
結果がインライン表示には大きすぎる場合、自動的にファイルに保存されます。
読みやすい要約を取得するには、scripts/にあるprint_clusters.pyを使用してください。
ステップ 3 — クラスターのメトリクスを計算する
トレースレベルのクラスターでは、コスト/レイテンシー/トークンのメトリクスを計算します。
posthog:execute-sql
SELECT
properties.$ai_trace_id as trace_id,
sum(toFloat(properties.$ai_total_cost_usd)) as total_cost,
max(toFloat(properties.$ai_latency)) as latency,
sum(toInt(properties.$ai_input_tokens)) as input_tokens,
sum(toInt(properties.$ai_output_tokens)) as output_tokens,
countIf(properties.$ai_is_error = 'true') as error_count
FROM events
WHERE event IN ('$ai_generation', '$ai_embedding', '$ai_span')
AND timestamp >= parseDateTimeBestEffort('<window_start>')
AND timestamp <= parseDateTimeBestEffort('<window_end>')
AND properties.$ai_trace_id IN ('<trace_id_1>', '<trace_id_2>', ...)
GROUP BY trace_id
生成レベルのクラスターでは、イベント UUID を使って照合します。
posthog:execute-sql
SELECT
toString(uuid) as generation_id,
toFloat(properties.$ai_total_cost_usd) as cost,
toFloat(properties.$ai_latency) as latency,
toInt(properties.$ai_input_tokens) as input_tokens,
toInt(properties.$ai_output_tokens) as output_tokens,
if(properties.$ai_is_error = 'true', 1, 0) as is_error
FROM events
WHERE event = '$ai_generation'
AND timestamp >= parseDateTimeBestEffort('<window_start>')
AND timestamp <= parseDateTimeBestEffort('<window_end>')
AND uuid IN ('<gen_uuid_1>', '<gen_uuid_2>', ...)
評価レベルのクラスターでは、まず $ai_clusters の各クラスターの metrics フィールドを確認します(たとえば、合格率、N/A 率、主要な評価者名、平均判定コストなど)。個々の評価行が必要な場合は、イベント UUID を使って照合します。
posthog:execute-sql
SELECT
toString(uuid) AS evaluation_id,
toString(properties.$ai_trace_id) AS trace_id,
toString(properties.$ai_target_event_id) AS generation_id,
toString(properties.$ai_evaluation_name) AS evaluation_name,
toString(properties.$ai_evaluation_result) AS evaluation_result,
toString(properties.$ai_evaluation_reasoning) AS evaluation_reasoning,
toFloatOrNull(toString(properties.$ai_total_cost_usd)) AS judge_cost,
timestamp
FROM events
WHERE event = '$ai_evaluation'
AND timestamp >= parseDateTimeBestEffort('<window_start>')
AND timestamp <= parseDateTimeBestEffort('<window_end>')
AND uuid IN ('<eval_uuid_1>', '<eval_uuid_2>', ...)
ステップ 4 — 特定のトレースを詳しく調べる
興味深いクラスターを特定したら、トレースツールを使って個々のトレースを調べます。
posthog:query-llm-trace
{
"traceId": "<trace_id_from_cluster>",
"dateRange": {"date_from": "<window_start>", "date_to": "<window_end>"}
}
メッセージの内容が必要な場合
クラスターのイベント、ID、コスト/レイテンシー/トークンのメトリクス、評価行には events を使用します。
ユーザーメッセージやモデルの入出力全体が必要な場合は、events.properties.$ai_input、$ai_output、$ai_output_choices をクエリしないでください。
これらの大きなフィールドは posthog.ai_events にあります。
代表的な例をいくつか確認する場合は、query-llm-trace を使用してください。posthog.ai_events を読み取り、イベントツリー全体を返します。
一括抽出する場合は、まずクラスターからトレース ID を取得してから、trace_id を起点に posthog.ai_events をクエリします。
posthog:execute-sql
SELECT
trace_id,
timestamp,
span_id,
event,
model,
input,
output_choices
FROM posthog.ai_events
WHERE trace_id IN ('<trace_id_1>', '<trace_id_2>', ...)
ORDER BY trace_id, timestamp
posthog.ai_events の保持期間は events より短いため、古いクラスターにはメタデータやメトリクスが残っていても、メッセージの内容がない場合があります。
$ai_* イベントのスキーマ全体を確認するには、exploring-llm-traces スキルを読み込んでください。
調査パターン
「どのような種類の LLM 使用状況がありますか?」
- 最近のクラスタリング実行を一覧表示します(ステップ 1)
- 最新の実行のクラスターを読み込みます(ステップ 2)
- クラスターのタイトルと説明を確認します。それぞれが異なる使用パターンを表しています
- クラスターのサイズを比較し、トラフィックの分布を把握します
「最もコストが高い/最も遅いクラスターはどれですか?」
- 実行からクラスターを読み込みます(ステップ 2)
- 各クラスターからトレース ID を抽出します
- クラスターごとにメトリクスを計算します(ステップ 3)
- クラスターごとに
avg(cost)、avg(latency)、sum(cost)を集計します - クラスター間で比較します
「このクラスターには何が含まれていますか?」
- クラスターのトレースを読み込みます(
tracesフィールドから) rankで並べ替えます(セントロイドに最も近いものが、最も代表的です)- 上位 3~5 件のトレースを
query-llm-traceで調べ、パターンを把握します - クラスターの
titleとdescriptionを確認し、AI が生成した概要を把握します
「エラーの多いクラスターはありますか?」
error_countを使ってメトリクスを計算します(ステップ 3)- クラスターごとにエラー率を計算します:
items_with_errors / total_items - エラー率の高いクラスターに注目します
- エラーのあるトレースを詳しく調べ、根本原因を特定します
「実行間でクラスターはどのように変化していますか?」
- 複数の実行を一覧表示します(ステップ 1)
- 各実行のクラスターを読み込みます
- クラスターのタイトルを比較します。実行間で似たタイトルがあれば、パターンが安定していることを示します
- クラスターのサイズの変化を追跡し、トラフィックパターンの変化を検出します
UI リンクの作成
- クラスターの概要:
https://app.posthog.com/ai-observability/clusters - 特定の実行:
https://app.posthog.com/ai-observability/clusters/<url_encoded_run_id> - クラスターの詳細:
https://app.posthog.com/ai-observability/clusters/<url_encoded_run_id>/<cluster_id>
ユーザーが PostHog UI で目視確認できるよう、これらのリンクを必ず提示してください。
ヒント
- SQL クエリでは必ず時間範囲を設定してください。時間範囲を指定せずにクラスターイベントを検索すると時間がかかります
- クラスターイベントを検索する際は、分析対象の期間ではなく、イベントが発生した時点を基準に範囲を指定してください。実行の
$ai_window_endはイベント自体のtimestampより前です - まず実行の一覧を確認して全体像を把握し、その後、特定のクラスターを詳しく調べてください
- クラスターのタイトルと説明は AI が生成した要約です。トレースを調べて内容を確認してください
- ノイズクラスター(
cluster_id: -1)には、どのパターンにも当てはまらなかった外れ値が含まれます - 有効なクラスタリング設定を把握するには、
llma-clustering-job-listを使用してください - クラスター内のトレース ID は、詳細な調査に
query-llm-traceで直接使用できます - メッセージの内容は
events.propertiesではなくposthog.ai_eventsにあります。独自の一括 SQL クエリが必要な場合を除き、query-llm-traceを使用してください - 大規模なクラスターでは、代表例を確認するため、順位が最も高い(重心に最も近い)トレースを調べてください