432 lines
10 KiB
Markdown
432 lines
10 KiB
Markdown
# TobiichiGPT - 人工回覆系統
|
||
|
||
將 AI 對話系統改造成由真人管理員回覆的極簡方案。
|
||
|
||
## 🎯 特色
|
||
|
||
- ✅ **零修改** - 不需要修改 Open WebUI 程式碼
|
||
- ✅ **極簡化** - 4 個容器完成所有功能
|
||
- ✅ **共享資料庫** - Open WebUI 和管理後台使用同一個 PostgreSQL
|
||
- ✅ **視覺化後台** - NocoDB 提供專業的資料庫管理介面
|
||
- ✅ **可編輯代碼** - API 程式碼透過 bind mount 可直接修改
|
||
|
||
## 🏗️ 架構
|
||
|
||
### 主要服務(必須)
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ PostgreSQL │ ← 共享資料庫
|
||
└────────┬────────┘
|
||
│
|
||
┌────┴─────┬─────────────┬─────────────┐
|
||
│ │ │ │
|
||
┌───▼────┐ ┌──▼─────┐ ┌────▼─────┐ ┌───▼────┐
|
||
│ API │ │ Open │ │ NocoDB │ │ 用戶 │
|
||
│ 中間層 │ │ WebUI │ │ 管理介面 │ │ 瀏覽器 │
|
||
└────────┘ └────────┘ └──────────┘ └────────┘
|
||
```
|
||
|
||
### 代理服務(選用)
|
||
|
||
```
|
||
┌───────────┐
|
||
│ 用戶 │
|
||
└─────┬─────┘
|
||
│ 公網
|
||
┌─────▼──────────────┐
|
||
│ Cloudflare Tunnel │
|
||
└─────┬──────────────┘
|
||
│ 內網
|
||
┌─────▼──────────────┐
|
||
│ Nginx Proxy Mgr │
|
||
└─────┬──────────────┘
|
||
│
|
||
┌─────▼──────────────┐
|
||
│ 主要服務 (上方) │
|
||
└────────────────────┘
|
||
```
|
||
|
||
## 🚀 快速開始
|
||
|
||
### 1. 準備環境檔案
|
||
|
||
```powershell
|
||
# 複製主服務環境變數
|
||
Copy-Item .env.example .env
|
||
notepad .env # 設定 DB_PASSWORD
|
||
|
||
# 如需代理服務
|
||
Copy-Item .env.proxy .env.proxy
|
||
notepad .env.proxy # 填入 CLOUDFLARE_TUNNEL_TOKEN
|
||
```
|
||
|
||
### 2. 啟動主要服務
|
||
|
||
```powershell
|
||
# 啟動 PostgreSQL + API + Open WebUI + NocoDB
|
||
docker-compose up -d
|
||
|
||
# 查看狀態
|
||
docker-compose ps
|
||
|
||
# 查看日誌
|
||
docker-compose logs -f
|
||
```
|
||
|
||
### 3. 啟動代理服務(選用)
|
||
|
||
```powershell
|
||
# 啟動 Cloudflare Tunnel + NPM
|
||
docker-compose -f docker-compose.proxy.yml --env-file .env.proxy up -d
|
||
|
||
# 查看狀態
|
||
docker-compose -f docker-compose.proxy.yml ps
|
||
```
|
||
|
||
## 🌐 服務訪問
|
||
|
||
### 主要服務
|
||
|
||
| 服務 | 網址 | 說明 |
|
||
|------|------|------|
|
||
| **Open WebUI** | http://localhost:3000 | 用戶對話介面 |
|
||
| **API 伺服器** | http://localhost:8000 | OpenAI API 相容端點 |
|
||
| **NocoDB** | http://localhost:8080 | 管理員回覆介面 |
|
||
| **PostgreSQL** | localhost:5432 | 資料庫 |
|
||
|
||
### 代理服務(如已啟動)
|
||
|
||
| 服務 | 網址 | 說明 |
|
||
|------|------|------|
|
||
| **NPM 管理面板** | http://localhost:81 | Nginx Proxy Manager |
|
||
| **HTTP 代理** | Port 80 | HTTP 流量 |
|
||
| **HTTPS 代理** | Port 443 | HTTPS 流量 |
|
||
|
||
**NPM 預設帳號**:
|
||
- Email: `admin@example.com`
|
||
- Password: `changeme`
|
||
|
||
## 📋 使用流程
|
||
|
||
### 設定 Open WebUI
|
||
|
||
1. 開啟 http://localhost:3000
|
||
2. 進入 **Settings** → **Connections**
|
||
3. 新增 OpenAI Connection:
|
||
- **API Base URL**: `http://api:8000/v1`
|
||
- **API Key**: `sk-human` (任意值)
|
||
4. 模型列表會出現 **human-admin**
|
||
|
||
### 管理員回覆
|
||
|
||
1. 訪問 NocoDB: http://localhost:8080
|
||
2. 連接到 PostgreSQL:
|
||
- Host: `postgres`
|
||
- Port: `5432`
|
||
- Database: `tobiichi`
|
||
- Username: `tobiichi`
|
||
- Password: (你在 .env 設定的密碼)
|
||
3. 開啟 `reply_queue` 表格
|
||
4. 查看 `status='pending'` 的訊息
|
||
5. 填入 `admin_reply` 欄位
|
||
6. 將 `status` 改為 `replied`
|
||
7. 用戶會在 3 秒內收到回覆
|
||
|
||
### 完整流程
|
||
|
||
```
|
||
用戶在 Open WebUI 發送訊息
|
||
↓
|
||
API 收到請求,寫入 reply_queue (status='pending')
|
||
↓
|
||
API 每 3 秒檢查該訊息的 status
|
||
↓
|
||
管理員在 NocoDB 看到訊息,填入回覆並改 status='replied'
|
||
↓
|
||
API 讀取 admin_reply 欄位
|
||
↓
|
||
回傳給 Open WebUI
|
||
↓
|
||
用戶收到回覆
|
||
```
|
||
|
||
## 🔧 技術架構
|
||
|
||
### 主要服務
|
||
|
||
- **PostgreSQL 15**: 共享關聯式資料庫
|
||
- **FastAPI**: Python Web 框架,提供 OpenAI API 相容端點
|
||
- **Open WebUI**: 對話前端介面
|
||
- **NocoDB**: 視覺化資料庫管理工具
|
||
|
||
### 代理服務
|
||
|
||
- **Nginx Proxy Manager**: 反向代理 + SSL 憑證管理
|
||
- **Cloudflare Tunnel**: 安全的公網訪問通道
|
||
|
||
### API 端點
|
||
|
||
- `/v1/models` - 模型列表(回傳 human-admin)
|
||
- `/v1/chat/completions` - 聊天完成端點(OpenAI 相容)
|
||
|
||
## 🌍 Cloudflare Tunnel 設定
|
||
|
||
### 1. 建立 Tunnel
|
||
|
||
1. 登入 [Cloudflare Zero Trust](https://one.dash.cloudflare.com/)
|
||
2. 前往 **Networks** → **Tunnels**
|
||
3. 點擊 **Create a tunnel**
|
||
4. 選擇 **Cloudflared**
|
||
5. 輸入 Tunnel 名稱(例如: `tobiichi-tunnel`)
|
||
6. 複製顯示的 Token
|
||
7. 將 Token 貼到 `.env.proxy` 的 `CLOUDFLARE_TUNNEL_TOKEN`
|
||
|
||
### 2. 設定 Public Hostname
|
||
|
||
#### 選項 A: 透過 NPM 代理(推薦)
|
||
|
||
在 Cloudflare Tunnel 設定:
|
||
- **Public hostname**: `chat.yourdomain.com`
|
||
- **Service Type**: HTTP
|
||
- **URL**: `http://npm:80`
|
||
|
||
然後在 NPM (http://localhost:81) 設定:
|
||
- **Domain**: `chat.yourdomain.com`
|
||
- **Forward to**: `openwebui:3000`
|
||
|
||
#### 選項 B: 直接指向服務
|
||
|
||
在 Cloudflare Tunnel 設定:
|
||
- **Public hostname**: `chat.yourdomain.com`
|
||
- **Service Type**: HTTP
|
||
- **URL**: `http://openwebui:3000`
|
||
|
||
### 3. 啟動 Tunnel
|
||
|
||
```powershell
|
||
docker-compose -f docker-compose.proxy.yml --env-file .env.proxy up -d
|
||
```
|
||
|
||
訪問你設定的網域即可從公網訪問服務。
|
||
|
||
## 📦 資料持久化
|
||
|
||
所有服務資料都會持久化保存:
|
||
|
||
```yaml
|
||
volumes:
|
||
postgres-data: # PostgreSQL 資料
|
||
openwebui-data: # Open WebUI 配置和對話記錄
|
||
nocodb-data: # NocoDB 配置
|
||
npm-data: # NPM 配置(代理服務)
|
||
npm-letsencrypt: # SSL 憑證(代理服務)
|
||
```
|
||
|
||
## 🛠️ 修改 API 程式碼
|
||
|
||
API 程式碼位於 `./api/` 目錄,透過 bind mount 掛載到容器:
|
||
|
||
```powershell
|
||
# 編輯 API 程式碼
|
||
notepad api\server.py
|
||
|
||
# 重啟 API 服務套用修改
|
||
docker-compose restart api
|
||
|
||
# 查看 API 日誌
|
||
docker-compose logs -f api
|
||
```
|
||
|
||
## 🐳 檔案結構
|
||
|
||
```
|
||
tobiichiGPT/
|
||
├── api/ # API 服務程式碼
|
||
│ ├── server.py # FastAPI 主程式
|
||
│ └── requirements.txt # Python 依賴
|
||
├── docker-compose.yml # 主要服務編排
|
||
├── docker-compose.proxy.yml # 代理服務編排
|
||
├── .env.example # 主服務環境變數範例
|
||
├── .env.proxy # 代理服務環境變數範例
|
||
└── README.md # 本文件
|
||
```
|
||
|
||
## 🔍 故障排除
|
||
|
||
### API 無法連接資料庫
|
||
|
||
```powershell
|
||
# 檢查資料庫是否啟動
|
||
docker-compose ps postgres
|
||
|
||
# 查看資料庫日誌
|
||
docker-compose logs postgres
|
||
|
||
# 檢查網路連接
|
||
docker network inspect tobiichi-network
|
||
```
|
||
|
||
### Open WebUI 無法連接 API
|
||
|
||
1. 確認 API URL 使用容器名稱: `http://api:8000/v1`
|
||
2. 檢查兩個容器是否在同一網路:
|
||
```powershell
|
||
docker network inspect tobiichi-network
|
||
```
|
||
|
||
### NocoDB 無法連接資料庫
|
||
|
||
1. 檢查 PostgreSQL 是否健康:
|
||
```powershell
|
||
docker-compose ps
|
||
```
|
||
2. 確認資料庫密碼正確(`.env` 檔案)
|
||
|
||
### 代理服務無法啟動
|
||
|
||
```powershell
|
||
# 檢查主網路是否已建立
|
||
docker network ls | Select-String "tobiichi-network"
|
||
|
||
# 先啟動主服務
|
||
docker-compose up -d
|
||
|
||
# 再啟動代理服務
|
||
docker-compose -f docker-compose.proxy.yml up -d
|
||
```
|
||
|
||
## 📝 開發筆記
|
||
|
||
### 資料庫 Schema
|
||
|
||
`reply_queue` 表格結構:
|
||
|
||
```sql
|
||
CREATE TABLE reply_queue (
|
||
id SERIAL PRIMARY KEY,
|
||
user_message TEXT NOT NULL,
|
||
admin_reply TEXT,
|
||
status VARCHAR(20) DEFAULT 'pending',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
replied_at TIMESTAMP
|
||
);
|
||
|
||
CREATE INDEX idx_status ON reply_queue(status);
|
||
CREATE INDEX idx_created_at ON reply_queue(created_at);
|
||
```
|
||
|
||
### 環境變數
|
||
|
||
**主服務** (`.env`):
|
||
- `DB_PASSWORD`: PostgreSQL 密碼
|
||
|
||
**代理服務** (`.env.proxy`):
|
||
- `CLOUDFLARE_TUNNEL_TOKEN`: Cloudflare Tunnel 認證 Token
|
||
|
||
### Port 映射
|
||
|
||
**主服務**:
|
||
- 3000: Open WebUI
|
||
- 5432: PostgreSQL
|
||
- 8000: API
|
||
- 8080: NocoDB
|
||
|
||
**代理服務**:
|
||
- 80: HTTP
|
||
- 443: HTTPS
|
||
- 81: NPM 管理介面
|
||
|
||
## 📄 授權
|
||
|
||
MIT License
|
||
build: .
|
||
container_name: tobiichi-gpt
|
||
ports:
|
||
- "8000:8000"
|
||
networks:
|
||
- tobiichi-network
|
||
|
||
open-webui:
|
||
image: ghcr.io/open-webui/open-webui:main
|
||
container_name: open-webui
|
||
ports:
|
||
- "3000:8080"
|
||
volumes:
|
||
- open-webui:/app/backend/data
|
||
networks:
|
||
- tobiichi-network
|
||
|
||
networks:
|
||
tobiichi-network:
|
||
driver: bridge
|
||
|
||
volumes:
|
||
open-webui:
|
||
```
|
||
|
||
然後在 Open WebUI 中使用:
|
||
- **API Base URL**: `http://human-reply-server:8000/v1`
|
||
|
||
## 📝 進階設定
|
||
|
||
### 修改等待超時時間
|
||
|
||
編輯 `docker/human_reply_server.py` 第 79 行:
|
||
|
||
```python
|
||
timeout = 600 # 預設 10 分鐘,可改為其他秒數
|
||
```
|
||
|
||
### 修改伺服器埠號
|
||
|
||
**方法 1: 修改 docker-compose.yml**
|
||
```yaml
|
||
# 編輯 docker-stack/docker-compose.yml
|
||
ports:
|
||
- "9000:8000" # 本機 9000 對應容器 8000
|
||
```
|
||
|
||
**方法 2: 修改程式碼**
|
||
```python
|
||
# 編輯 docker/human_reply_server.py
|
||
uvicorn.run(app, host="0.0.0.0", port=8000) # 改為其他埠號
|
||
```
|
||
|
||
### 設定 Cloudflare Tunnel
|
||
|
||
詳細設定步驟請參考專案根目錄的說明文件,或參考 `docker-stack/.env.example`:
|
||
|
||
```powershell
|
||
cd docker-stack
|
||
Copy-Item .env.example .env
|
||
notepad .env # 填入您的 CLOUDFLARE_TUNNEL_TOKEN
|
||
```
|
||
|
||
### 支援多管理員
|
||
|
||
目前版本採「先搶先贏」機制,任何管理員都可以回覆任何訊息。若需要分配機制,可以加入:
|
||
- 管理員登入系統
|
||
- 訊息認領機制
|
||
- 管理員負載平衡
|
||
|
||
## ⚠️ 注意事項
|
||
|
||
- 此為**最簡化版本**,適合小規模使用
|
||
- 訊息儲存在記憶體中,重啟會遺失
|
||
- 沒有身份驗證,建議僅在內網使用
|
||
- 若需生產環境,建議加入:
|
||
- 資料庫持久化
|
||
- 身份驗證
|
||
- WebSocket 即時推送
|
||
- 訊息隊列系統
|
||
|
||
## 🎨 管理員後台截圖
|
||
|
||
後台提供:
|
||
- 待處理訊息列表
|
||
- 用戶訊息顯示
|
||
- 回覆文字框
|
||
- 一鍵送出功能
|
||
- 自動刷新
|