🧹

[ADK] 1.15.0のContextFilterPluginで長大な会話履歴をフィルタリングしパフォーマンスを改善する

に公開

こんにちは、サントリーこと大橋です。

2025/09/26にAgent Development Kit(以降ADK) 1.15.0と1.15.1がリリースされました。

https://github.com/google/adk-python/releases/tag/v1.15.0
https://github.com/google/adk-python/releases/tag/v1.15.1

前回の記事では1.15.0、1.15.1の概要と、パフォーマンス改善に繋がる新機能「Context CachingとStatic Instruction」について解説しました。

https://zenn.dev/soundtricker/articles/6891fed2de91b0

今回の記事では、同じく1.15.0で追加された、パフォーマンス改善のためのもう一つの新機能「ContextFilterPlugin」について深掘りしていきたいと思います。

課題: 会話が長くなるとトークン(LLMが処理するテキストの最小単位)が増え続ける問題

チャット形式のAIエージェントを運用していると、会話のセッションが長くなるにつれて、過去のやり取りがどんどん積み重なっていくという課題に直面します。

ADKを含む多くのエージェントフレームワークでは、文脈を維持するために過去の会話履歴を毎回LLMへのリクエストに含めます。しかし、これが長くなると、以下のような問題が発生します。

  1. パフォーマンスの劣化: LLMに送信するトークン量が増加し、レスポンスが遅くなります。
  2. コストの増加: 多くのLLMは入力トークン数に基づいて課金されるため、不要な履歴を毎回送信するとコストが増大します。
  3. コンテキストウィンドウの圧迫: モデルが一度に処理できるトークン数には上限があり、それを超えるとエラーが発生したり、古い情報が切り捨てられたりします。

これまでは、開発者が自前で履歴を要約したり、取捨選択したりするロジックを組む必要があり、手間がかかっていました。

ADK1.15.0における ContextFilterPlugin

この課題を解決するためにADK 1.15.0で導入されたのが ContextFilterPlugin です。

ContextFilterPlugin は、その名の通り、LLMに渡すコンテキスト(会話履歴)をフィルタリングするためのプラグインです。RunnerApp にこのプラグインを追加するだけで、LLMへのリクエストに含まれる会話履歴を自動的に制御できます。

このプラグインは、主に2つの方法で履歴をフィルタリングします。

  • num_invocations_to_keep: 保持する直近のやり取り(ユーザーの発言とエージェントの応答のペア)の数を指定します。例えば 2 を指定すると、最新の2往復の会話だけがコンテキストとして利用されます。
  • custom_filter: 独自のfilterを定義してフィルタリングを行う。

これにより、開発者は複雑な履歴管理ロジックを実装することなく、エージェントのコンテキストサイズを常に適切な範囲に保つことができます。

使用例

ContextFilterPlugin の使い方は非常に簡単です。App または Runnerplugins リストに追加するだけです。

以下は、直近3回の会話履歴のみを保持するエージェントの例です。

agent.py
from google.adk.agents import Agent
from google.adk.apps import App
from google.adk.plugins.context_filter_plugin import ContextFilterPlugin

# Agentの定義
root_agent = Agent(
    model='gemini-2.5-flash',
    name='chat_agent',
    instruction='あなたはフレンドリーなアシスタントです。',
)

# ContextFilterPluginのインスタンスを作成
# 直近3回のやり取りを保持する
context_filter = ContextFilterPlugin(
    num_invocations_to_keep=3
)

# AppにAgentとPluginを登録
app = App(
    name='chat_app',
    root_agent=root_agent,
    plugins=[
        context_filter,
    ]
)

# あとはこのappインスタンスをRunnerに渡して実行します。
# runner = InMemoryRunner(app=app)
# runner.run_async(...)

このように、既存のAgentのコードをほとんど変更することなく、手軽にコンテキスト管理機能を導入できます。num_invocations_to_keep の代わりに custom_filter を使って独自のフィルター機能を作成することも可能です。これらは同時に指定することも可能です。

まとめ

今回はADK 1.15.0で追加された ContextFilterPlugin について解説しました。

会話が長くなりがちなチャットエージェントにおいて、コンテキストの増大はパフォーマンスとコストに直結する重要な課題です。ContextFilterPlugin を利用することで、この課題に非常にシンプルかつ効果的に対処できるようになります。

前回の記事で紹介した Static InstructionContext Caching が「不変のコンテキスト」を効率化する仕組みであるのに対し、今回の ContextFilterPlugin は「可変のコンテキスト(会話履歴)」を管理する仕組みです。この2つを組み合わせることで、ADKエージェントのパフォーマンスを大きく向上させることができるでしょう。

さらに、今回のリリースでは直接追加されませんでしたが、コンテキスト管理に関連する機能として EventCompactor の開発も進んでいるようです。現在mainブランチに取り込まれているのは、インターフェース(定義)側だけのようですが、これは単に履歴をフィルタリング(削除)するだけでなく、イベントを要約・圧縮(Compact)して、情報を失わずにトークン量を削減することを目指す仕組みのようです。多分。
今後のリリースで、より高度なコンテキスト管理が可能になることが期待されます。

https://github.com/google/adk-python/commit/c37bd2742ca309d42c1575911458578ac192f8a2


お知らせ/宣伝

ADK開発者が集う日本語のDiscordコミュニティが誕生しました。ADKに関する情報交換や議論に興味がある方は、ぜひご参加ください!

https://discord.gg/BKpGRzjtqZ

また、ADKの最新のコミットログやリリースノートを分かりやすく解説するPodcastを、月・水・金に配信しています。ADKの動向を追いかけたい方は、ぜひ聴いてみてください。

https://www.youtube.com/playlist?list=PL0Zc2RFDZsM_MkHOzWNJpaT4EH5fQxA8n

Discussion