R-2/R-3:Redis 快取層與 LLM 對話品質強化 + pnpm/turbo 遷移 #1

Merged
admin merged 6 commits from develop into master 2026-08-14 04:56:21 +00:00
2 changed files with 76 additions and 1 deletions
Showing only changes of commit 5732925f64 - Show all commits
+11
View File
@@ -1,3 +1,14 @@
# 複製為 .env 後依需要調整。
# R-2 階段會改為 postgresql 連線字串(例如 postgresql://user:password@localhost:5432/kokorone)。
DATABASE_URL="file:./prisma/dev.db"
# R-2:情緒狀態即時讀寫/session 快取的加速層;連不到時自動退回原本行為(DB/行程記憶體),不是必要依賴。
REDIS_URL=redis://127.0.0.1:6379
# R-3:LLM_PROVIDER=mock(預設,冒煙測試固定用這個)|claude(真的呼叫 API)
LLM_PROVIDER=mock
# 這個部署走 CLIProxy(OpenAI 相容的分散式派工代理)而不是直連 api.anthropic.com,
# 底層仍是 Claude;若改直連官方 API,把 CLAUDE_BASE_URL 換成 https://api.anthropic.com/v1 即可。
CLAUDE_BASE_URL=http://localhost:3000/api/v1
CLAUDE_API_KEY=
CLAUDE_MODEL=claude-sonnet-4-5
+65 -1
View File
@@ -2,4 +2,68 @@
以人腦「記憶/情緒/關係」架構為引擎基礎的戀愛陪伴系統。
> 目前使用 npm workspaces 開發(本機無 pnpm),待 R-1 階段會遷移至 pnpm + Turborepo,對外指令介面(`npm run restart` / `npm run smoke`)保持不變。
## 開發環境
Monorepo 採 pnpm workspace + Turborepo(`pnpm-workspace.yaml` / `turbo.json`)。
```bash
pnpm install # 安裝所有 workspace 套件
pnpm run build # turbo run build(依相依順序建置 shared/db/api,並建置 web 的 production bundle)
pnpm run restart # 停止舊的 api/web 行程、重建 TypeScript(tsc -b)、重新啟動並等待健康檢查
pnpm run smoke A # 執行 A 群組冒煙測試;all 表示依序執行 A~R 全部群組
```
對外指令介面(`restart` / `smoke`)維持與遷移前相同的腳本名稱;唯一差異是
**pnpm 不會像 npm 一樣吃掉 `--` 分隔符**,`pnpm run smoke -- A` 會把字面上的
`--` 一起傳給腳本而找不到群組,要執行子指令請直接接在腳本名稱後面
(`pnpm run smoke A`),不要加 `--`。
## 環境變數
複製 `.env.example` 為 `.env` 後依需要調整;`apps/web/.env.local` 另外可設定
`NEXT_PUBLIC_API_URL`(瀏覽器端呼叫 api 用,預設 `http://localhost:3001`)。
| 變數 | 預設值 | 說明 |
| --- | --- | --- |
| `DATABASE_URL` | `file:./prisma/dev.db` | Prisma 連線字串。R-5 若遷移到 PostgreSQL,改為 `postgresql://user:password@host:5432/db` 並將 `prisma/schema.prisma` 的 `provider` 由 `sqlite` 換成 `postgresql`。 |
| `PORT` | `3001` | api(NestJS)監聽埠。 |
| `PORT_API` / `PORT_WEB` | `3001` / `3100` | `pnpm run restart`(`scripts/dev-restart.mjs`)啟動 api/web 時使用的埠號。 |
| `WEB_ORIGIN` | `http://localhost:3100` | api 的 CORS 允許來源之一;`http://localhost:8081`(Expo web 開發伺服器)已固定加入,不受此變數影響。 |
| `NEXT_PUBLIC_API_URL` | `http://localhost:3001` | web(Next.js)呼叫 api 的位址,build time 注入,正式環境需在建置時設定。 |
| `LLM_PROVIDER` | `mock` | `mock`(模板庫,冒煙測試固定用這個)/`claude`(呼叫真實 API,見下)。 |
| `CLAUDE_BASE_URL` | `http://localhost:3000/api/v1` | OpenAI 相容的 chat completions 端點基底路徑。本專案的部署方式是透過 [CLIProxy](https://gitea.jsc.idv.tw/jiantw83/CLIProxy)(分散式派工代理,本機 3000 埠)轉發到真實 Claude,而非直連 `api.anthropic.com`;若要直連官方 API,把這個值換成 `https://api.anthropic.com/v1` 並確認金鑰/請求格式相容即可,`ClaudeProvider` 的呼叫端程式碼不需要改動。 |
| `CLAUDE_API_KEY` | (無) | 呼叫 `CLAUDE_BASE_URL` 用的金鑰,`LLM_PROVIDER=claude` 時必填。 |
| `CLAUDE_MODEL` | `claude-sonnet-4-5` | 要求 Provider 使用的模型名稱;CLIProxy 端需要有對應的 Worker 已註冊、能接這個模型的派工,否則會回報「沒有任何可用的 {模型}-{執行者}-{工具} 組合」。 |
| `TTS_PROVIDER` | `mock` | `mock`/`real`(P-4 空殼,尚未接上真實供應商,人工確認後才實作)。 |
| `PUSH_PROVIDER` | `mock` | `mock`/`expo`(Q-3,`expo` 直接可用,不需金鑰)。 |
## 部署路徑
開發環境:以上服務直接用 `node`/`next dev`/`expo start` 跑在同一台 Linux 主機上
(`pnpm run restart` 一鍵重啟 api/web),**不使用 Docker**——這是本專案的實際
部署選擇,取代原先技術選型草案中「Docker Compose(開發)」的規劃。
正式環境建議路徑:
1. **建置**:`pnpm install --frozen-lockfile && pnpm run build`(turbo 依序建置
`packages/shared`/`packages/db`/`apps/api`,並產出 `apps/web` 的 production
bundle)。
2. **資料庫遷移**:`npx prisma migrate deploy`(依 `DATABASE_URL` 指向的資料庫套用
遷移;R-5 遷移到 PostgreSQL 後流程相同,只是連線字串換成 postgresql)。
3. **啟動**:
- api:`node apps/api/dist/main.js`(讀取上表環境變數)。
- web:`apps/web` 下 `npx next start -p <PORT_WEB>`(讀取建置時注入的
`NEXT_PUBLIC_API_URL`)。
- mobile:`apps/mobile` 透過 `eas build` 產出實際的 App Store/Google Play
安裝檔,不隨 api/web 一起常駐部署。
4. **程序常駐與重啟**:用 systemd unit(或 pm2)分別管理 api/web 兩個
Node 行程,設定 `Restart=on-failure`;健康檢查沿用 `GET /health`
(api)與首頁 200(web),與 `scripts/dev-restart.mjs` 開發環境用的
檢查邏輯一致。
5. **反向代理/TLS**:nginx 或雲端負載平衡器終止 TLS 後轉發到 api/web
對應埠號,對外只曝露 443。
這個路徑刻意不假設 K8s 或容器化,只依賴「Node.js 行程 + systemd + nginx」,
因為這台開發主機本身就是照這個模式跑(`pnpm run restart` 正是這個模式的
開發期簡化版),移植到正式主機時只是把「用 node 直接跑」換成「用 systemd
管理同一組 node 指令」,中間不需要引入額外的容器化工具鏈。