YamAgent 架構總覽與設計歷程
YamAgent
是我自己設計的 AI 助理系統,靈感來自想要打造一個 陪伴式、記憶型、語境穩定的個人 AI 系統,可以真正支援我在開發、寫作、生活規劃上的節奏與需要。
🧩 系統定位與需求背景
在使用 ChatGPT 官方介面與 API 的過程中,我發現以下幾個限制:
- ✅ 回合記憶易失,對話上下文容易斷裂
- ✅ 多執行緒(thread)管理困難
- ✅ 缺乏成本管理與 token 追蹤
- ✅ 想要不同人格(語氣/角色)切換時不夠彈性
於是我開始構思一個 本地部署、結構清晰、可控又可擴充 的個人助理系統。
⚙️ 架構設計與技術選型
我採用了以下技術堆疊:
- 後端:Python + FastAPI
- 資料庫:PostgreSQL(Tailscale 內網連線)
- 前端:Vite + React + shadcn/ui
- 部署方式:ThinkPad(WSL Ubuntu)+ Nginx reverse proxy
- API 模型串接:OpenAI GPT-4o
資料庫設計核心包含:
session
:記錄每條對話執行緒chat
:每則訊息紀錄(user / assistant)memory
:人格記憶欄位(可切換載入)token_usage
:每日 token 花費統計(GPT-4o 價格公式)yamlog
:每日學習或事件日誌紀錄
🧱 實作中遇到的挑戰與解法
❓ Q1:API 回傳訊息過長導致 CORS 錯誤?
背景:我最早嘗試以 render 部署 FastAPI,但遇到 preflight 錯誤或 500 錯誤。
解法:直接將後端部署在家中 ThinkPad,並透過 Nginx 設定 CORS headers 與路由反向代理 /api
,問題解決。
❓ Q2:資料庫無法初始建立?
背景:Base.metadata.create_all(bind=engine)
執行無反應,後來發現是 alembic migration 沒有生效。
解法:確認 env.py
是否正確匯入所有模型、並確保 alembic migration 是針對正確的 DB 執行。從此我都改為手動執行 create_all
初始化。
❓ Q3:訊息過長無法正常顯示?
背景:在前端顯示 message 訊息時,長內容格式錯亂或難以閱讀。
解法:加入 highlight.js
支援 markdown 格式與語法高亮,並加上複製按鈕與「正在輸入」動畫,提高使用體驗。
🔁 功能演進歷程
- 初始版本只有
/chat
API,可傳入 prompt + 記憶塊 - 加入
/memory
功能後,可自定角色人格與語境開場白 - 實作
/token-usage
每日統計後,能更安心掌控花費 - 將 chat、memory 整合進
/[session_id]
UI 頁面,並支援 sidebar 切換 thread - 現在支援多 session、多記憶快取、多模型管理
✍️ 設計理念
我認為個人 AI 助理應該具備以下幾點:
- 可控:我想知道資料存在哪、花多少 token、角色說話口氣為何
- 可續寫:同一個對話 thread 應能不斷延伸,而非斷裂
- 可陪伴:角色應該能理解我的節奏與目標,甚至提醒我不要分心
- 可延伸:未來我會加入日誌整合、語音輸入、日曆任務連動等模組
🚫 ChatGPT 官方服務的限制與我為什麼選擇自建
在開始開發 YamAgent 之前,我有一段時間依賴 OpenAI 提供的 ChatGPT 官方服務,但很快就遇到以下幾個致命的限制:
🧱 1. ChatGPT 無法知道現在幾點幾分
- ChatGPT 本身並不連接實際時間,只有在你問它「現在幾點」時,它才會試著用語境推測,但實際上完全不具備即時時間感知。
- 對於我這種需要「記錄每小時狀態」、「做生活節奏管理」的使用者來說,這是一個無法解決的盲點。
🔒 2. ChatGPT sandbox 中不能主動 call API
- 無法自動幫我 call webhook / query database
- 無法觸發任務提醒或與我本地程式整合
🌐 3. 官方 Web UI 無法管理上下文與人格切換
- 雖然官方後來推出「Custom GPTs」,但記憶與角色切換的行為依然不穩
- 缺乏 thread 的資料庫化管理,也難以做多任務切換
🧑💻 為什麼我選擇自建 YamAgent?
因為我不想再受限於 OpenAI 的沙盒規則、context window、甚至商業政策的不確定性。我想要一個:
- 可以自己定義人格、記憶、行為模式
- 可以連接我自己的 DB、API、時間來源
- 可以在我不使用雲端時仍然本地運作的 AI 系統
這也是為什麼 YamAgent 的設計原則,是以「全地端 + 高自由度」為核心,自己掌握 context loading、token 控管、人格模組與資料儲存方式。
🔧 技術補充:我如何解決 ChatGPT 系統性限制?
- 透過 Python
datetime.now()
讓 agent 知道「現在幾點」 - 自建
/yamlog
與/token-usage
API 模組,記錄每日學習與花費 - 把所有記憶存在 PostgreSQL,不再依賴 ephemeral context
- 自訂角色人格 schema,未來可開發多人格模組(已預設 mentor 角色)
這是為了「能長期依賴與穩定使用」這個系統。
🖥 YamAgent 的本地部署流程與架構實作
🏠 為什麼部署在本地 ThinkPad?
我不希望自己的對話、記憶、個人日誌都放在雲端商業平台。
我想要掌握所有資料與操作權,因此選擇把整個 YamAgent 系統部署在我自己家裡的 ThinkPad X1 Gen11 上。
這台機器配備:
- 32GB RAM / 1TB SSD
- WSL Ubuntu 系統
- 長期開機並穩定運行我的個人助理系統與日誌記錄
🧠 系統組成(全地端)
我將整個系統切為三個模組:
yamagent
(後端 FastAPI):- 提供 /chat、/session、/memory、/yamlog、/token-usage 等 API
- 使用 PostgreSQL 作為資料儲存,部署於本地
yamagent-web
(前端 Vite + React):- 包含 chat UI、token 統計頁、session sidebar 等功能
- 打包後部署至
/var/www/yamagent-web
Nginx
:- 轉址
/api
到本地 FastAPI - 靜態服務前端 SPA
- 轉址
🌐 Tailscale 內網架構
我希望能在公司 MacBook 上開發,家裡 ThinkPad 上部署。
因此我使用 Tailscale 架設私人內網 VPN,讓兩台電腦能穩定互通。
- MacBook M4 為主開發機
- ThinkPad 為穩定部署主機
- 使用 Tailscale 分配的內網 IP(例如
100.x.x.x
)互通
我也曾遇過:
- Tailscale 掛掉後無法遠端打開 YamAgent
- 服務自動中斷需手動重啟(目前計畫導入 systemd 或 PM2 處理)
🏁 部署過程重點紀錄
- WSL 安裝 PostgreSQL,設好 local superuser
yamuser
- poetry + uvicorn 運行 FastAPI,並在開機後啟動
- 前端打包後以 Nginx 提供
/
靜態頁面,API 用/api/
反向代理 - 使用
highlight.js
提升 Markdown 渲染品質 - 使用
.env
控制 API Key、DB 連線設定等
✅ 為什麼這樣部署?
這樣的部署方式滿足我以下需求:
- 私有:所有資料掌控在我自己手上
- 低成本:不需花雲端主機錢
- 可擴充:未來要加 voice-to-text / 任務整合都能接在這架構上
- 跨地點開發:公司與家中機器透過 Tailscale 無縫連線
💭 結語
YamAgent 是我親手為自己打造的「思考副駕駛」,幫助我建立節奏、記憶內容、回顧進度。