LayerX エンジニアブログ

LayerX の エンジニアブログです。

外部イベントがモニタリング対象に与える影響を評価し続けるエージェントの試作

こんにちは。LayerX の Ai Workforce 事業部 FDE部エンジニアのkoseiと申します。 当事業部では、エンタープライズのお客さま向けにAi Workforceというプロダクトを提供しています。 今回はAi Workforceそのものの話ではないですが、関連する一般的なユースケースについて少し試していることを共有します。

組織が大きくなると、多種多様で膨大なアセットをどう活かすか、どう管理し、守り、継続的に価値を出していくのかが重要になります。 ここでいうアセットは、単なるファイルや文書だけではありません。個別の案件やプロジェクト、ノウハウ、実施機関や取引先企業、契約や判断履歴、現時点でのリスク状態なども含まれます。 こうした対象は、一度評価して終わりではなく、外部で起きた出来事をきっかけに、評価や優先順位、活用可能性が変わっていきます。そうなると、人間がすべてを手作業で追い続けるのではなく、エージェントが

  • 今どれがリスクが高まりそうか
  • どれに人が入るべきか
  • どこは一旦据え置いてよいか

を常に監視・更新し、人間がすぐにアクションに活かせる状態を作りたくなります。

今回は、そのようなケースで何が重要になってくるのかや肌感を得るため、 「外部イベントをフックに、管理対象の評価を更新していく ambient agent 的なもの」を、小さく作って試してみました。

背景

このような「外部を起点に、管理対象の評価・判断を更新し続ける」ユースケースは、意外と幅があります。

例えば、公募案件の一覧に対して、自社アセットを活かして取りにいけそうな案件はどれかを継続的に監視・評価する、というケースがあります。 他にも、コンプライアンス運用において、法改正や当局ガイダンス、同業他社への行政処分のニュースを受けて、今どのルールは優先的に見直しをした方が良いかを考えるなどがあり得ます。

ただ、ここで難しいのは二次的な影響です。外部イベント(ニュース記事等)に案件名や実施機関名がそのまま出てくるなら話は簡単ですが、実際にはそうならないことのほうが普通です。たとえば、湾岸の情勢の悪化やタンカー被害のニュースは、個別の内陸インフラ案件名を含みません。航空便の大量欠航や移動制限のニュースも、どの島嶼国の空港案件や物流案件に影響するかまでは直接書いてくれません。商品価格や燃料価格の変動も、どの設備案件に効くかを明示してくれるわけではありません。

このあたりはサプライチェーンの文脈では以前からよく議論されているようです。特定の外部イベントがどの調達先や物流網、供給先に波及するのかを把握し、調達不能になるリスクを下げたり、代替調達を素早く打てるようにしたりする、という文脈です。

今回見たかったのも構造としてはかなり近く、違うのは対象が部材や供給網そのものではなく、案件やプロジェクト、その評価状態(リスクがどの程度か)である、という点です。

しかも、外部イベントとして得られる記事が、必ずしも管理対象の文書と意味的に近いとも限りません。たとえば「航空便の大量欠航」という記事に対して、本当に見たいのは航空会社そのものではなく、現地渡航や施工監理が止まりそうな案件、輸送制約で機材搬入が遅れそうな案件のような、もう一段波及した先です。

このとき、単純な対象名一致やベクトル検索だけだと、二次的な影響先までは届きにくいです。そこで今回は、この「二次的な波及」についても試すのにちょうどよい題材として、Knowledge Graph (以後KG)を使用しました。

題材とするユースケース

今回は題材として、World Bank の公開プロジェクト文書と外部ニュースを使いました。複数プロジェクトを横断的に見ているマネージャーや評価機関のような立場を想定して、「外部環境の変化によってどのプロジェクトが危なそうか」「どのプロジェクトに手を入れるべきか」を見たい、というダミーユースケースを置いています。

World Bank のdocumentsデータには、「プロジェクトの関連文書」として、プロジェクトの概要や追加融資の背景が書かれた資料、プロジェクトの基本情報や環境・社会配慮の論点がまとまった資料、環境影響評価のための文書といった資料が多く含まれており、実際の業務におけるユースケースに近い形で実験できるため、今回用いました。

データ出典: The World Bank, Projects & Operations / World Bank Projects API, 取得日:2026年5月20日。 The World Bank, Documents & Reports API, 取得日:2026年5月20日。 World Bank 資料の利用は、Terms of Use for Datasetsに従います。

これらの資料を用いて、KGを構築します。

イベント側のデータとしては、外部ニュースのようなものを想定しています。今回は具体的なソースとして GDELT を使いました。特に、15分ごとに更新される GDELT Event Database という、報道されている情報を元に「誰が、誰に対して、何をしたか」といったメタデータが付与されたイベントデータセットから抽出して利用しました。

データ出典:The GDELT Project(https://www.gdeltproject.org/

本当は、一定期間で LLM が「リスクが高い」と判定した案件が、結果として本当に危なかったのか、あるいは安定してうまくいったのかまで検証できるとさらに面白かったと思っています。World Bank の案件には第三者機関による評価の仕組みもあるようで、そういったスコアと照らし合わせられると、どの程度当たり外れがあったのかをもう少し定量的に見られたはずです。今回は時間の都合でそこまではできていません。

画面イメージ

今回試作したものの画面は以下になります。

1枚目は各プロジェクトのリスクに関するスコアを集計した全体を俯瞰するダッシュボード的な画面と特にリスクが高く手当が必要なプロジェクトが並んでいる画面です。2枚目は、特定のプロジェクトをクリックして閲覧可能な詳細画面であり、各プロジェクトの具体的なリスク内容等を検討する画面です。

重要な点としては、各値は固定のレポートではなく、外部イベントをきっかけにエージェントが情報収集・判断した結果を集計・反映したものであり、外部イベントが発生するたびに更新されていくということです。 人間はこのモニターを起点に、スコアが大きく変化した案件を深掘りしたり、異常な変化だけを別途検知したりできます。

今回の画面では、実際に LLM が作ったリスク評価結果を使っています。つまり、最終的にやりたかったのは、

  • 人間が一覧で全体感を掴む
  • 変化が大きいものに気づく
  • 必要なときだけ個別案件に入る

という運用であり、モニターはそのための入口です。

今回の構成

今回の構成は、大きく分けると 3 段階です。 2と3を繰り返すことで、外部イベントを起点にした判断結果データ(エージェントによるリスク評価)を更新し続ける仕組みです。

  1. まず、World Bank のプロジェクト文書から KG を構築し、各プロジェクトの初期リスク評価を作って DB に保存する
  2. その後、イベント(ニュース)を入力にして、KG 上で関連しておりリスク影響がありそうなプロジェクトを見つける
  3. プロジェクト文書等の詳細と照らし合わせて、リスク評価の更新を推論する
flowchart TB
    %% ===== データソース =====
    subgraph WB["世界銀行プロジェクト(一次データ)"]
        WB_DOC["プロジェクト文書<br>(PDF/HTML/JSON)"]
        WB_META["プロジェクトマスタ<br>(ID / 国 / セクター / 金額など)"]
    end

    subgraph EXT["外部イベント(ニュース等)"]
        EV["外部イベント<br>(ニュース等)"]
    end

    %% ===== 事前構築(KG + DBの初期評価) =====
    subgraph PREBUILD["1. 事前構築(KG構築 + 初期DB構築)"]
        RELEX["LLMで関係抽出"]
        KG((("Neo4j ナレッジグラフ")))
        PM[("プロジェクトDB<br>(project_id, title, links, ...)")]
        RISK[("リスクDB<br>(type, prob, impact, rationale, ...)")]
        WB_DOC --> EVAL_INIT["LLMで初期リスク評価"] --> RISK
    end

    %% ===== イベントフックでのKG探索 =====
    subgraph EXPLORE["2. イベントフックでのKG探索"]
        ING["イベント取り込み"]
        QGEN["KG探索"]
        JOIN["関連プロジェクト候補の抽出"]
    end

    %% ===== リスク評価の更新 =====
    subgraph UPDATE["3. リスク評価の更新"]
        EVAL["LLMでリスク評価<br>(記事 + 根拠パス + 既存状態)"]
        HIST[("イベント評価履歴DB<br>(event, path, diff, timestamps)")]
    end

    %% ===== PREBUILD =====
    WB_DOC --> RELEX --> KG
    WB_META --> PM

    %% ===== EXPLORE =====
    EV --> ING --> QGEN  --> JOIN
    KG --> JOIN

    %% ===== UPDATE =====
    JOIN --> EVAL
    PM --> EVAL
    RISK --> EVAL
    EVAL --> HIST

    %% ==== overall ====

1. 事前構築

flowchart TB
    %% ===== データソース =====
    subgraph WB["世界銀行プロジェクト(一次データ)"]
        WB_DOC["プロジェクト文書<br>(PDF/HTML/JSON)"]
        WB_META["プロジェクトマスタ<br>(ID / 国 / セクター / 金額など)"]
    end

    %% ===== 事前構築(KG + DBの初期評価) =====
    subgraph PREBUILD["1. 事前構築(KG構築 + 初期DB構築)"]
        RELEX["LLMで関係抽出"]
        KG((("Neo4j ナレッジグラフ")))
        PM[("プロジェクトDB<br>(project_id, title, links, ...)")]
        RISK[("リスクDB<br>(type, prob, impact, rationale, ...)")]
        EVAL_INIT["LLMで初期リスク評価"]
    end

    WB_DOC --> RELEX --> KG
    WB_DOC --> EVAL_INIT --> RISK
    WB_META --> PM

KGの構築自体は、かなりシンプルに neo4j_graphraghttps://github.com/neo4j/neo4j-graphrag-python)の SimpleKGPipeline を使って構築を始めました。

llm = OpenAILLM(model_name=kg_model)
embedder = OpenAIEmbeddings()

pipeline = SimpleKGPipeline(
    llm=llm,
    driver=driver,
    embedder=embedder,
    schema=KG_SCHEMA,
    on_error="IGNORE",
    from_file=True,
    perform_entity_resolution=True,
)

await pipeline.run_async(
    file_path=str(path),
    document_metadata=metadata,
)

このくらいのコード量でスタートできるので、「まずナレッジグラフを構築して動かしてみる」用途ではかなり扱いやすいかと思います。

また、今回は

  • どの組織が実施主体なのか
  • どの施設や設備が関係するのか
  • どの国や制度と結びついているのか

などを ノードやリレーションとして設定しておくことで、二次的な波及もLLMが推論に活かすことを期待します。

最終的にはプロジェクトへの影響が見たいので、KG上には、管理対象である「プロジェクト」を表すノードも追加しておき、 そのノードとのリレーションも推論させます。(プロジェクトへの波及の推論に使うため)

これにより以下のようなナレッジグラフが得られます(ピンク色の大きめの丸がプロジェクトに対応します)

2. ニュース評価

flowchart TB
    subgraph EXT["外部イベント(ニュース等)"]
        EV["外部イベント<br>(ニュース等)"]
    end

    subgraph EXPLORE["2. イベントフックでのKG探索"]
        ING["イベント取り込み"]
        QGEN["KG探索"]
        JOIN["関連プロジェクト候補の抽出"]
        ING --> QGEN --> JOIN
    end

    EV --> ING

外部イベントであるニュースが入力されると上記のフローで関連するプロジェクトのリスク評価を更新します。

今回は素朴に、探索の起点としてまず記事本文に近い Chunk を探し、その Chunk から関連エンティティや 管理対象プロジェクトのノードまでのパスを取っています。

3. リスク評価更新

flowchart TB
    subgraph UPDATE["3. リスク評価の更新"]
        EVAL["LLMでリスク評価"]
        HIST[("イベント評価履歴DB<br>(event, path, diff, timestamps)")]
    end

    JOIN["関連プロジェクト候補の抽出"]
    PM[("プロジェクトDB<br>(project_id, title, links, ...)")]
    RISK[("リスクDB<br>(type, prob, impact, rationale, ...)")]

    JOIN --> EVAL
    PM --> EVAL
    RISK --> EVAL
    EVAL --> HIST

その後、

  • ニュース本文
  • KG 上のパス
  • 既存リスク
  • プロジェクト文書

を合わせて LLM に渡し、「このプロジェクトのリスク評価をどう更新すべきか」を判断させる流れにしました。

更新先のデータベースはかなりシンプルで、イメージとしては、

  • project_id
  • リスク内容
  • リスクの影響度
  • リスク発生確度
  • 判定理由

のような項目を持つものです。

実際に作ってみてどうだったか

結論から言うと、今回狙っていたような

  • 外部イベントから
  • KG を通じて
  • 妥当な二次的波及を拾い
  • そのままリスク評価の更新を適切に行う

というところまでは、まだ十分に実証できたとは言いづらかったです。 12回分のイベントデータを入力してリスク評価の推移を人手で見た所感ですが、妥当な結果よりも「変化しない」「誤検知」の割合がかなり多かったです。

一方で、まだ検証しきれていないものの活用の余地はいろいろありそうだと感じました。

たとえば 経路があることによる、どの関係(特に固有名詞)をたどってプロジェクトへ届いたのかも説明性が向上したり、リレーションの種類等を事前に定義しておけば、フィルタリングもしやすく、扱いやすくなったりしそうです。

今回、実際に触ってみたことで、色々と改善や工夫をしたくなる点も見つかってきました。

  • リスク評価部分のミス

    外部記事とプロジェクトの関係性があまり強くないにもかかわらず「リスク評価」を更新してしまう等がよくみられました。(今回使ったモデルが時間とコストの都合で gpt-5-nano だったことも影響していそうです。)

  • イベントのフィルタの必要性

    上記のような誤検知も一定は発生する一方で、外部イベント自体は大量かつ多種多様なため、適切なフィルタや制限しておく仕組みが必要そうです。

  • Country のような抽象度の高いノードにリレーションが集中しやすい等、ノードの種類・特徴を活かせる

    実際に構築されたKG。オレンジ色のノードがCountry

    例えば、短いパスを優先して取得場合、抽象的・汎用的なノードをハブとした経路が得られやすく、パスとしては一般論からでも導けそうなものが多くなってしまいます。

    今回は時間とコストを抑えるためにニュース記事から距離の近いプロジェクトだけに絞ってリスク評価する形にしましたが、期待していた二次波及の検知という目的においては更なる工夫の余地がありそうです。

  • KG構築時に外部情報も含めた方が良い可能性がある

    今回はプロジェクト文書のみから KG を作りましたが、外部からの二次以上の波及を検知するためには、よりチャンクとしての類似性は低いかつグラフとしては繋がるようなノードを増やすことが一定役立つのではと感じました。例えば、KG 構築時に抽出された固有名詞や組織名をさらに Web 検索し、その検索結果や関連エンティティも別のノードとしてつないでいく、といった拡張をしても良いかもしれません。

まとめ

今回は、外部イベントをフックに管理対象の評価状態を更新していく ambient agent 的なものを、簡易的に組んでみました。

その中で、Knowledge Graph を勉強も兼ねて敢えて使いましたが、単なる対象名一致ではたどり着きにくい候補や、固有名詞同士の関係を LLM が参照しながら判断する構図には、一定の活用可能性がありそうだと感じました。

一方で、距離の近い候補だけに寄せると挙動が単純な近傍探索に寄ってしまうことや、外部イベントよりもプロジェクト資料側に引っ張られてリスク更新してしまうことなどの点においては、調整と検証が必要そうです。

それでも、外部世界の変化をエージェントが継続的に取り込み・既存のリソースの評価や優先順位をつけ、人間がアクションに繋げやすい形で重要なものを浮かび上がらせる仕組みとしては、試してみることで色々と学びがありました。KGの構築方法・経路の選定・検索方法や、エージェントによる判断の誤検知減少、全体的な精度検証等、改善を試したいものは色々あるので機会があれば取り組んでみようと思います。