放課後のサイエンス

最終回:LLM×ナレッジグラフの境界を探る:誰もが使える推論プラットフォームへ —— GUI化と次なるフロンティア

August 23, 2026 | 4 Minute Read


ARIA-FORGEイメージ図

1.はじめに:道具からプラットフォームへ

Phase 6 で ARIA-Forge の推論エンジンは完成しました。全9クエリ facts=1。LLMガードレールが不確かなパスに付箋を貼り、Cu-Cu から Al-Al への類推も適切にラベリングされる。情報喪失ゼロ。推論品質は、実用に足る水準に達したと言っていいでしょう。

しかし、ここまで ARIA-Forge を使うには、コマンドラインから python scripts/run_aria_raw_all.py を叩く必要がありました。閾値を変えたければ config.py を編集し、結果を見たければ JSON ファイルを開く。これでは、材料科学の研究者——Python に必ずしも習熟していない、本来のユーザー——には届きません。

最終章 Phase 7 の目標は、ただ一つ。ARIA-Forge を「誰もがブラウザから使える Web アプリケーション」にすること。

本稿では、フレームワーク選定からアーキテクチャ設計、UI実装、そして改善の繰り返しまで、Phase 7 の全貌をお伝えします。そして最後に、全7回のシリーズを総括し、ARIA-Forge の未来を展望します。


2.フレームワーク選定:なぜ Streamlit なのか

GUI化にあたり、まず悩んだのがフレームワーク選びです。候補は Streamlit と Gradio の二択。どちらも Python ネイティブで、既存コードを import して呼び出せます。

決め手は、generate_report.py が生成する Markdown レポートの扱いでした。

観点 Streamlit Gradio 判定
Markdownレンダリング st.markdown() でコードブロック・表・見出しを完全表示 gr.Markdown() は表やコードブロックに制約あり Streamlit
プログレス表示 st.status() で段階的表示が容易 コールバック依存で実装が複雑 Streamlit
キャッシュ @st.cache_resource(エンジンキャッシュに最適) gr.State()(やや複雑) Streamlit
研究分野での普及度 データサイエンス・NLP分野で広く普及 MLデモで普及 同等
導入コスト pip install streamlit のみ 同様 同等
表1:Streamlit vs Gradio の比較。Markdownレンダリングの差が決定的だった。

ARIA-Forge の出力は、コードブロックと数値表と見出しが複雑に入り組んだ、いわば「論文の要約」のような Markdown です。これを変換なしでブラウザに美しく表示できる st.markdown() の存在が、Streamlit を選んだ最大の理由でした。


3.アーキテクチャ設計:上から薄くラップする

GUIの設計で最も重視したのは 「既存コードに手を加えない」 ことです。推論エンジンは Phase 6 で検証済み。これを GUI 化のために壊すわけにはいきません。そこで、すべてをモジュールインポートで繋ぎ、上から薄くラップする方式を取りました。

web_ui.py  ← 今回新規作成
  │
  ├─ import scripts.run_aria_raw_all as aria_module
  │   ├─ aria_module.MasterGraphEngine  ← エンジン(@st.cache_resource でキャッシュ)
  │   └─ aria_module.run_single_query() ← 単一クエリ実行(今回追加)
  │
  ├─ import scripts.generate_report as report_module
  │   └─ report_module.generate_report()  ← レポート生成(変更ゼロ!)
  │
  └─ import config  ← 閾値の動的変更のみ

図1: Phase 7 のアーキテクチャ。既存コードは一切修正せず、上からimportしてラップする。

subprocess で別プロセスとして呼び出す方式も検討しましたが、エンジン初期化に数秒〜数十秒かかるため実用的ではありません。モジュールインポート方式なら、Streamlit の @st.cache_resource デコレータでエンジンをメモリ上に保持できます。2回目以降の推論は即時実行。22,396ノードのグラフ読み込みも、初回だけです。

もう一つ、既存の run_aria_raw_all.py には run_single_query() という関数を1つだけ追加しました。全クエリをループ実行する既存関数には手を触れず、単一クエリを受け取って dict を返す薄いラッパーです。後方互換性は完全に維持されています。


4.UIデザイン:操作できるのは2つだけ

Streamlit で構築した UI は、驚くほどシンプルです。操作できるパラメータはたった2つ——Primary Threshold(類似度閾値)と Analogy Threshold(類推フォールバック閾値)のスライダーだけ。Phase 5.6r で削除された RETRIEVAL_TOP_KMAX_HOP_COUNT といったコントロールは、実はコード内で参照されておらず、実質的に機能していませんでした。機能しない UI は潔く削除しました。

UI領域 内容
サイドバー Primary Threshold(0.3〜0.9, default 0.7)/ Analogy Threshold(0.2〜0.6, default 0.4)のスライダー
メイン上部 クエリ自由入力テキストエリア + プリセット選択(既存9クエリをドロップダウンから)
メイン中央 プログレス表示:Phase 1/4 エンジン初期化 → 2/4 キーワード抽出&グラフ検索 → 3/4 パス分類&LLMレビュー → 4/4 レポート生成
メイン下部 generate_report.py の出力を st.markdown() でそのままレンダリング
表2:web_ui.py の画面構成。操作要素は必要最小限。

引けるコントロールが2つだけ——これこそ、Phase 5.6r から Phase 6 にかけての紆余曲折を経て到達した「コードの単純さ」の証明でもあります。余計なパラメータを削ぎ落とし、研究者が本当に気にすべきものだけを残した。このミニマルな UI は、技術的制約ではなく、設計思想の結晶です。


5.改善の繰り返し:実装して初めて見えた5つの課題

実装は完了し、いざ streamlit run web_ui.py——。動きました。美しい Markdown レポートがブラウザに表示され、プリセットクエリを選んでボタンを押せば推論が走る。しかし、細かく見ていくと、実装段階では気づかなかった課題が次々と顔を出しました。

# 問題 修正
1 プリセット切替時にテキストエリアが更新されない(Streamlitは初回レンダリング時のみ value を参照) st.session_state で状態管理し、on_change コールバックで検知・更新
2 RETRIEVAL_TOP_KMAX_HOP_COUNT がコード内で未参照なのに UI に存在 サイドバーから該当コントロールを削除
3 クラス変数 MasterGraphEngine.ANALOGY_THRESHOLD の直接書換による並行実行時の競合リスク インスタンス変数 engine.ANALOGY_THRESHOLD への書換に変更
4 結果なし(facts=0, hypotheses=0)時に report_markdown が未定義のまま後続処理が継続 st.stop() で早期リターン、結果なし時は st.warning() 表示後に停止
5 プログレス表示が実際には同期的(st.status のラベル更新は処理完了後に一括描画) コードコメントに制約を明記(Streamlitのアーキテクチャ上の限界)
表3:実装後に発見された5つの課題と修正内容。GUI開発特有の「実行してみて初めてわかる問題」たち。

特に印象的だったのは #1 です。st.text_area(value="初期値") と書けば、プリセットを切り替えたときにも値が更新される——そう期待するのが自然です。しかし Streamlit は、ウィジェットの value初回レンダリング時のみ参照します。この「宣言的UI」と「状態管理」の間にあるギャップに、最初は戸惑いました。

#3 も、Python の属性解決順序(インスタンス属性がクラス属性を上書きする)を理解していなければ、うっかりクラス変数を直接触ってしまう——そんな落とし穴です。Web フレームワークの上で動作するコードを書くことは、単体の Python スクリプトを書くこととは別種の注意力を要求します。


6.シリーズ総括:22,396ノードの孤島から、ここまで

最終回の締めくくりとして、ARIA-Forge の進化の全軌跡を一枚の図にまとめます。

Phase タイトル 得たもの 直面した壁 主要技術
1〜2 巨大グラフの孤独 接続性 22,396ノードが論文間で繋がらない孤島問題 セマンティック名寄せ(cos類似度0.95)
3〜4 ベクトル検索の落とし穴 網羅性 長文クエリが特定論文に閉じ込められるEmbedding Trap マルチエントリーポイント化
5 事実と類推の境界 構造 閾値0.7の壁。厳格にすればヒットせず、緩めればハルシネーション 二段階ルーティング(facts/hypotheses分離)
5.6 決定論の迷宮 定量性 Al-AlクエリにCu-Cuがfactsで返る誤検知。過剰防衛による全パス棄却 キーワード共起密度。棄却→再分類へ転換
6 パラダイムシフト 判断の手放し 閾値調整の無限後退。あるクエリを救えば別が犠牲になる LLMガードレール(排除→評価)
7 誰もが使えるプラットフォームへ アクセシビリティ 開発者専用CLIツールからの脱却 Streamlit GUI化。エンジンキャッシュ
表4:ARIA-Forge 全7Phase の進化マップ。各Phaseで一つの壁を乗り越え、一つの能力を獲得してきた。

この表を見ていると、不思議な感慨が湧いてきます。Phase 1 の孤島問題から Phase 6 の LLM ガードレールまで、私たちが乗り越えてきた壁は、どれも「最初から想定できた」ものではなく、「やってみて初めてぶつかった」ものばかりです。

そして、その都度私たちが取ったアプローチは「より複雑なロジックで押さえつける」方向から、「よりシンプルな仕組みで受け入れる」方向へと、一貫してシフトしてきました。Phase 5.6 初版の三重バリデータ(LLM+正規表現+PSP検証)が Phase 6 ではたった一つの LLM ガードレールに置き換わったこと。Phase 5.6r の複雑な適応的閾値が Phase 6 では「全部通す」という単純明快なルールになったこと。

「制御」から「委譲」へ。「排除」から「評価」へ。ARIA-Forge の進化は、AI システムにどこまでをプログラムで制御し、どこからを AI 自身に委ねるべきか——その境界線を探る旅でもあった。

7.残された宿題:完璧ではないことが、完璧

シリーズの締めくくりとして、あえて未解決の課題を明記しておきます。

  • plausibility の差別化不足(Phase 6 から継続):LLM の評価が “medium” に偏り、有益な差別化ができていない。
  • 全クエリリグレッションテスト未実施:q1〜q7, q6_retry, tn_1 の全9クエリに対する体系的なリグレッションは未了。
  • 複合語ノード名問題:Phase 5.6 初版で MgOnanostructure\bMgO\b にマッチしなかった問題は、ノード名の正規化という根本的対応が未着手。

しかし、未完成であることは、拡張の余地があるということでもあります。ARIA-Forge は「完璧な答えを返す AI」ではなく、「考えるための材料を整理し、注釈を付け、研究者の判断を支援する AI」です。その立ち位置からすれば、LLM の評価が “medium” に偏るのは慎重さの表れとも言えます。断言できないことを断言しない——それは研究者の態度そのものです。


8.次なるフロンティア:ARIA-Forge の未来

このブログシリーズは今回で最終回ですが、ARIA-Forge の開発はまだ始まったばかりです。現在構想中の次のステップを、未来への予告として記しておきます。

全固体電池ドメインへのストレステスト。 ARIA-Forge のナレッジグラフは、現在、半導体パッケージング分野の論文から構築されています。このグラフに全固体電池の論文を追加投入し、未知ドメインの概念(固体電解質、イオン伝導度、界面抵抗など)に対して ARIA がどのように類推を働かせるか——これは、ARIA-Forge の汎用性を試す最大の挑戦です。

自律的再探索エージェントへの進化。 現在の ARIA-Forge は、1回のクエリに対して1回の推論を実行して終わります。しかし、研究者の思考プロセスはそうではありません。最初の結果を見て「では、この材料で同じことをしたら?」と追加の問いが生まれます。その連鎖を、LLM が自律的に駆動する——最初の推論結果を読んで、追加の検索クエリを自ら生成し、2巡目、3巡目の推論を重ねていくエージェント。それが、次の ARIA-Forge の姿です。

22,396ノードの孤島から始まった旅は、7つの Phase を経て、研究者がブラウザから対話的に材料探索できるプラットフォームへと結実しました。しかし、これはゴールではありません。ARIA-Forge の旅は、まだ始まったばかりです。

全7回、お読みいただきありがとうございました。このブログが、材料インフォマティクスとナレッジグラフ、そして LLM の交点に立つすべての方にとって、何らかの道標となれば幸いです。