agentviz
by Yurikada
README.md
# agent-viz
ML実験の試行・ケース別スコア・判断の根拠を、人間とAIエージェントが同じ画面で確認するPythonツール。
**入口:** [セットアップと合成デモ](#使い方) · [判断ビュー](#判断ビュー実装済み) · [時系列ダッシュボード](#時系列ダッシュボード2026-09-04)
合成デモは個人の実験ログなしで動きます。公開版の構成は [pyproject.toml](pyproject.toml) と [src/agentviz/](src/agentviz/) を参照してください。
人間とAIエージェントの意思疎通を、チャットからビジュアル(グラフ・樹形図・ヒートマップ・フローチャート)へ拡張する継続資産。Kaggle / AtCoder Heuristic / トレードモデル開発で共用する。
## 構成方針(2026-08-24 調査に基づく)
- **記録の背骨 = MLflow**(ローカルSQLiteバックエンド)。エージェントが書き、人間は `mlflow ui` で見る
- **カスタム図 = 自己完結HTML**(Plotly)。MLflow のアーティファクトビューでインライン描画される
- 自前で持つのは「共通試行台帳スキーマ」「レポート部品」「ドメインアダプタ」の薄い層だけ
調査の正本: KnowledgeBase `00_Inbox/人間とAIエージェントのビジュアル意思疎通ツール 調査メモ`
## Phase 0(実装済み)
- `agentviz.schema` — 共通試行台帳スキーマ。1試行 = TrialRecord、ケース = seed / fold / 期間
- `agentviz.ledger` — TrialLedger。MLflow への log_trial / fetch_trials
- `agentviz.report` — build_report。試行台帳テーブル+メトリクス推移+ケース別×試行別相対スコアヒートマップの自己完結HTML
## 使い方
Python 3.10以上。cloneしたリポジトリ直下で実行します。
```powershell
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[dev,panel]"
# HTMLだけを生成する。実験ストアには記録しない
.\.venv\Scripts\python.exe demo\generate_demo.py --no-log
# 生成された demo/out/report.html をブラウザで開く
# テスト
.\.venv\Scripts\python.exe -m pytest
```
パネルを使わない場合は `.[dev]` だけでインストールできます。macOS/Linuxでは
`.venv/Scripts/python.exe` を `.venv/bin/python` に置き換えてください。
台帳への記録とパネルを試す場合:
```powershell
$env:AGENTVIZ_STORE = Join-Path (Get-Location).Path "store"
.\.venv\Scripts\python.exe demo\generate_demo.py
.\.venv\Scripts\python.exe -m agentviz.panel
```
パネルは `http://127.0.0.1:7861`。記録デモは実行ごとにrunを追加するため、
表示だけ確認する繰り返し実行には `--no-log` を使います。
MLflow UIを使う場合は、記録デモの末尾に出る `tracking -> sqlite:///.../mlflow.db`
のURI部分を `mlflow ui --backend-store-uri "<表示されたSQLite URI>"` に渡します。
保存先は `AGENTVIZ_STORE`、未設定時は `~/dev/Projects/agent-viz/store` です。
## Phase 1(実装済み)
- `agentviz.adapters.ahc` — 自前AHCランナー実測形式の取込。`from_results_json`(results/*.json)と `from_experiments_jsonl`(1行=1実験。壊れた行はエラーとして返して続行、metrics空の行はper-seed結果から再計算して救済、別端末の絶対パスは `results_dir` でファイル名解決)
- `agentviz.adapters.kaggle` — `from_cv(fold_scores, lb_score=...)`。ケース=fold、LBは `lb_score` メトリクス。
macro AUC / macro F1 のように**指標がラベル別スコアの平均**で定義されるコンペ向けに
`from_per_label(label_scores, label_meta=..., metric_name="macro_auc")` を持つ(ケース=ラベル)。
主指標を `cv_mean` と呼ばないのは、fold間のばらつき(測定の揺れ)とラベル間の落差(実力の差)を
取り違えないため。動かせるのは後者である。`label_meta` はケースの meta に入り、
教師の濃さや陽性数による層別の材料になる
- `agentviz.adapters.trade` — `from_walkforward(windows, ...)`。ケース=ウォークフォワード窓。OOSは `oos_score` メトリクス、ティアシートHTMLは `log_trial(artifact_paths=...)` で添付
- `agentviz.report` — 汎化ギャップ散布図を追加(`lb_score` / `oos_score` を持つ試行が2つ以上で自動表示。CV vs LB=IS vs OOSを同型に扱う)
- `agentviz.replay` — `build_replay(frames, infos, events)`。ahc069自作リプレイの骨格(シークバー・再生・コマ送り・←→キー・イベントクリックジャンプ)をドメイン非依存に一般化した自己完結HTML
実データ確認済み: `AtCoder\ahc\ahc069\experiments.jsonl`(1191行)から1133試行を取込、1130試行でper-seedケース解決(examples/ingest_ahc069.py)。
## Phase 2(実装済み)— 双方向化
- `agentviz.feedback` — 層別フィードバックの正本ストア(追記専用JSONL、`store/feedback.jsonl`)。add / list / resolve
- `agentviz.panel` — Gradioパネル兼MCPサーバー。人間は試行台帳・ヒートマップを見て層別指摘(対象試行・対象ケース・指示・優先度)を投函し、エージェントはMCPツールで読んで対応し `resolve_feedback` で閉じる
```powershell
# パネル起動(http://127.0.0.1:7861、ポートは AGENTVIZ_PANEL_PORT で変更)
.venv\Scripts\python.exe -m agentviz.panel
```
```powershell
# Claude Code への登録(パネル起動中に)
claude mcp add --transport http agentviz http://127.0.0.1:7861/gradio_api/mcp/
```
MCPを使わない場合も `gradio_client` または `agentviz.feedback.FeedbackStore` で直接読み書きできる。
UIのドロップダウン選択が反映されない環境では「再読込」ボタンが確実なフォールバック。
## Phase 3(実装済み)— 決定点
`feedback` が「この層が弱いから直せ」という**指摘→対応の一往復**を扱うのに対し、
`decisions` は「どれを採るか決まるまで先へ進めない」**論点**を扱う。形が違うので分けてある。
- `agentviz.decisions` — 決定点のストア(追記専用JSONL、`store/decisions.jsonl`)。propose / decide / supersede
- 選択肢は `measured` フラグを持つ。**未測定の選択肢を測定済みと並べて表示できないと、「測った中で最良」を「最良」と誤読する**
- `blocks` で決定間の依存を持つ。`ready()` は依存先が決着したものだけを返す
- 各選択肢は `evidence_trials` で台帳の試行を指す
正本の分担: 確定した判断の記述は **KnowledgeBase の Vault が正本**。
`decisions` が持つのは作業面(選択肢・根拠リンク・状態)で、`vault_ref` でVault側を指す。
同じ文章を両方に持たない。
`decide` は**人間の判断を記録するための口**である。エージェントが選択肢を並べ(`propose_decision`)、
人間が選ぶ。`chosen` は登録済みキーに限られ、自由記述は受け付けない(後から機械的に辿れなくなるため)。
`revise_option` は根拠の状態(evidence_trials / measured / note)だけを理由付きで改訂する
(登録時点の根拠はイベントとして常に履歴に残る)。
## 視点合わせ(実装済み)— エージェント→人間
`feedback` は人間→エージェント、`decisions` は論点の帳簿。もう一方向が欠けていた:
**エージェントが今どの比較を見て物を言っているのかを、人間の画面に一致させる手段**。
エージェントが「9ラベルに絞ると8勝1敗」と言っても、人間が別の比較を見ていれば
数字は合わない。条件を言葉で伝え直すのは伝言ゲームで、実際にこの往復で
「除外したのか、全部見たのか」が曖昧になった。
- `agentviz.viewstate` — 指差しのストア(追記専用JSONL、`store/viewstate.jsonl`)。
point / clear / current / history
- MCPツール `point_at_comparison` — 基準・候補・集計から外すケースをパネルへ送り、
**同じ呼び出しでその比較の数字も返す**(別々に取ると食い違いうる)。
`note` は必須。理由の無い画面変更は人間から見れば「勝手に変わった」でしかない
- MCPツール `clear_comparison_pointer` / パネルの「指差しを解除」ボタン
**台帳も決定も書き換えない。** 所見でも判断でもなく、視点を合わせるポインタである。
**人間の選択を黙って上書きしない**ことが設計の要で、パネルは適用時に
「誰がいつ何のために指定したか」を必ず表示し、解除の口を添える。
## 判断ビュー(実装済み)
「平均の順位表」だけでは判断できない、が実戦で繰り返し出たため、判断の骨格を部品化した。
すべて **人間=図 / エージェント=JSON** の二面で提供する。
- **ペア差** `paired_diff` — 2試行のケース単位差。**平均の符号とケース多数決が食い違う場合に
警告**(食い違ったら順位を主張できない。実データで複数回発火した)。
`cases` で集計を部分集合に限れる。**両試行で条件が同じでないケースを平均に混ぜない**ための口で、
RSNAでは勾配の来ていない3ラベルの差がノイズなのに12ラベルの平均を薄め、
平均 -0.040 に対し中央値 -0.104 と3倍ずれた。外したケースは `excluded_cases` に必ず入り、
**図からも消さず灰色で残す**(消すと、都合の良い部分集合を選んだのか
条件の違うケースを外したのかを読者が区別できない)。
パネルにも「集計から外すケース(複数可)」の選択欄があり、選ぶとその場で
図と統計が更新される(MCP `compare_trials` の `cases`、`build_report` の
`pairs` 第3要素と同じ機能)
- **層別平均** `strata_means` — 「この層では順位が入れ替わる」を出す。層の定義(ドメイン知識)は
呼び出し側が持つ
- **効き幅** `decision_leverage` — どの決定を先に決めるべきか。前提2つ(1決定=1因子、
生きている選択肢のみ)を毎回premisesとして同梱
- **ケース別詳細** `case_scores` / ドットストリップ図 — 相対ヒートマップで消える
「ケースの絶対難易度」を並び順として受動的に目に入れる
- **オラクル余地** `headroom` — 制約緩和系の案(scheduled sampling等)は実装前に
オラクル走行で上限を測る。オラクル採用不可・上限であること・閾値未満なら系統見送り、を
premisesに同梱
- **汎化ギャップ散布図** — `lb_score` / `oos_score` 付き試行が2つ以上で自動表示
## 実ケースの確認(実装済み)— ケースの中身を開く
`case` は集計の器(RSNAならラベル、AHCならseed、トレードなら期間)で、
**その中で何が起きたかは台帳から見えなかった**。「Baker's が弱い」までは
人間とエージェントで共有できても、どの実例をどう外したかは残らないので、
双方が別のものを思い浮かべたまま原因を議論することになる。実際にRSNAで
「教師が悪いのか画像が難しいのか」の往復がここで止まった。
- `ExampleResult(example_id, case_id, y_pred, y_true=None, meta={})` —
ケースの中の1件。`TrialRecord(examples=[...])` に入れる。
**`y_true` は無くてよい**。その場合 `error` は None で、誤差では並べられない。
無いものを0として扱わない(0にすると「正解が無いだけの実例」が誤差順の
上位に混ざり、見た目には分からない)
- 上限 `MAX_EXAMPLES=20000`。台帳は全件保存の場所ではなく、**議論のために覗く**ところ。
超えたら理由付きで断る
- `example_rows` / MCP `list_examples` — 1試行の実例を誤差の大きい順に。
正解が1件も無ければ黙って別の順序にせず、`sort_fallback` に何をしたかを書く。
「実例が無い」と「正解が無い」は別の文言にする(直す場所が違うため)
- `example_disagreements` / MCP `compare_examples` — 同じ実例を2試行がどう違えたか。
符号は `paired_diff` と揃える(負なら候補が良い)。ただし**どちらが良いかを
言えるのは `y_true` があるときだけ**で、無ければ `delta` は None、
`pred_shift` だけが出る。「違う」と「良い」を混ぜない
- MCP `point_at_examples` — 実例まで人間の画面を合わせ、**同じ呼び出しで中身も返す**。
`case_id` は必須(同名 `example_id` が別ケースにありうる)。`note` も必須。
比較の指差しと同じ1本のポインタに相乗りする。人間の画面が同時に2つの
「今見ているもの」を持てないため
- パネルに「実ケース」節。指差しが実例まで指しているときだけ開く。
指していないのに勝手に何かを開かないのは viewstate の約束と同じ
**まだできないこと**: 実例を入れると study 単位のブートストラップが可能になるが、
それ自体は未実装。ケース単位の再標本化(`case_resample_range`)は
信頼区間ではないので、順位の主張には使えないままである。
## 運用部品
- **試行アーカイブ** `set_archived` / `archive_trial` — フェーズが進んで決着した試行を
可逆に非表示化し、可視化の分解能を保つ(削除しない。履歴はMLflowに残る)
- **ダークモード** — レポートはprefers-color-scheme対応(Plotly図はrelayoutで追随)
- パネルMCPツール20本(読み取り15+書き込みは `add_feedback` 系・`decide` / `archive_trial`・`point_at_comparison` / `point_at_examples` / `clear_comparison_pointer`。指差し3本は台帳を変えず、人間の画面が見ているものだけを動かす)
## 実運用の適用例(ケーススタディ)
- [kaggle-store-sales-workflow](https://github.com/Yurikada/kaggle-store-sales-workflow) —
時系列検証設計。**12決定を決定点として帳簿化**し、分割設計・ベースライン・特徴・採用可否を
すべて「測ってから決める」で運用。CV改善のLB転移分析まで
- [kaggle-house-prices-workflow](https://github.com/Yurikada/kaggle-house-prices-workflow) —
nested-CVモデル選択。ケース別ヒートマップが平均の順位に隠れた層別反転を検出した初適用
- `rsna-knee-abnormality-detection` — 弱教師つき12ラベル分類(macro ROC-AUC)。
`from_per_label` の初適用。教師の濃さでラベルを層別すると、
濃い8ラベル 0.751 に対し教師が枯れた4ラベルが 0.525 で、
**指標の1/3が実質未学習**であることが平均 0.6807 の下から出てきた。
続く比較でペア差の集計限定が要ることも判明した(全12ラベルでは平均 -0.040 だが、
勾配の来ているラベルに絞ると効き幅は -0.090。平均だけで採否を決めていたら
半分以下に見誤っていた)
- `examples/ingest_ahc069.py` — AHC自前ランナーの実測ログ1133試行の取込
## ロードマップ
- 残差相関行列のビュー化(ブレンド多様性の判断で手組みした。部品化候補)
- 名前付き層ストア(人間の「指差し」の永続化)
- run alias(同一測定を複数の決定文脈から参照。試行の流用が可視性を壊した教訓から)
- pahcer形式アダプタ(実物の出力が手に入ったときに追加)
- レポートのサイズ最適化(Plotly同梱で約4.9MB/枚。エージェントの読み取りには支障なしと実測済み)
## 時系列ダッシュボード(2026-09-04)
`agentviz.timeseries.build_timeseries(spec, out_path)` — 条件×時系列(中央値+帯)の比較ページ。
kaggriculture の「本番56試合の再戦」計装から一般化した。横軸は day / epoch / 窓など任意の整数、
セクション→パネル→系列の仕様 dict を渡すと、KPI・小さな多重パネル・凡例・端ラベル・ホバー・表・所見を持つ
自己完結 HTML を返す。**Plotly を同梱しない**(インライン SVG を JS で描く)ので 1ページ 30〜200KB。
仕様の形は `timeseries.py` の docstring にある。使用例: `Kaggle/kaggriculture/79_live_ts_page.py`
(集計 JSON → 仕様 → HTML)。`validate_spec` が系列長・帯の形・表の列数の不一致を描く前に止める。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues