前提
AI girlfriend appやバーチャルコンパニオンのチャットでは、会話メモリを単純に「全部保存する」設計にすると、体験品質とプライバシーの両方で問題が出やすくなります。ユーザーにとって自然な継続性を作りながら、保存する情報を絞る設計が必要です。
本稿では、会話メモリを短期記憶と長期記憶に分ける実装方針を整理します。プロダクト例としては、落ち着いた会話体験を重視するAIコンパニオンのようなサービスで特に重要になる考え方です。
短期記憶の役割
短期記憶は、現在のセッションを自然に保つためのコンテキストです。数ターン前の話題、直近のユーザー意図、会話中に一時的に出てきた制約を保持します。
実装上は、モデルに渡す直近履歴、セッション内サマリー、一時的な状態オブジェクトに分けると扱いやすくなります。
interface ShortTermMemory {
recentMessages: ChatMessage[];
sessionSummary: string;
temporaryPreferences: Record<string, string>;
}
短期記憶は保存期間を短くし、セッション終了や一定時間後に破棄できるようにしておくと、過剰保存を避けやすくなります。
長期記憶の役割
長期記憶は、次回以降の体験を改善するための情報です。ユーザーの呼び方、好みの会話トーン、避けたい話題、よく話す趣味など、継続利用に意味があるものだけを対象にします。
重要なのは、長期記憶に入れる条件を明確にすることです。すべての発話を自動的に保存するのではなく、抽出ルール、ユーザー許可、削除導線を用意します。
interface LongTermMemoryItem {
key: string;
value: string;
sourceMessageId?: string;
confidence: number;
createdAt: string;
updatedAt: string;
}
境界を決める
短期記憶と長期記憶を分ける基準は、次のように考えると整理しやすいです。
- その場だけ必要な情報は短期記憶に置く
- 次回以降も明確に役立つ情報だけ長期記憶に昇格する
- センシティブな情報はデフォルトで長期保存しない
- ユーザーが見直し、削除できる形にする
この境界を曖昧にすると、会話は一時的に自然になりますが、後から監査しづらいデータが増えていきます。
LLMに渡すコンテキスト
長期記憶をそのまま大量にプロンプトへ入れると、トークンコストが増えるだけでなく、不要な個人情報を毎回参照することになります。プロンプトには、現在の会話に必要な項目だけを選んで渡すのが基本です。
function selectMemoryForPrompt(
userIntent: string,
memoryItems: LongTermMemoryItem[],
): LongTermMemoryItem[] {
return memoryItems
.filter(item => isRelevant(userIntent, item))
.slice(0, 8);
}
実際には、ルールベースのフィルタと埋め込み検索を組み合わせると運用しやすくなります。ただし、最初のMVPでは保存対象を絞るルール設計のほうが重要です。
まとめ
AI companion系のチャットでは、記憶は魅力的な機能である一方、プライバシーと信頼に直結します。短期記憶は会話の自然さ、長期記憶は継続利用の価値を担うものとして分離し、保存条件と削除導線を最初から設計に入れておくべきです。