とりあえず基盤は完成したので 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(発言制御エージェント)**
- グループ内の状況(誰が最後に話したか、誰が注目されているか)を判断し、次に発言すべきキャラクターを選定する専門エージェントを配置。
* **クロス・アウェアネス実装**
- 個々のキャラクターが、自分以外のキャラクターの動向やステータスを「共通状態管理テーブル」を通じて参照できるように設計。
* **実装方式**:
- 全員の履歴を単純結合するのではなく、オーケストレーターが「今回の出力に含めるべき会話のコンテキスト」をフィルタリングしてプロンプトを構築する。
- ユーザーが不在でも特定のトリガーや時間経過で自律的にメッセージを生成する仕組みの構築。
先日から進めているロールプレイチャットシステム開発を引き続き進めている。ユーザーマニュアルの目次だけ列挙。
1. 起動手順
2. 初回セットアップ
3. ユーザープロファイルの管理
4. キャラクターの管理
5. ロールプレイの開始
6. チャット画面の使い方
7. 画像生成機能(Draw Things 連携)
8. 記憶管理(Lore Book)
9. 設定の変更
10. バックアップと復元
こんな感じの機能というかそういうのが実装済み。スマホでの利用を考えて立ち絵表示は廃止してその代わりにDraw Thingsと連携してチャット画面内に生成画像を表示できるようにした。Draw Thingsが生成した画像ファイルはPNGでメタ情報も含まれていてそのままだとファイルサイズが大きすぎるからWebPに変換して持ってくるようになっている。記憶管理についてはチャット画面に整理ボタンを設置。クリックするとチャット内の会話内容などをLLMが処理して記録する。記録しておくと新規セッション時などに直近3つ分の記録と最大15件までのブックマーク済みの記録をもとに開始できる。SillyTavernのLore Book的な感じ。キャラクター管理ではキャラ用のシステムプロンプトとアイコン画像、画像生成用のポジティブプロンプトとネガティブプロンプトを入力できるようにした。
とか何とかやってたら肥大化したスパゲッティコードと化したので、日曜日をほぼ丸々使ってフロントエンドとバックエンドのリファクタリングを行った。機能ごとにファイルを分けたり、同じことをするのに重複している箇所の整理、開発中のテストコードが残ったままになっている箇所の削除などなどを行ってすっきりさせた。
今はUIテーマの色をカスタマイズできるように改修中。昨日ひとまず実装してみたけど色の変わらない部分があったりと、機能の設計段階から見直した方が良さそう。Gitでロールバックしてやり直すことにする。
と思ったらセッションが長くなった時の記憶データ生成処理が上手くいっていないな。先にこっちの修正が必要そう。
Open WebUIを利用してGemma4に小説書かせて遊ぶのに「モデル」機能を利用していたんだが、システムプロンプトは固定できるが、セッションをまたいで続きを書かせるために、登場人物を列挙したり状況を付与したり、あらすじをまとめたり、直前のシーンをまるごとコピペしたりと、引継ぎプロンプトを書くのがとてもめんどくさい。
どうにかならんのかと思ってClaudeに相談したらこんなのできるよ、とさらっとHTML+JS+CSSでたたき台を作ってくれた。よくよく考えたら仕様を決めてClaude Codeに作ってもらえばええやん、ということで、たたき台のHTMLを今度はGeminiに共有したうえでやりたいことも含めて仕様を決めて指示書を作成し、Claude Codeに大幅改修してもらった。現在の状態になるまでの作業時間は仕様決めもふくめて5時間ほど。

上記が実際の画面。どういった文体・ジャンルのものを書くのかとかの基本の固定ルールをシステムプロンプトに書いて、登場人物の名前とかを書いて、どういう展開を書きたいのかを書いて生成ボタンを押すと右側の欄に文章が出力される。出力内容の編集機能も付いてる。というか生成したテキストボックス内に文章が出力される感じ。OpenAI互換になってて画面上部でLLM動かしてるAPIサーバーのURLを指定してモデルを選択できる。LLMのサンプラー設定も画面下部の設定アイコンから調整可能。
上記は新規で書く時の画面だけど、続きを各モードがタブで分かれていて、そっちに切り替えるとキャラクターごとの前回時点での状況の入力やあらすじの自動生成およびあらすじ欄への入力ボタン、直近の2シーンをプロンプトカラムにコピペできるボタンなどが追加される。
あと、各種プロンプトなどはJSON形式でインポートとエクスポートができるようになってる。せっかくGemma4がマルチモーダルなので、画像ファイルを渡してこれについて小説書いて、ってのもできる。
ひとまず機能的には完成でいいかな。なんか文字が小さく薄くて視認性が低いのでそこは改善したい。なんというかClaude Codeが海外風デザインを気どった結果な気がする。
続けて作っているのは同じくOpenAI互換のローカルLLMサーバーと連動して動くロールプレイシステム。

ト書き付きの小説形式っぽいモードと、キャラクターの台詞のみのチャットモードを選んでセッションを開始できる仕組み。上の画像は小説モード。何故か設定画面の最大出力トークン数が512になっていたので出力途中で力尽きてる。ほかにもエンターキーですぐに送信されてしまうから入力欄の中で改行や文字の変換ができなかったりするから、色々と修正が必要。
スマホに対応させてるから同じLAN内であれば、ベッドでゴロゴロしながらスマホでチャットとかもできる。各種設定とかチャット履歴などは個別にエクスポート可能。加えて全データ・設定の一括エクスポートとインポート機能も付けてまるごとバックアップおよび復旧できるようにした。UI部分に関しては試行錯誤中。Claudeに完全にお任せにしたら妙な紫のが出てきたんだよね。フォントサイズやUIカラーを変更して保存できるテーマの切り替え機能とかを付けたいかな。どのようにキャラクターイラストを表示させたらそれっぽくなるのかとかあるし。
Gemini Proに壁打ちして仕様決め、Claudeの使用量は全部Claude Codeに回すって感じで作業している。そうしないとClaude Proプランでは遊びレベルでも使用量が厳しい。
とまぁ、そんなことをやってるのでゲームしてる暇が全くない。FGOとアズレンのイベント消化なんかも時間ギリギリになりがちである。