- Add CPU/GPU memory monitoring endpoint and frontend widget - Add Amazon Bedrock model support (API key / inference profiles) plus model selector entries - Add Discord weather/laundry notification job (JMA forecast + LLM-generated message) - Add Discord bot that replies to mentions via the configured LLM, with weather-aware context - Add scheduled "useless tips" job with separate webhook and quiet-hours skip - Switch FastAPI startup to lifespan handler, log viewer, markdown rendering, and toast UI additions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
124 lines
5.3 KiB
Markdown
124 lines
5.3 KiB
Markdown
# アーキテクチャ概要
|
||
|
||
## 全体構成
|
||
|
||
```
|
||
フロントエンド (Vue 3 + TypeScript + Vite, :5173)
|
||
↕ REST + SSE (Vite dev proxy 経由)
|
||
バックエンド (FastAPI + Python, :8000)
|
||
↕ SQLAlchemy
|
||
SQLite (playchat.db)
|
||
↕ LiteLLM
|
||
OpenAI / Anthropic / Ollama など任意の LLM
|
||
```
|
||
|
||
---
|
||
|
||
## バックエンド
|
||
|
||
### ディレクトリ構成
|
||
|
||
```
|
||
backend/
|
||
├── app/
|
||
│ ├── main.py # FastAPI インスタンス、CORS、ルーター登録、DB初期化
|
||
│ ├── api/
|
||
│ │ ├── chat.py # チャット・セッション関連エンドポイント
|
||
│ │ ├── memory.py # 長期メモリ参照・削除
|
||
│ │ └── logs.py # API ログ参照・削除
|
||
│ ├── core/
|
||
│ │ ├── config.py # .env 読み込み・定数定義
|
||
│ │ ├── llm.py # LiteLLM ラッパー(ストリーミング・ログ記録)
|
||
│ │ └── memory.py # メモリ読み書きロジック(要約・コンテキスト生成)
|
||
│ └── db/
|
||
│ ├── database.py # SQLite 接続・セッションファクトリ・テーブル自動作成
|
||
│ └── models.py # SQLAlchemy モデル定義
|
||
└── pyproject.toml
|
||
```
|
||
|
||
### DB テーブル
|
||
|
||
| テーブル | 主なカラム | 用途 |
|
||
|---|---|---|
|
||
| `sessions` | id (UUID), title, model, created_at, updated_at | チャットセッション |
|
||
| `messages` | id, session_id, role, content, created_at | 会話メッセージ(短期メモリ) |
|
||
| `memories` | id, session_id, summary, embedding_json, created_at | 要約による長期メモリ |
|
||
| `api_logs` | id, session_id, model, request_json, response_text, error, latency_ms, created_at | LLM API 呼び出しログ |
|
||
|
||
### メモリ機構(`core/memory.py`)
|
||
|
||
1. **短期メモリ**: セッション内の全 `messages` をコンテキストとして送信
|
||
2. **長期メモリ**: メッセージ数が `MEMORY_SUMMARIZE_THRESHOLD`(デフォルト 20)を超えると、古い半分を LLM で要約して `memories` に保存しメッセージを削除
|
||
3. **コンテキスト合成**: `get_context_messages()` が `memories` の要約をシステムメッセージとして先頭に付加し、残存メッセージと結合して返す
|
||
|
||
### LLM 呼び出し(`core/llm.py`)
|
||
|
||
- `stream_chat()` / `complete()` が LiteLLM を薄くラップ
|
||
- `_log_context` で呼び出しを囲み、成功・失敗どちらも `api_logs` テーブルに記録
|
||
- `DEBUG=true` で `litellm._turn_on_debug()` が有効になり詳細ログが出力される
|
||
|
||
### SSE ストリーミング(`api/chat.py`)
|
||
|
||
`POST /chat/stream` は `StreamingResponse` で以下のイベントを順番に送出する:
|
||
|
||
```
|
||
data: {"type":"session_id","value":"<uuid>"} # 新規セッション時のみ
|
||
data: {"type":"chunk","value":"テキスト断片"} # 0回以上
|
||
data: {"type":"done"} # 正常完了
|
||
data: {"type":"error","value":"エラー内容"} # 例外発生時
|
||
```
|
||
|
||
バッファリング防止のため `Cache-Control: no-cache` と `X-Accel-Buffering: no` を付与する。
|
||
|
||
---
|
||
|
||
## フロントエンド
|
||
|
||
### ディレクトリ構成
|
||
|
||
```
|
||
frontend/src/
|
||
├── api/
|
||
│ └── client.ts # fetch ラッパー・SSE クライアント・型定義
|
||
├── stores/
|
||
│ └── chat.ts # Pinia ストア(全アプリ状態)
|
||
├── components/
|
||
│ ├── SessionList.vue # セッション一覧サイドバー
|
||
│ ├── ChatWindow.vue # メッセージ表示エリア
|
||
│ ├── MessageInput.vue # 入力欄・送信
|
||
│ ├── ModelSelector.vue # LLM モデル切替セレクト
|
||
│ ├── MarkdownContent.vue # marked + DOMPurify によるレンダリング
|
||
│ ├── LogViewer.vue # API ログ閲覧パネル
|
||
│ └── ToastList.vue # エラートースト通知
|
||
└── App.vue # ルートレイアウト
|
||
```
|
||
|
||
### 状態管理(`stores/chat.ts`)
|
||
|
||
| 状態 | 型 | 説明 |
|
||
|---|---|---|
|
||
| `sessions` | `SessionInfo[]` | セッション一覧 |
|
||
| `currentSessionId` | `string \| null` | 選択中セッション |
|
||
| `messages` | `Message[]` | 表示中メッセージ |
|
||
| `isStreaming` | `boolean` | SSE 受信中フラグ |
|
||
| `selectedModel` | `string` | 選択中 LLM モデル |
|
||
| `toasts` | `Toast[]` | エラー通知キュー |
|
||
|
||
### SSE 受信フロー
|
||
|
||
1. `sendMessage()` がユーザーメッセージと空のアシスタントメッセージを `messages` に追加
|
||
2. `streamChat()` が fetch + ReadableStream で SSE を受信
|
||
3. `chunk` イベント受信のたびに `messages.value[msgIdx].content` を更新(Vue reactive proxy 経由)
|
||
4. `done` で `pending` フラグを解除
|
||
5. `error` / ネットワークエラーは `error` フラグを立て赤バブル表示 + トースト通知
|
||
|
||
### Markdown レンダリング(`MarkdownContent.vue`)
|
||
|
||
- アシスタントメッセージのみ `marked` で HTML に変換後 `DOMPurify` でサニタイズ
|
||
- ストリーミング中(`pending=true`)は未閉じのコードフェンス(` ``` `)を自動補完してから描画
|
||
|
||
### Vite プロキシ設定
|
||
|
||
`/chat`、`/memory`、`/logs`、`/health` を `http://localhost:8000` に転送。
|
||
`/chat` は SSE バッファリング無効化のため `configure` で `x-accel-buffering: no` を付与。
|