ロールプレイチャットシステムを開発中その2
- Category: 生成AI関係
とりあえず基盤は完成したので v1.0.0 とする。更新履歴は以下の通り。
## [1.0.0] - 2026-04-24
### Added
#### コアチャット機能
- LM Studio(OpenAI互換エンドポイント)との双方向チャット連携
- ストリーミング生成(`/chat/stream` SSE)およびストップ機能
- チャットセッション管理(作成・削除・履歴閲覧)
- メッセージ送信履歴を直近15往復に制限し、トークン超過を防止
- Thinking(思考モード)のオン/オフ切り替えとフロントエンド表示
#### キャラクター・ユーザー管理
- キャラクタープロファイル(名前・設定・システムプロンプト・画像)の作成・編集・削除
- ユーザープロファイル(呼称・自己紹介など)の管理
- キャラクター別アイコン画像のアップロードと静的配信(`/images/`)
#### 長期記憶システム
- チャット後の記憶自動抽出(差分方式、手動トリガー)
- 記憶のピン留め・ブックマーク機能
- キーワードフィルタリングと全ピン解除
- 記憶の編集・削除
- 記憶インデックスのリセット機能
- 外部記憶(Lore Book)の管理機能
#### 画像生成連携
- Draw Things(ローカル画像生成サーバー)との連携基盤
- チャット内からの画像生成トリガーとプレビュー表示
- メッセージ・セッション削除時の関連画像ファイルの自動削除
#### バックアップ
- プロジェクトデータのZIPバックアップ機能
### Changed
#### データ基盤(Pydantic移行)
- キャラクター・ユーザー・記憶・チャット・システム設定の全モデルを `models.py` でPydanticクラスとして定義
- バックエンド全体でJSONの読み書きをPydanticモデル経由に統一し、型安全性と保守性を向上
#### UIテーマ・スタイル
- CSSカスタムプロパティ(CSS変数)によるテーマ管理を導入
- プリセットテーマ(ライト・ダーク・各種カラーテーマ)の選択機能
- ハードコードされた色定義をすべてCSS変数に置換
- カスタムテーマ作成・保存・切り替え機能(バグ修正済み)
#### フロントエンドアーキテクチャ
- `ChatArea.jsx` を8つのサブコンポーネントに分割
- ロジックをカスタムフック(`useChat` 等)に分離
- パーサー関数・共有UIコンポーネントを独立ファイルに切り出し
- LLM通信処理の共通化
#### バックエンド整理
- `memory.py` のリファクタリングと不要コードの削除
- ルーター構成の整理(`character` / `user` / `memory` / `chat` / `system` / `image`)
- `vite.config` にローカルIPアドレスを追記(LAN環境からのアクセス対応)
### Fixed
- ユーザープロファイルで指定した呼称がLLMに反映されない不具合
- 記憶抽出結果が英語になるバグ
- 記憶生成時のトークン不足エラーへの対処(プロンプト最適化)
- Thinking出力の表示漏れ
- Draw Things連携の各種バグ
- カスタムテーマ切り替え時の表示崩れ
今後の構想としては以下の通り。実現できるかどうかわからない。あとUIも改善したいところ。
## 1. LLMサーバーと画像生成APIについて
- クラウドAPIやローカルのOllamaなど、任意のLLMを利用できるようにする。
- 画像生成についてもComfyUIに対応したいし、同一ネットワーク内の別端末のAPIを叩けるようにする。
## 2. 非同期エージェント・パイプライン
メインの生成処理を待たずに(あるいは並行して)外部情報を取得・処理する設計。
* **生成フローの分離**
- **Pre-generation**: 入力直後に実行(例:ユーザー入力の要約、感情分析)
- **Parallel**: メイン生成と同時に実行(例:画像生成プロンプトの作成)
- **Post-generation**: 出力完了後に実行(例:レスポンスの反省、スロット更新)
* **技術的要点**:
- Node.jsの `Promise.all` 等を使用した非同期処理によるUXの最適化。
- 各エージェントに個別のプロンプトを注入し、結果を最終プロンプトに統合するオーケストレーション。
- 現在の構成の場合、Pythonでの非同期実装では async/await が標準らしい。エージェント処理(思考や検索)をすべて async で定義し、複数のLLM呼び出しを asyncio.gather() で並行実行すれば、Node.jsのPromiseと遜色ないパフォーマンスが出るとのこと。
## 3. 状態管理(Tracker System)
会話履歴とは別に、世界の「状態」を保持する専用のデータベースレイヤー。
※ベクター検索(RAG)も活用?
* **Trackerの役割**
- **World State**: 日時、天気、場所、登場人物。
- **Character Stats**: 感情値、好感度、装備、ステータス。
- **Quest/Lore**: 進行中のクエスト、フラグ管理。
* **実装方式**:
- 会話のたびにエージェントがTrackerテーブルを更新。
- LLMへ送信する際、System Promptの末尾に、現在の「状態」を構造化データとして注入する。
## 4. モデルの適材適所(Dynamic Routing)
タスクの難易度に応じて、ロードするモデルや呼び出すプロバイダーを切り替える仕組み。
実行環境によってはLLMモデルを複数同時にロードすることも検討。
* **階層化モデル構成**
- **Reasoning Tier**: 思考、計画、状態更新を担当(軽量モデルで高速化)。
- **Generation Tier**: 描写、会話、ロールプレイを担当(大規模モデルで高品質化)。
- **投機的サンプリング** の導入も検討。
## 5. プロンプトのモジュール化(Depth Injection)
一枚岩のSystem Promptを廃し、ブロック単位で管理する仕組み。
* **構成要素**:
- Persona(キャラクター定義)、World Info(世界観)、State(Tracker情報)、Instruction(行動指示)。
## 6. マルチキャラクター・オーケストレーション
複数キャラクターが共存し、相互作用するための仕組み。
* **Response Orchestrator(発言制御エージェント)**
- グループ内の状況(誰が最後に話したか、誰が注目されているか)を判断し、次に発言すべきキャラクターを選定する専門エージェントを配置。
* **クロス・アウェアネス実装**
- 個々のキャラクターが、自分以外のキャラクターの動向やステータスを「共通状態管理テーブル」を通じて参照できるように設計。
* **実装方式**:
- 全員の履歴を単純結合するのではなく、オーケストレーターが「今回の出力に含めるべき会話のコンテキスト」をフィルタリングしてプロンプトを構築する。
- ユーザーが不在でも特定のトリガーや時間経過で自律的にメッセージを生成する仕組みの構築。