Files
playchat/docs/architecture.md
T
colcaroliandClaude Sonnet 4.6 4a08ba29fa Add system memory monitoring, Bedrock support, and Discord integrations
- 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>
2026-06-19 00:59:38 +09:00

124 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# アーキテクチャ概要
## 全体構成
```
フロントエンド (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` を付与。