💬

Vertex AI Agent Engine Memory Bank で AI エージェントの記憶を深ぼってみた

に公開

はじめに

業務でエージェント開発を行う人も増えてきたと思います。私自身エージェントを作る中で、「対話をまたいで一貫した文脈を維持すること」が案外難しいと感じる場面が多くありました。
会話の中だけならうまく動くのに、セッションをまたぐと急に前提が抜け落ちたり、ユーザーの好みを忘れたりしてしまう——そんな状態では、エージェントを実サービスに統合したときの UX に大きな影響が出てしまいます。
そんな中で目に留まったのが、Google が今年の7月にリリースした「Vertex AI Agent Engine Memory Bank」でした。
このリリースに関連して、ACL2025 で採択された Google Research の In Prospect and Retrospect: Reflective Memory Management for Long-term Personalized Dialogue Agents という論文が1月に発表されており、この論文では RMM(Reflective Memory Management)というフレームワークによって、長期的な会話でパーソナライズされた応答を可能にする対話エージェントを構築しているようです。
このフレームワークは、過去の情報を記憶したいトピックごとに整理する「Prospective Reflection」と、これまでのコンテキストと記憶のトピックを紐づけるために、LLM とユーザーの応答からのフィードバックで検索精度を動的に改善する「Retrospective Reflection」という、2つの主要なメカニズムを統合しています。

Memory Bank というタイトルを持った論文が AAAI 2024 で採択されているようで、前述の Google Research の論文でも引用はされていますが、直接の関係はなさそうでした。

今回のブログでは、まずは公開されているサンプルコードやドキュメントをもとに Vertex AI Agent Engine の Memory Bank がどう動くのかを確認し、そのうえで 実サービスに組み込む際の要件を満たせるのかをいくつか検証していきます。

Vertex AI Agent Engine MemoryBank とは

実用的な機能も追加し、Vertex AI Agent Engine Memory Bank としてエージェント対話の文脈を長期的に保持し AI Agent をより実用的に活用できるようにしたサービスとしてローンチされています。このサービスを活用すると、通常の「コンテキストウィンドウ内での短期記憶」とは異なり、対話を超えた永続的な記憶を自動的に保存・検索・活用できます。これにより好み・事実・タスク状態を自動的に保存し、長期的に一貫したパーソナライズ体験を実現することができます。

MemoryBank: Enhancing Large Language Models with Long-Term Memory によると、短期記憶を単純にようやくするだけでなく、それぞれの記憶を R = e^{-\frac{t}{S}} で表される忘却曲線に従ようにし、あまり呼び出されない古い記憶は忘れる仕組みになっているようです。

MemoryBank を使って長期記憶を持つ Agent を作る

では、実際に Vertex AI Memory Bank を活用して長期記憶を持つ Agent を作ってみましょう。
まず、Agent を作成し、MemoryBank にメモリを溜める準備をします。中核となる処理のみ抜粋してご紹介します。

まずは Agent を定義します。今回は、フリマサイトでユーザーの購買意思決定を支援する Agent にしました。

from google import adk

agent = adk.Agent(
    model="gemini-2.0-flash",
    name='my_sample_agent',
    instruction="""
    あなたはフリマアプリにおいて、そのユーザーの購買意思決定を支援するアシスタントです。
    ユーザーは、フリマアプリにあるアイテムを探すために他のアイテムとの比較や、その詳細、おすすめの商品などを尋ねてきます。
    過去のユーザーとの会話などを参考に、ユーザーの嗜好に合わせた提案を行ってください。
    """,
    # PreloadMemoryTool を追加
    tools=[adk.tools.preload_memory_tool.PreloadMemoryTool()]
)

次に、作成済みの Agent を Agent Engine にデプロイして、インスタンスを作成します。

from vertexai.agent_engines import AdkApp

agent_engine = client.agent_engines.create(
      agent=AdkApp(agent=agent), # 作成した Agent を渡す
      config={
            "staging_bucket": "gs://<your_path>",
            "requirements": ["google-cloud-aiplatform[agent_engines,adk]"]
      }
)

その後、Vertex AI Memory Bank Service を設定します。

from google.adk.memory.vertex_ai_memory_bank_service import VertexAiMemoryBankService
from google.adk.sessions import VertexAiSessionService

# メモリサービス(Vertex AI Memory Bank)の初期化
memory_service = VertexAiMemoryBankService(
    project="rio-test-pj-426105",
    location="us-central1",
    agent_engine_id=agent_engine_id
)

app = AdkApp(
    agent=agent,
    memory_service_builder=memory_service,
)

reasoning_engine_resource_id = agent_engine.api_resource.name.split("/")[-1]

# create した Reasoning Engine の update
agent_engine = client.agent_engines.update(
    name=agent_engine.api_resource.name,
    agent=app,
    config={
      "staging_bucket": "gs://<your_path>",
      "requirements": ["google-cloud-aiplatform[agent_engines,adk]"]
      }
)

これで準備は完了しました。

まずは新規セッションでおすすめの商品を聞いてみます。

[user1] 私におすすめの商品はなんですか?
[agent] おすすめの商品をお探しとのことですね!😊 
いくつかご質問させてください。

1.  **興味のあるカテゴリーはありますか?** (例: レディースファッション、メンズファッション、家電、インテリア、エンタメなど)
2.  **何か特定のアイテムを探していますか?** (例: ワンピース、スニーカー、スマホ、漫画など)
(〜中略〜)
これらの情報があると、よりあなたにピッタリの商品を見つけやすくなります。

何も情報がない状態なので、もちろん具体的な回答は得られません。
では、具体的な情報をエージェントに教えてから、Memory Bank に保存します。

# 具体的な情報をエージェントに送信
await call_agent(
    """
    私は2歳の男の子と、4歳の女の子向けのおもちゃを探しています。
    2歳の子はアンパンマンが好きで、4歳の子はプリンセスが好きです。
    予算は5000円以内くらいでお願いします。
    """, 
    session.get("id"), user_id
    )
# Memory Bankに保存
await agent_engine.async_add_session_to_memory(session=session)

新しいセッションでもう一度おすすめを聞いてみると、以前の会話を記憶しているのがわかります。

[user1] 私におすすめの商品はなんですか?
[agent] お子様向けのおもちゃですね。2歳のお子様にはアンパンマン、4歳のお子様にはプリンセスがお好きとのこと、そしてご予算が5000円程度とのことでしたので、いくつかおすすめの商品をご提案します。

1.  **アンパンマン おしゃべりいっぱい!ことばずかんSuperDX**:
(〜中略〜)
これらの商品は、過去の会話からお子様の好みや予算に合わせて選んでみました。

長期記憶をつ Agent を活用してみる

実際に Agent を既存のサービスに組み込んで運用しようとすると、より実践的なシナリオで活用できる機能が必要になってきます。今回は Vertex AI MemoryBank で単にユーザーとエージェント間の会話を長期記憶化するだけでなく、運用上必要になってくる様々な要件を満たすことができるのか、試してみたいと思います。今回はあるフリマアプリの中に購買意思決定を支援するような Agent を開発することを想定して、いくつかの調査をしてみました。

会話する前にメモリを設定しておきたい

既存のサービスに組み込む場合、Agent との会話がなくともユーザーはそのサービスを活用している場合があるため、その活動履歴を何かしらの形で Agent の記憶に注入しておく必要があります。

今回の例で言えば、あるユーザーは様々な商品を購入しているが、Agent とそのような会話はしていないような状況ですね。別の LLM に購買履歴を要約として書き出してもらい、それを記憶として MemoryBank に登録できると良いかもしれません。
VertexAI MemoryBank の generate メソッドを活用すれば、会話になっていない内容も記憶として持てそうです。

例えば、Agent との会話をするという意味ではコールドスタートなユーザーがいたとします。

事前にメモリに購買履歴を注入して、その上でコールドスタート状態でゼロから会話しても過去の購入内容が反映できるか確認してみます。

# 購入履歴データを事前にメモリに注入する
user_id = "user2"

client.agent_engines.memories.generate(
    name=agent_engine_resource_name,
    direct_memories_source={"direct_memories": [
        {"fact": """
        過去の購買履歴は以下のとおりです。

        [購入履歴データ]
        1. 商品名: ダウンコート(ライトベージュ Mサイズ)
           カテゴリ:レディース・アウター
           購入日時: 2024-11-20
           購入金額: 5800円 (500円OFFクーポン利用)

        2. 商品名: だるまさんシリーズ 3冊セット(対象年齢 2歳〜)
           カテゴリ:本・絵本
           購入日時: 2024-12-01
           購入金額: 1250円

        3. 商品名: HHKB Professional HYBRID Type-S(日本語配列/墨)
           カテゴリ:PC周辺機器
           購入日時: 2024-10-15
           購入金額: 33000円
        """}]},
    scope={
        "app_name": APP_NAME,
        "user_id": user_id
    }
)

ゼロからの会話で、おすすめ商品を聞いてみます。

[user2(コールドスタートなユーザー)] 私におすすめの商品はなんですか?
[agent] 過去の購入履歴から、いくつかおすすめの商品を提案しますね。

1.  **お子様向け絵本:** 過去に「だるまさんシリーズ」を購入されているので、お子様向けの別の絵本はいかがでしょうか?例えば、「ノンタンシリーズ」や「ぐりとぐらシリーズ」などは定番で人気があります。
2.  **冬物アウター:** 昨年ダウンコートを購入されていますが、今年は別のデザインのアウターも検討されてはいかがでしょうか?
(〜後略〜)

過去に会話はしたことないが、注入された記憶をもとに商品をおすすめしてくれました。

変な記憶が発生したときに上書きしたい

実運用では、LLM が意図しない情報を「記憶すべき内容」と誤って判断してしまうケースがあります。
例えば、ユーザーのジョークをそのまま事実として記憶してしまったり、誤解に基づく推測を保存してしまう、といった状況です。さらに上記のように他の LLM によって生成された情報を注入するような場合には、その中にハルシネーションが発生したような場合もあります。このようなとき、後からメモリを修正できることが重要になります。
MemoryBank の API には 特定のメモリエントリを更新・削除するためのエンドポイント が用意されており、間違った記憶が発生した場合でも、後から管理者側で修正を行うことができます。

何を記憶すべき重要とするかをカスタマイズしたい

MemoryBank の標準挙動では、LLM が「記憶すべき内容かどうか」を一定のルールで自動判定します。
しかし、サービスによって「重要だとみなしたい情報」は大きく異なります。
今回は、ユーザー本人の嗜好だけでなく、家族構成や家族の嗜好も重要だとして記憶に抽出するように Custom Topic を作成して MemoryBank に設定をし、実際に記憶に抽出されるか確かめてみましょう。

まず、Custom Topic を設定する前の状態から確認します。
以下のように、自分の嗜好と家族の嗜好を両方を含めた会話をし、このセッションを Memory Bank に保存します。

[user3]
2歳の息子と、4歳の娘向けのおもちゃを探しています。
息子は最近、アンパンマンとカーズにハマっています。特にメーターが好きです。
娘は昆虫とプリキュア、すみっコぐらしが好きです。図鑑もよく見ます。
[user3]
家があまり広くないので、大きすぎないおもちゃがいいです。
予算は5000円以内でお願いします
[user3]
私自身は、最近寒くなってきたので、冬物のアウターを探しています。
おしゃれ着というより、機能性重視で暖かくて軽くて動きやすいものがいいです
丈は膝くらいのものを探しています

上記の会話のあと、新規セッションでおすすめ商品の商品を聞いてみます。

[user3] 
私におすすめの商品教えて。
[agent] 承知いたしました。過去の会話から、機能性を重視した暖かくて軽くて動きやすい膝丈くらいの冬物アウターをお探しとのことでしたので、いくつかおすすめの商品を提案します。
(〜後略〜)

この user に対して保存されたメモリを確認してみると以下の1件のみでした。
私は機能性を重視した、暖かくて軽くて動きやすい、膝丈くらいの冬物アウターを探しています。

ここで、家族構成や嗜好に関する情報を記憶するように、Custom Topic を設定します。

# Custom Topic
from vertexai.types import MemoryBankCustomizationConfig as CustomizationConfig

memory_topic = {
  "custom_memory_topic": {
    "label": "family_profile_and_needs",
    "description": """
    ユーザーの家族構成(配偶者の有無、子供の人数と年齢、ペットの有無)、
    家族がの嗜好やアレルギー情報、
    家族のライフスタイル(都市部/郊外、アクティブ/インドア、在宅勤務の有無など)、
    およびそれに伴う商品ニーズ(例:知育玩具、ベビー用品、家族旅行用品、静音性、安全性など)に関する情報。
    この情報は、家族全体のニーズに合わせたレコメンドを最適化するために利用される。
"""
  }
}

# Agent のアップデート
client.agent_engines.update(
    name=agent_engine.api_resource.name,
    config={
        "context_spec": {
            "memory_bank_config": {
                "customization_configs": [
                    CustomizationConfig(
                        memory_topics=[memory_topic]
                    )
                ],
            }
        }
    },
)

Custom Topic 設定後、上記ユーザーと全く同じ入力を別のユーザーで試してみます。

[user4] 
私におすすめの商品教えて。
[agent] 以前の会話から、息子さんはアンパンマンとカーズのメーター、娘さんは昆虫、プリキュア、すみっコぐらし、図鑑が好きとのことでした。また、家があまり広くないとのことですので、大きすぎないおもちゃで、予算5000円以内という条件でおすすめの商品を探してみます。
(〜後略〜)

メモリに保存された結果は以下の2件でした。

私は家があまり広くないので、大きすぎないおもちゃを探しており、予算は5000円以内です。
私は2歳の息子と4歳の娘向けのおもちゃを探しています。息子はアンパンマンとカーズのメーターが好きで、娘は昆虫、プリキュア、すみっコぐらし、そして図鑑も好きです。

Custom Topic を設定することで、家族構成や子どもの好みを記憶し、レコメンドしてくれるようになりました。逆に、ユーザー本人に関する情報が記憶できなくなってしまっているので、チューニングは必要ですね。

個人ごとの intent に沿った判断ができるようになって欲しい

エージェントを運用していると、ユーザー個々の“意図や好み”に合わせた判断が求められる場面が増えていきます。
たとえば:

  • “このユーザーは新品志向なのか、中古でも良いのか”

  • “価格より配送速度を重視しているのか”

  • “ブランド優先か、機能優先か”

これらは短期の会話だけでは判別が難しく、過去の行動・記憶の蓄積が重要になります。さらに、ユーザーがエージェントの提案を肯定したり否定した場合、その反応や理由をメモリにフィードバックして何が重要なのかや、何が好きなのか、といった判断基準を改善することができれば、翌日以降の提案精度は大きく向上するはずです。このようなユーザーとの会話からのフィードバックを反映させて、より高度なエージェントの運用したい場面は多くあります。しかし、調べた限りでは、 VertexAI の MemoryBank にはそのような機能はなさそうでした。Agent との会話ログやメモリを抜き出して別の LLM で判断させてメモリを上書きするような仕組みを作るとできるかもしれません。(追加で少し調査すると、AWS の Bedrock AgentCore Memory にあり、Episodic Memory Strategy で似たようなことができそうでした。)

まとめ

今回の調査では、Vertex AI Agent Engine の MemoryBank が
単なる「会話の長期記憶ストア」に留まらず、
実サービスにエージェントを統合した際に必要となる運用要件にも柔軟に対応できることを確認できました。

  • 会話前の記憶注入

  • 間違ったメモリの修正

  • 非同期なメモリ更新

  • 重視する要素のカスタマイズ

会話を通したユーザーインテントの理解とそのフィードバックなど、運用において求められる機能は増えてくるかと思いますが、それらも将来的には追加されることを期待したいと思います。

Discussion