アーキテクチャ概要
StarNionは完全にセルフホスト可能なAIパーソナルアシスタントです。すべてのデータはユーザー自身のサーバーに保存され、システムは5つのコアサービスで構成されています。
システム全体の構造
┌─────────────────────────────────────────────────────────┐
│ ユーザーアクセス │
│ │
│ ウェブブラウザ Telegramアプリ │
│ │ │ │
└───────┼────────────────────┼────────────────────────────┘
│ │
▼ ▼
┌───────────────┐ ┌────────────────────────────────────┐
│ UI (Next.js) │ │ Gateway (Go) │
│ :3893 │──▶│ :8080 │
│ │ │ │
│ - チャットUI │ │ ┌──────────┐ ┌────────────────┐ │
│ - ダッシュ │ │ │ REST API │ │ Telegram Bot │ │
│ ボード │ │ │ /api/v1/ │ │ Manager │ │
│ - 24+ページ │ │ └────┬─────┘ └───────┬────────┘ │
│ - 設定 │ │ │ │ │
└───────────────┘ │ ┌────┴────────────────┘ │
│ │ WebSocket Hub (/ws/chat) │
│ └────────────────┬─────────────────┘
│ │ gRPC
└───────────────────┼────────────────────┘
│
▼
┌───────────────────────────────────────┐
│ Agent (TypeScript) │
│ :50051 │
│ │
│ ┌─────────────────────────────────┐ │
│ │ AI SDK v5 · Multi-LLM │ │
│ │ │ │
│ │ 24+スキル: finance、diary、 │ │
│ │ goals、search、wellness、... │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ┌──────────────┴──────────────────┐ │
│ │ SSEストリーミング │ │
│ └──────────────┬──────────────────┘ │
└─────────────────┼──────────────────────┘
│
┌─────────────────┴──────────────────────┐
│ │
▼ ▼ │
┌──────────────────┐ ┌──────────────────────┐ │
│ PostgreSQL │ │ MinIO │ │
│ (pgvector) │ │ (オブジェクトストレ │ │
│ │ │ ージ) │ │
│ - 会話 │ │ - 画像 │ │
│ - 財務 │ │ - 音声 │ │
│ - 日記/メモ │ │ - ドキュメントファイル│ │
│ - 埋め込み │ │ - 生成ファイル │ │
└──────────────────┘ └──────────────────────┘ │
│
┌────────────────────────────────────────────────┐ │
│ LLMプロバイダー │──┘
│ Gemini / OpenAI / Claude / GLM / Ollama │
└────────────────────────────────────────────────┘
5つのコアサービス
1. UI (Next.js) — ポート3893
ウェブフロントエンド。ユーザーがブラウザで直接操作するインターフェースです。
- チャットインターフェース: リアルタイムストリーミング応答、ファイル添付、会話履歴
- ダッシュボード: 費用の概要、目標の状態、Dデイ、日記、メモ、ドキュメント、画像
- 24以上の機能ページ: 家計、予算、分析、日記、ウェルネス、ガーデン、目標、Dデイ、メモ、メモリ、レポート、統計、検索、スキル、ペルソナ、モデル、チャンネル、ログ、使用量、ファイルなど
- 設定: プロバイダー&モデル管理、Telegramチャンネル設定、通知センター(cron)
- i18n: next-intlによる4言語サポート(韓国語、英語、日本語、中国語)
Next.js APIルートがプロキシとして機能し、リクエストをGatewayのREST APIに転送します。
2. Gateway (Go) — ポート8080
すべてのトラフィックのハブです。UIとAIエージェントの仲介役として機能します。
- REST API (
/api/v1/): チャット、ファイルアップロード、設定、スキル管理、チャンネル設定など - WebSocket (
/ws/chat): リアルタイムストリーミングチャット接続 - Telegram BotManager: ユーザーごとにTelegramボットインスタンスを動的に起動・停止
- gRPCクライアント: TypeScriptエージェントと通信
- Cronスケジューラー: ユーザーごとに切り替え可能な通知ジョブ(週次レポート、予算警告、デイリーサマリーなど)
- MinIO連携: アップロードされたファイルをオブジェクトストレージに保存
Goの高い並行処理能力により、多くのユーザーが同時に接続しても安定した動作が保証されます。
3. Agent (TypeScript/Node.js) — ポート50051 (gRPC)
AIの脳。Vercel AI SDK v5ベースのエージェントがメッセージを分析して複数のLLMプロバイダーでスキルを実行します。
- AI SDK v5エージェント: メッセージ処理、スキル選択、応答生成
- マルチLLM: Anthropic Claude、Google Gemini、OpenAI、GLM (Z.AI)、Ollama
- スキルシステム: 24以上の組み込みスキル — finance、diary、goals、wellness、search、memo、documents、image、audioなど
- SSEストリーミング: AI SDK標準ストリーミング形式によるリアルタイムレスポンス
- 埋め込みサービス: テキストをベクターに変換してPostgreSQL(pgvector)に保存
- RAGメモリ: 全ユーザーデータにわたる4層セマンティックメモリ
4. PostgreSQL (pgvector)
主要なデータストア。pgvector拡張機能により、通常のデータと一緒にベクター埋め込みも保存されます。
保存されるデータ:会話履歴、費用記録、日記エントリ、メモ、目標、Dデイ、ドキュメントインデックス、埋め込みベクター、チャンネル設定、スキル設定、ペルソナ、cronスケジュール、使用量ログ
5. MinIO(オブジェクトストレージ)
ファイルストア。S3互換APIを提供するため、AWS S3に置き換えることもできます。
保存されるファイル:アップロードされた画像、音声、ドキュメント、AIが生成したファイル(QRコード、生成された画像など)
データフロー:メッセージ処理
ユーザーが「今日の昼食1,200円」と入力したときの処理フローです。
1. ユーザー → UI (Next.js)
「今日の昼食1,200円」
2. UI → Gateway (HTTP POST /api/v1/chat または WebSocket)
{ message: "今日の昼食1,200円", user_id: "...", thread_id: "..." }
3. Gateway → Agent (gRPC Chat RPC)
サーバーストリーミングで呼び出し
4. Agent: AI SDK v5処理
4-1. メッセージ分析:「食費1,200円として認識」
4-2. スキル選択:financeスキル
4-3. DBクエリ:今月の食費合計を確認
4-4. 費用を記録:INSERT INTO finance_entries
4-5. 応答生成:「昼食1,200円を記録しました。今月の食費合計:8,750円」
5. Agent → Gateway (gRPCストリーミング)
トークンごとに応答をストリーミング
6. Gateway → UI (WebSocket または SSE)
リアルタイムストリーミングで配信
7. UI → ユーザー
画面に応答を表示
gRPC通信
Gateway(Go)とAgent(TypeScript)はgRPCで通信します。
// proto/starnion/v1/agent.proto(概要)
service AgentService {
// 通常のチャット(サーバーストリーミング)
rpc Chat(ChatRequest) returns (stream ChatResponse);
// ヘルスチェック
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
}
gRPCを選択した理由:
- サーバーストリーミング: LLMの応答をリアルタイムでトークンごとに配信
- 型安全性: Protobufスキーマによってインターフェースが保証される
- 効率性: HTTP/2ベースで低レイテンシー
WebSocket:リアルタイムチャット
Web UIチャットはWebSocketで実装されています。GatewayのWebSocket Hubが接続を管理します。
ブラウザ ──WebSocket── Gateway Hub ──gRPC Stream── Agent
│ /ws/chat サーバーストリーミング │
│◀─────────────────────────────────────────────────│
リアルタイムのトークンごとのストリーミング
接続フロー:
- ブラウザが
/ws/chat?user_id=...へのWebSocket接続を確立 - ユーザーがメッセージを入力 → JSONが送信される
- GatewayがAgentにgRPCストリーミングリクエストを送信
- Agentの応答トークンが即座にWebSocket経由でリレーされる
- ブラウザ画面にリアルタイムで文字が表示される
マルチチャンネル:単一エージェント
Web UIとTelegramは同じTypeScriptエージェントに接続されています。
Telegramユーザー ──▶ Telegram Bot ──▶ Gateway ──▶ Agent ──▶ 同じDB
Webユーザー ──▶ WebSocket ──▶ Gateway ──▶ Agent ──▶ 同じDB
いずれかのチャンネルに記録されたものは同じPostgreSQLデータベースに保存されるため、ウェブで書いたメモをTelegramから取得したり、その逆も可能です。
各チャンネルのメッセージは platform フィールドで識別されます:web、telegram。
4層RAGメモリシステム
Agentが過去の記録を参照する際に使用する4層メモリ構造です。
クエリ:「先週何を食べた?」
レイヤー1:日次ログ(デイリーログベクター)
├─ 過去7日間の会話のベクター検索
└─ 食費関連エントリを抽出
レイヤー2:ナレッジベース(ナレッジベースベクター)
├─ 支出パターン分析結果
└─ よく訪れるレストランのパターン
レイヤー3:ドキュメントセクション(ドキュメントセクションベクター)
└─ アップロードされたレシートやドキュメントのインデックス化されたコンテンツ
レイヤー4:最近の財務(最近の費用記録)
└─ 最近の費用エントリの直接DBクエリ
各レイヤーから関連するコンテキストを取得してLLMに一緒に渡すことで、「先週サムギョプサルを食べたよね?」のような自然なメモリ参照が可能になります。
マルチプロバイダーLLM
Agentは複数のLLMプロバイダーをサポートしています。ユーザーはWeb UIの設定 > モデルでプロバイダーとモデルを切り替えることができます。
| プロバイダー | モデル例 | 備考 |
|---|---|---|
| Anthropic Claude | claude-sonnet-4-5、claude-haiku | 長いコンテキスト処理 |
| Google Gemini | gemini-2.0-flash、gemini-2.5-pro | 高速応答、マルチモーダル |
| OpenAI | gpt-4o、gpt-4o-mini | 高品質な応答 |
| GLM (Z.AI) | glm-4-flash、glm-4-plus | 中国語の強み |
| Ollama | llama3、mistral、qwen | 完全ローカル(インターネット不要) |
モデルとプロバイダーはWeb UIまたはCLI(starnion config models)でユーザーごとに管理できます。
セキュリティに関する考慮事項
セルフホスト設計
StarNionはセルフホスティングを前提として設計されています。
- すべての個人データ(会話、費用、日記エントリ)はユーザーのサーバーにのみ保存されます
- メッセージコンテンツはLLM API呼び出し時のみ外部サーバーに送信され、選択したLLMプロバイダーにのみ送信されます
- Ollamaを使用すると完全なオフライン操作が可能です
JWT認証
Web UIのログインはNextAuth v5によるJWT(JSON Web Token)ベースです。
- サーバーはログイン時にJWTを発行します
- 以降のすべてのAPIリクエストにトークンが含まれます
- トークンが期限切れになると再ログインが必要です
- Gatewayのトークン検証によりAPIレベルのセキュリティを保証します
PostgreSQLアドバイザリロック
PostgreSQLのセッションレベルのアドバイザリロックを使用して、Telegramボットの重複実行を防止します。これにより、同じボットトークンが2つのGatewayインスタンスによって同時にポーリングされることを防ぎます。
データの分離
各ユーザーのデータは user_id 外部キーによって完全に分離されています。あるユーザーが別のユーザーのデータにアクセスすることはできません。