David

くらちゃんや、Agentのデータと記憶を支えるData Brainの開発を進める中で、私たちは「一度覚えたことを、どう正しく更新し続けるか」という問題に向き合ってきました。その問題を研究として整理したのが、共同研究による論文 MemShift: Separating Detection from Repair in LLM-Derived Personal Memory です。本稿では、記憶が古くなる理由から、評価の設計と実験で見えてきたことを順に解説します。

「覚えている」と「今も正しい」は違う

たとえば、AIアシスタントが「あなたの重要な連絡先はAさんとBさんです」と覚えていたとします。その根拠は、カレンダーや連絡履歴をもとにした「直近30日で3回以上、個別の打ち合わせをした相手」というルールです。

これは、どこかの文書をそのまま保存した情報ではありません。複数の記録を集め、本人の基準に沿って計算した結果です。論文では、このような項目を definition item、つまり本人の定義から導いた記憶として扱います。

ここで、打ち合わせの予定が修正されたり、記録が削除されたり、「重要」の基準が変わったりすると、保存したリストは古くなります。さらに、何も書き加えなくても時間は進みます。昨日まで「直近30日」に入っていた打ち合わせが、今日は対象から外れるかもしれません。

記憶を維持するには、新しいメッセージを追加するだけでは足りません。どの条件で作られ、何が変わると見直す必要があるのかを扱う必要があります。

更新の失敗を、二つに分ける

MemShiftが分けて考えるのは、次の二つです。

  • 検知(Detection):元データや定義の変化に気づき、影響する記憶を更新対象にする。
  • 修復(Repair):現在のデータと定義から、正しい値をもう一度導く。

最終回答だけを採点すると、どちらの失敗も同じ誤答になります。しかし、直し方は違います。

変更に気づかなかったのであれば、依存関係やバージョンの管理が問題です。変更を検知したうえで再計算を間違えたのであれば、必要なデータの渡し方や、値を導く処理を見直す必要があります。

元データ・定義・時刻の変化を検知し、現在の条件で記憶を再計算する二段階の流れ。検知漏れと修復失敗を別々に記録する。

図1|記憶更新の二つの仕事。変化に気づいたことと、正しい記憶に直せたことを分けて見る。

論文は、変化した項目への正答率(Update)を、次の式で整理します。§3.4・式1

数式
Update=(1−m)r+ma\mathrm{Update}=(1-m)r+ma

ここで、m は更新対象として検知できなかった割合、r は検知して再導出した項目の正答率、a は検知しなかった項目に対して返した回答の正答率です。検知しなくても、後から追加された情報でたまたま正答することはあります。その経路も含めて、全体を分解しています。

この式が伝えるのは、検知を改善した効果は、その後の修復がどれだけ正しくできるかに左右されるということです。

五つの変化を、同じ条件で比べる

MemShiftでは、架空の一人の生活を12か月にわたって生成します。メール、チャット、カレンダー、連絡先、タスク、ノートの6種類の情報源があり、1つの世界には約1,500〜1,650のイベントが含まれます。

評価する記憶は48項目です。勤務先や予定などの42項目に加えて、「重要な連絡先」「親しい友人」「進行中のプロジェクト」など、本人の定義に基づく6項目があります。

評価では、次の五つの変化を扱います。§3・表1

変化 何が変わるか 確かめたいこと
元データの修正 予定や所属などの記録 新しい状態に更新できるか
削除 参照していた記録がなくなる 古い値を返し続けないか
定義の変更 「重要」「進行中」などの判断基準 記録が同じでも計算し直せるか
書き手モデルの切り替え 記憶を作るモデル 正しく保持していた内容が残るか
エクスポート・インポート 記憶を扱う実装 値と更新に必要な情報を引き継げるか

最初の三つは、同じ世界から分岐を作り、対象の変化以外をそろえて比較します。正解の値と依存する記録は、文章を生成する前に決まっています。採点もLLMの評価ではなく、日付・時刻・集合・状態などを決定的に照合します。

定義の変更では、記録そのものを変えません。モデルの切り替えとエクスポートでも、元の世界の正解は変わりません。「新しい文章を読んで答えを変える」だけでは調べにくい記憶の性質を、切り分けて測る設計です。

気づけば直る、とは限らない

検知と修復を別々に操作するため、論文では参照実装 HoldMem を用意しています。

検知を有効にすると、情報源のイベント数、定義のバージョン、書き手モデルを記録したキーを使い、変化があれば記憶を無効化して再導出します。修復には、LLMによる再導出、LLMが書いたプログラムによる計算、正解と同じ規則を使う厳密な再計算を比較します。

次は、Qwen3.5-9Bを記憶の書き手・読み手に用い、20の12か月世界で測った、定義変更後の変化した項目全体への正答率です。表3

修復方法 検知キーなし 情報源のキーあり
LLMによる再導出 26.9% 27.1%
LLMが書いたプログラム 45.0% 70.4%
厳密な再計算 64.7% 91.6%

定義変更後のUpdateを比較した図。LLM再導出はキーなし26.9%、あり27.1%。LLMが書いたプログラムは45.0%から70.4%。厳密な再計算は64.7%から91.6%。

図2|検知の効果は修復方法で変わる。20の合成世界、Qwen3.5-9B、定義変更後の変化した全項目(558項目時点)。厳密な再計算は修復の上限を見るための比較条件。

LLMによる再導出では、キーを足しても26.9%から27.1%への変化にとどまりました。再計算の方法を変えると、検知によって得られる改善が大きくなります。

特に難しかったのが、複数の記録を集計するdefinition itemです。論文で評価した4種類のオープンウェイトモデルは、変化したこの種の項目を再導出した際の正答率が各変化で最大でも25%でした。一方、厳密な再計算は91%以上でした。§6.1・表16

ここでの厳密な再計算は、43項目について正解生成と同じ評価器を使う条件です。完成した製品の性能ではなく、修復が正しければ検知の効果をどこまで得られるかを見る上限です。また、情報源全体を監視するキーは、この実験では変化していない項目もほぼ毎回更新しており、実質的に全体のリフレッシュとして動いています。

文章を読み直す代わりに、定義を実行する

「最近よく会う人」を数えるために、毎回LLMにすべての予定を読ませる必要があるでしょうか。

条件が明確で、必要なレコードが構造化されていれば、集計そのものはプログラムに任せられます。LLMには、本人の言葉で書かれた定義を、どのデータに対するどんな処理にするかを担当させる。この役割分担を試したのが、論文の「書き手が生成したプログラム」です。

先ほどの「直近30日で3回以上、個別に打ち合わせをした相手」を、簡略化したPythonで表すと次のようになります。

python
from collections import Counter
from datetime import timedelta

def important_contacts(live_meetings, now, days=30, minimum=3):
    cutoff = now - timedelta(days=days)
    counts = Counter(
        meeting["person"]
        for meeting in live_meetings
        if meeting["one_off"]
        and cutoff <= meeting["at"] <= now
    )
    return sorted(
        person
        for person, count in counts.items()
        if count >= minimum
    )

入力は、削除済みの予定を除いた現在のレコードです。at と now は同じ時刻基準の datetime とします。これは考え方を示す説明用コードで、論文の実装そのものではありません。

日数や回数の定義が変われば、対応する値や処理を変えて再計算する。日付が進んだ場合も、現在時刻を使って対象を選び直せます。ただし、再計算を呼び出すタイミングは別途必要です。関数が正しくても、実行されなければ記憶は古いままです。

実験では、LLMが書いたプログラムは、厳密な再計算との差の多くを埋めました。同時に、削除済みレコードに対して値を返してしまう失敗もありました。プログラムが正常終了したことと、正しい状態を返したことは別です。§6.2・表25

モデルの能力と渡す情報にも影響されます。定義に関わる全レコードを構造化した形で渡したClaude Sonnet 5.5は、変化したdefinition itemの91.8%に正答しました。選択された情報だけを渡した場合は50.0%でした。したがって、この研究の結論は「LLMには集計ができない」ではなく、修復方法、情報の網羅性、実行コストを一緒に設計する必要があるというものです。§6.2・表15

過去の引用だけでは、次の変化を追えない

出典を残すことは、記憶を更新するうえでも役に立ちます。しかし、「前回の答えを作るときに引用した記録」だけを監視していても、十分とは限りません。

たとえば、前回の重要な連絡先リストにCさんは入っていませんでした。その後、Cさんとの打ち合わせが増えて、条件を満たしたとします。新しく追加された予定が前回の引用先に含まれていなければ、引用先の変更だけを監視する仕組みは、この変化を見落とすことがあります。

過去の回答の引用先だけを監視する方法では、新しく条件を満たしたCさんの記録を見落とす。情報源・対象条件・定義のバージョン・時間の変化まで追跡する必要がある。

図3|「前回使った根拠」と「次に答えを変えうる入力」は一致しない。

論文の引用ベースのキーは、定義のバージョンも持つため、定義変更そのものが引き起こした222件の変化はすべて検知しました。それでも、その後のレコードや時間の変化を見落とします。定義変更後の変化した項目全体で見ると、検知漏れは32.4%でした。§6.3

必要なのは、過去の引用に加えて、今後対象に入りうる情報源や条件、定義のバージョン、時間の境界を扱うことです。たとえば「直近30日」という記憶には、新しい予定の通知だけでなく、古い予定が期間外になるタイミングも関係します。

記憶を持ち運ぶとき、値以外に何を残すか

別のモデルやサービスへ記憶を移すときも、同じ問題が現れます。

「重要な連絡先はAさんとBさん」という文章だけが残っても、どの定義で、どの時点の情報から導いたのかが分からなければ、その後の更新を続けにくくなります。

論文では、キーを含めてエクスポートした記憶は、別の実装へ移した後も元の実装と同じ結果になりました。一方、キーを除いた条件では、その後の変化を検知しませんでした。この比較は、同じデータモデルを共有する2実装間で行われています。§6.3・付録F.10

持ち運ぶ対象には、記憶の文章や値だけでなく、更新を続けるための依存関係やバージョンも含まれます。

記憶を、更新できる状態として設計する

MemShiftから得られる設計上の示唆は、記憶のライフサイクルを分けて扱うことです。

  1. 何から導いたかを残す。 元データの識別子、定義、バージョンを管理する。
  2. いつ見直すかを決める。 修正・削除だけでなく、新しく対象に入る記録や時間経過も扱う。
  3. どう導き直すかを選ぶ。 明確な集計は構造化データとプログラムを使い、文章理解と計算の役割を分ける。
  4. 値と状態を一緒に扱う。 削除された記録に依存する古い値を撤回し、答えられない状態やアクセス権を表現する。
  5. 失敗した段階を測る。 正答率に加えて、検知漏れと修復の正しさを項目の種類ごとに確認する。

評価には、正解を厳密に定められる合成データと、構造化した定義が使われています。実際のメールの曖昧さや、本人の基準を聞き出す難しさは、次に検証すべき課題です。

一度作った記憶が正しかったとしても、その正しさが続くとは限りません。変化を見つけ、必要な記憶を見直し、現在の条件で正しく導き直す。 MemShiftは、この一連の仕事を診断できるようにする研究です。

論文・コード

  • Zichuan Xu, Haochen Zhang, Yuyang Dong, Makoto Onizuka, Chuan Xiao. MemShift: Separating Detection from Repair in LLM-Derived Personal Memory. arXiv:2611.02338v1, 2026年11月2日。
  • 論文概要 · PDF · コード・再現手順

本文の図は、論文の設定・結果をもとに本稿用に構成しています。