会話トランザクト(Transcript)
会話トランザクトは、プラットフォーム:詳細タイプ:ターゲットIDという会話キーで整理された、ロボットが送受信したメッセージを自動的に記録します。
この記録は、対話の復元(event.history)、影分身モジュールのdiff、冷起動時の再現などに使用される履歴データを提供します。
本ドキュメントでは、ストレージモデル、各保留ポリシーのスイッチが何を保護しているか、および、実行時のオーバーライドAPIと制限の緩和がもたらす実際のコストについて説明します。
制限を変更する前に、「リスクと監査」セクションを必ずお読みください。各スイッチには、その存在理由があります。
動作原理
メッセージ ──append()──▶ 書き込みバッファ(メモリ deque、ハード上限 4096 行)
│ 1 秒ごとにバッチで一時保存(1 バッチ ≤64 行、1 トランザクション)
▼
storage バックエンドの transcript テーブル(デフォルトは sqlite)
│ 約 32 行追加ごとに遅延実行で保持クリーンアップをトリガー
▼
┌─ セッションごとに FIFO で裁断(max_per_session、デフォルト 50 行)
└─ グローバルな TTL 削除(ttl_hours、デフォルト 168 = 7 日)
3 つの階層の保護が、それぞれ異なるリスクを防いでいます:
| 旋钮 | デフォルト値 | 保護対象 | 無効化(=0)時の結果 |
|---|---|---|---|
| 書き込みバッファ上限 | 4096 行(定数、設定不可) | メモリ:ストレージ利用不能時の蓄積が RAM をオーバーフローしないように | 無効化不可——これはメモリの防衛線です |
| 単条テキストの切り詰め | 2000 文字(定数、設定不可) | 単条メッセージのメモリ/ディスク使用量 | 無効化不可 |
max_per_session |
50 条/セッション | ディスク成長:1 セッションの履歴が無限に蓄積されるのを防ぐ | そのセッションの履歴が無限に成長します |
ttl_hours |
168(7 日) | ディスク成長:全セッションの長期蓄積を防ぐ | transcript テーブルが無限に成長します |
重要な認識:書き込みバッファにはハード上限があるため、保持戦略を緩めても直接メモリがオーバーフローすることはありません; 本当のリスクはストレージ層と下流のコンシューマー(次節参照)にあります。
設定
[ErisPulse.transcript]
enabled = true # 自動記録を有効にするかどうか
max_per_session = 50 # 1セッションに保持する件数(0 = セッションのクリッピングを無効化)
ttl_hours = 168.0 # グローバルな保持期間(時間、0 = 保持期間なし)
環境変数による上書きも有効です:ERISPULSE_TRANSCRIPT_MAX_PER_SESSION、ERISPULSE_TRANSCRIPT_TTL_HOURS。
設定の変更はホットで有効になります(バッファリングの書き込み間隔内で、最大で約1秒の遅延)。
[docs/ja/quick-start.md]
実行時オーバーライド API
実行時に動的に調整する必要がある場合(例:特定のシナリオで一時的に保持期間を延長する):
from ErisPulse import transcript
# オーバーライド(設定値を上書き;メモリ内に保持されるため、再起動後に設定値に戻る)
transcript.set_retention(max_per_session=500, ttl_hours=24 * 30)
# 有効な値とそのソースを取得
transcript.get_retention()
# {'max_per_session': 500, 'ttl_hours': 720.0, 'overridden': ['max_per_session', 'ttl_hours']}
# 設定に従って復元
transcript.reset_retention()
0を渡すと、対応するポリシーを無効化し、警告ログを出力して記録します。負数を渡すとValueErrorが発生します。- オーバーライドは次の保持クリーニング時に有効になります(遅延実行、最大で ~32 件の追加のリズムまで遅れることがあります)。
transcriptシングルトンは、ルートパッケージからインポートすることも、sdk.transcriptからインポートすることもできます。
風険と監査:制限を解放する前に必ず読む
max_per_session / ttl_hours を無効化(または大幅に大きく設定)した後、transcript テーブルはメッセージ量に応じて無制限に成長します。その結果は以下のとおりです。
- ディスクがいっぱいになる —— sqlite の単一ファイルが継続的に膨張し、ディスクが枯渇した後はフレームワークのストレージ層が利用できなくなります。
- クエリの性能低下 ——
get()/recent()/get_by_trace()のスキャンコストはテーブルの成長に伴って増加します。 - 下流のメモリ圧力(OOM の本当の原因) —— 歴史セッション全体をメモリに読み込むコンシューマー(セッションの履歴付き再開、パネルの全量取得、および
get(session, n)で大きな n を取得するあなたの業務コード)はテーブルの成長とともにメモリを消費し、極端な状況では OOM kill を引き起こします。
解放する前に自問すべき3つの質問:どのくらいの期間の履歴が必要ですか?どのくらいの容量が必要ですか?誰がデータの削除を行う予定ですか?もし「削除しない」という答えが依存している場合は、正しい方法は通常、外部アーカイブ(定期的に古いデータを専用のデータベースに移す)です。受信箱に無制限にデータを保持するのではなく、適切な管理を行うべきです。
監査手段(定期的にテーブルのサイズを確認する方法):
# ORM/SQL ビルダーを経由して行数とサイズを確認(sqlite 例)
from ErisPulse import storage
row = storage.Table("transcript").raw_sql("SELECT COUNT(*) AS n FROM transcript")
-- sqlite ファイルに対して直接クエリを実行(テーブルのサイズ)
SELECT COUNT(*) FROM transcript;
保留戦略が無効化されました という warning ログが記録された場合 = 0 で戦略を無効化した人がいることを意味します。これは自分の操作であることを確認してください。
他のメカニズムとの境界
- インタラクティブセッションタイマー / wait_reply:インタラクティブセッションシステムを参照。受信箱とは無関係。
- 会話の再開時の履歴の持ち込み:
resume(with_history=N)は受信箱から最近の N 条を取得する。受信箱が切り詰められた場合、持ち込み可能な履歴数が減少する(max_per_sessionを大きくすることで、再開可能な期間を延長できる)。 - 影のモジュール diff:
get_by_traceチェーンによるクエリに依存する。TTL が短い受信箱は、diff 可能な期間を短くする。