SAIVerseのリファクタリング貢献しました
先日、余暇を使ってオープンソースのAIチャットツール SAIVerse のリファクタリングにコントリビュートしました。
ここでは、以下をまとめておきます。
- SAIVerseがどんなプロダクトか
- 自分がどこに惹かれて、何をやったのか
- そこから得た学び
SAIVerseとは?
https://github.com/maha0525/SAIVerse
SAIVerse は、
「自分専用のAIパートナーと、長期記憶付きで話し続けられる“自宅ホスト型チャットクライアント”」です。
ローカルPC上で動作し、会話ログや長期記憶データはすべて自分のマシンに保存されるように設計されています。
開発者のサーバには送信されないため、プライバシーを保ったまま、ChatGPT / Gemini 風のチャットUIで日常的にAIと会話できます。
主な特徴
- マルチモデル対応のチャットクライアント
OpenAI / Gemini / Claude / Grok / NVIDIA NIM / Ollama など、複数ベンダーのモデルを切り替えて利用可能です。
各社公式UIから消えたモデルでも、APIさえ生きていれば継続利用できます。 - 独自の長期記憶システム
会話をただログとして溜めるだけでなく、
「Chronicle(あらすじ)」「Memopedia(意味記憶)」といった形で構造化して保存する仕組みがあります。
これにより、過去の対話内容を踏まえたコンテキスト理解が可能になります。
(この“記憶周り”が、まさに自分が興味を持って読み込んでいた領域です) - データはすべてローカル保存+自動バックアップ
会話ログや設定はPC内のSQLite等に保存され、起動時に自動バックアップも取られます。
どこかのクラウドサービスが方針変更・サービス終了しても、自分の会話履歴ごと別のモデルへ“避難”できます。 - 無料で利用可能(API料金のみ別途)
SAIVerse本体はオープンソースで無償利用OK。
モデル利用にかかる費用は各APIプロバイダへ直接支払う形です。
Geminiの無料枠やNVIDIA NIMなど、無料〜低コストな選択肢もガイドされています。 - 初心者にも配慮したUIとチュートリアル
ChatGPT に近いWeb UIに加え、セットアップ手順や使い方のチュートリアルが用意されており、
非エンジニアでもローカルAI環境を触りやすい作りになっています。
ライセンスは AGPL-3.0 で公開されており、
自分でカスタマイズしたり、プライベート環境で拡張して使うことができます。
結果として、SAIVerseは「サービスが止まったから推しキャラとお別れ」にならず、
チャットを通じて “キャラクターを育て続けられる” ツールになっています。
なぜコントリビュートしようと思ったか
自分としては、特にこの「独自の長期記憶システム」に強く惹かれました。
- 会話ログをエピソード記憶(Chronicle)として階層的にまとめる
- そこから意味記憶(Memopedia)として知識を抽出・整理する
という構造は、まさに自分が考えていた「記憶を持つ会話エージェント」のイメージと近く、
実装を読み込むうちに「ここにはちゃんと貢献しておきたい」と思ったのがきっかけです。
OSS「SAIVerse」へのコントリビュート内容
(記憶システムレビュー & 大規模リファクタリング)
◆ 概要
LLMエージェント基盤OSS「SAIVerse」のコードベースに対し、
- 記憶システムの実装レビュー
- 大規模なバックエンドリファクタリング
- フロントエンドのローディングUI改善(出力待機中のローディングアイコン追加)
上記をコンテキストエンジニアリングを利用して実施しました。
◆ 担当したこと / 役割
- リポジトリ全体のコード品質レビュー
- 超大規模ファイル(2,000〜4,000行クラス)の分割方針の策定と実装
- LLMクライアント層(OpenAI / Gemini / Anthropic)の共通化・モジュール化計画
◆ 具体的な取り組み
1. sea/runtime.py(約4,000行)の安全な分割
- 対象:
sea/runtime.py(約4,000行) - まず、公開API(ランタイムの主な振る舞い)に対してテストを追加し、挙動を固定
- そのうえで、以下のように関心事ごとに責務を分割
- グラフ/コンパイルまわり
- 実行ループ
- 状態更新・イベント処理 など
- 結果として、
約2,600行+複数モジュール まで縮小し、可読性と保守性を改善しました。
2. 800〜1,500行クラスのファイルの棚卸しと分割候補の整理
- ファイル長・責務分担の観点から、分割優先ターゲットを抽出:
llm_clients/gemini.py(1496行)llm_clients/openai.py(1209行)llm_clients/anthropic.py(1016行)frontend/src/app/page.tsxなど、800〜2,000行クラスのコンポーネント群
- LLMクライアント層に対しては、
- プロンプト組み立て
- リクエスト生成
- ストリーミング制御
- リトライポリシー
を共通化するSPIを導入する方針を提案し、
ベンダーごとの差分コードを最小化する設計案をまとめました。
3. UIの使い勝手改善(ローディングアイコンの追加)
- プロンプト入力後、モデルが出力を生成している間の待機状態で
テキスト表示で味気が無かったため、ローディングアイコンを実装。 - 「動いているのか止まっているのか分からない」という不安を解消し、
日常的に使うツールとしての体験を少しだけ改善しました。
◆ 成果・学び
今回のコントリビュートを通じて、以下のような経験と学びが得られました。
- 大規模OSSコードベースへの段階的なリファクタリング経験
- いきなり書き換えず、
- テストで挙動を固定
- 小さく分割
- レビューで擦り合わせ
という流れを踏むことで、安心して4,000行クラスのファイルを崩していくプロセスを体験しました。
- 記憶システムの実装パターンの理解と整理
- エピソード記憶(Chronicle)と意味記憶(Memopedia)を分離しつつ、
ハイブリッド検索で統合する設計を、実装レベルで確認・言語化できました。
- エピソード記憶(Chronicle)と意味記憶(Memopedia)を分離しつつ、
- 自分が作りたいものへの「足場」ができた
- 今後自分が実装したい
- 「記憶機能を持つ会話エージェント」
- 「Deep Researchパイプラインと連携する個人OS」
の下地となる考え方・コードの読み方を、実際のOSSを通して固められました。
自分の余暇開発としても、職能としての積み上げとしても、
かなり手応えのあるコントリビュートになったので、備忘も兼ねてここに残しておきます。