コンテンツへスキップ
DedicatedPHP 接触

PHPの会話メモリ:ユーザー間・組織間でコンテキストを分離する方法

PHPアシスタントのメモリを設計し、コンテキストを混在させることなく、各会話でユーザーの本人性、所属組織、現在の権限を確実に尊重する方法を解説します。

PHPアプリケーションでユーザーと組織ごとに会話を分離する概念図

アシスタントが別の人や企業の情報を使って回答した場合、問題は品質だけではありません。プライバシーやアクセス制御の侵害につながる可能性があります。マルチユーザーのPHPアプリケーションでは、会話メモリを、所有者、適用範囲、ライフサイクルが明確なデータとして扱う必要があります。メッセージを保存し、セッションIDで取得するだけでは不十分です。

PHPアプリケーションにおける会話コンテキストの分離とは、回答の生成に使う情報が現在の会話に属し、引き続き利用を許可されていることを保証することです。これには過去のメッセージ、要約、取得したあらゆるデータが含まれます。ドキュメント検索はコンテキストを補完できますが、アクセスルールと目的は会話メモリとは異なります。

会話メモリ、履歴、ドキュメントを分ける

会話メモリ、履歴、ドキュメントを分ける — guía visual de DedicatedPHP

履歴は、会話内のメッセージをすべて記録したものです。一方、メモリは、直近のやり取りや更新済みの要約など、特定のタスクのためにアプリケーションが取得すると決めた部分集合です。検索で取得したドキュメントは別の情報源であり、クエリとドキュメントへの権限に基づいて選択されます。これらを混同したり、ユーザーが発言したメッセージであるかのように保存したりしてはいけません。

この区別により、検証可能な判断がしやすくなります。監査や製品上の理由から履歴を保持しつつ、モデルに送るメモリを制限できます。また、各ドキュメントの断片には、それぞれの出典とアクセス制御を維持できます。出典を識別せずに混在させると、どのデータが回答に影響したのかを説明しにくくなり、保持ポリシーの適用も困難になります。

各会話の所有者を定義する

データ取得の設計に着手する前に、会話を識別する安定した方法を定めてください。少なくとも、次の点を考慮します。

  • 会話:ランダムまたは予測困難なIDを使い、IDを知っているだけでアクセス権が得られるとは見なさない。
  • ユーザー:やり取りを開始した、または閲覧権限を持つ認証済みユーザーの本人性。
  • 組織:複数の企業やワークスペースで運用する場合に、データが属する範囲。
  • 現在の権限:初期権限を無期限に複製するのではなく、読み取りのたびに評価する認可。

Webセッションはリクエストの認証に利用できますが、永続的な所有者を特定する唯一のキーにすべきではありません。会話が保存されている間に、ユーザーがログアウトしたり、組織を切り替えたり、権限を失ったりする可能性があります。リクエストごとに、現在のユーザーがアクティブな組織内でその会話にアクセスできることをアプリケーションが確認する必要があります。

コンテキストの変更時にどうするかも明示的に定義してください。組織を切り替えた場合、以前の会話を続けられるのか、新しい会話を開始する必要があるのか、それとも承認済みの要約だけを引き継げるのか。普遍的な正解はなく、製品とプライバシー要件によって異なります。その判断は、UIに暗黙の前提を置くのではなく、検証可能なルールに反映してください。

コンテキスト取得前にアクセス範囲を適用する

認可は、データをプロンプトに含める前に、取得クエリの一部として適用する必要があります。先に広範なデータを取得してからPHPで絞り込む方法では、エラー、別のコードパス、デバッグログなどによって無関係な内容が露出するリスクが高まります。

リレーショナルデータベースでは、会話ID、認可されたユーザー、組織を同時にクエリ条件に含められます。概念的な例を示します。

SELECT message_id, role, content, created_at
FROM conversation_messages
WHERE conversation_id = :conversation_id
  AND organization_id = :organization_id
  AND conversation_id IN (
      SELECT conversation_id
      FROM conversations
      WHERE owner_user_id = :user_id
         OR EXISTS (/* 有効なアクセス許可を確認 */)
  )
ORDER BY created_at DESC
LIMIT :message_limit

実際のスキーマは異なる場合がありますが、重要なのは、アクセス範囲によって取得対象のレコードを制限することです。読み取り、書き込み、エクスポート、削除の各操作で、バインドパラメーターと一貫した認可レイヤーを使用してください。ベクトルデータベースや検索サービスを使う場合は、組織と権限による制約を検索クエリに適用する必要があります。未認可の結果を無視するようモデルに指示するだけでは不十分です。

ドキュメント検索と会話メモリを組み合わせる場合は、それぞれの情報源に対応する認可を先に適用してください。出典のメタデータを保持し、明示的なポリシーなしにドキュメント検索の結果を恒久的なメモリへ変換しないでください。

キャッシュ、キュー、共有コンポーネントでの混在を防ぐ

データベースへのアクセスが正しくても、ほかのレイヤーで状態を共有していれば分離は保証されません。conversation:123のようなキャッシュキーは、同じIDが複数の範囲で使われる、再利用される、またはキャッシュ設定によって衝突する場合には不十分な可能性があります。キーには組織IDと会話IDを含め、必要に応じて権限やデータのバージョンも含めてください。機密情報をキーの一部にしてはいけません。

バックグラウンドジョブには、組織、会話、実行主体、ジョブの目的からなる、必要最小限で明示的なコンテキストを渡してください。実行時には、ジョブが引き続き認可されていること、共有グローバル状態から取得した本人性を使っていないことを改めて検証します。特に永続的なPHPプロセスでは、static変数、ユーザーデータを変更可能な状態で保持するsingletonサービス、リクエスト間で再利用されるセッションオブジェクトを避けてください。

エラーと再試行時の挙動も定義してください。再試行されたジョブが別プロセスの状態によって組織を切り替えることがあってはなりません。また、ポリシー上、権限の取り消し時に無効化が必要なら、キャッシュされた応答がその後も残ってはいけません。挙動は意図的に設計し、観測可能にしてください。

タスクに必要な範囲にメモリを限定する

分離することは、履歴全体をモデルに送ることではありません。現在のリクエストに役立つ直近のやり取りや要約を、件数とサイズの上限を設けて取得してください。情報の有効性も考慮します。古い設定、修正されたデータ、取り消された決定を、自動的に現在の事実として扱うべきではありません。

要約を使用する場合は、その適用範囲と出典を保存し、明確なルールに従って更新してください。要約は信頼できる情報源ではなく、権限確認の代わりにもなりません。重要なデータについては、過去の会話に保存された記述を信頼するのではなく、認可された記録システムを参照してください。コンテキストウィンドウを小さくすれば露出とコストを抑えられますが、認可の誤りを補うことはできません。

ある会話が別の会話に影響しないことをテストする

テストでは、許可されるアクセスと拒否されるアクセスの両方を確認します。異なるユーザーや組織のケースを作成し、あるリクエストで別の本人性に属するメッセージ、要約、ドキュメントが取得されないことを検証してください。次のような境界ケースも含めます。

  • ユーザーが組織を切り替え、以前の会話IDを再び開く。
  • 会話の作成後、メモリの取得前に権限が取り消される。
  • 2人のユーザーが同時にアクセスし、プロセス、キャッシュ、キュー基盤を共有する。
  • 存在しないIDや他人に属するIDに対し、別の人のものかどうかを明かさず、制御された応答を返す。
  • 権限または組織の変更後にジョブが再試行される。

単体テストに加え、認証済みリクエストからコンテキスト構築までの一連の処理をテストしてください。別々の会話に目印となるメッセージを入れ、それぞれについて取得結果に相手側の目印が決して含まれないことを検証できます。目標は、モデルが説得力のある回答を書くかどうかではなく、データ境界を検証することです。

機密情報をログに記録せずにインシデントを調査する

機密情報をログに記録せずにインシデントを調査する — guía visual de DedicatedPHP

オブザーバビリティを確保しつつ、プライベートなメッセージをログに複製せずに処理の流れを追跡できるようにします。適切な技術ID、認可の判断、取得件数、データの出典、各段階の所要時間と結果を記録してください。可能であれば仮名化したIDを使い、ログへのアクセスと保持期間を制限します。

予期しない空の取得、組織の不一致、異常に高い拒否率、適用範囲外でのキャッシュキーの再利用などの兆候は、障害の検出に役立ちます。デフォルトでは、プロンプト全文、ドキュメント、回答を記録しないでください。詳細な診断が必要な場合は、機密データをマスキングし、期間と範囲を限定した、承認済みの一時的な手順を定めます。

安全な設計では、コンテキストの各断片について、所有者、適用範囲、有効性を明示します。クエリ、キャッシュ、非同期ジョブにこれらのルールを適用し、拒否されるケースを検証することで、分離はアシスタントに期待を委ねるのではなく、PHPアプリケーションの検証可能な特性になります。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る