記錄我把 AstrBot 接到自家網站聊天窗的過程:比較現成客服系統、以 PHP 與 Workerman 建立 WSS 中轉層、處理 Nginx 與版本相容性問題,並規劃 PHP 與 Python 雙版本依共用契約並行。
這篇是我把 AstrBot 接到自家網站聊天窗的過程紀錄。重點不在「怎麼裝」,而在「為什麼這樣選」。部署細節我只簡單帶過,網域、金鑰都已換成示意值。

一、起點:我到底要什麼

一開始的需求很單純:訪客在網頁上開一個聊天窗,輸入問題,後面由 AstrBot 的 AI 與知識庫回答。就這樣。

我先給自己定了幾條 MVP 底線:

這幾條底線,後面所有選型都是拿來對照的。

二、第一步:先確認 AstrBot 有沒有現成方案

我先查了 AstrBot 的平台與插件。結論是:它內建的 WebUI 有 ChatUI,但那是管理介面裡的對話窗,不是給外部網站嵌入的客服 widget。插件市集也沒有找到現成的「網站聊天窗」平台。

另一條路是 OneBot。我搜尋了相關開源專案,找到的多半是 QQ 風格的網頁聊天面板,用途是操作機器人帳號,沒有訪客識別、匿名會話、多訪客隔離這些客服場景需要的東西,所以也排除。

真正有用的是 AstrBot 的 HTTP API:用 API Key 驗證,呼叫對話端點就能取得 Agent 的回覆(SSE 串流),插件、工具、知識庫都能一起用,效果與 IM 端一致。這是整個方案的關鍵,因為它代表我只需要做「前端加一層薄薄的中轉」,不必碰 AstrBot 內部。

三、為什麼不直接用功能完整的開源客服系統

我當然想過「直接用現成的」。我實際比較過幾條路線:

方案我的觀察不選的原因
Live Helper ChatPHP、Apache-2.0 授權,也有 API 與 Webhook,條件看起來很吻合我真的整套裝起來試了,後台功能非常多,對「只要網頁聊天加接 AstrBot」來說過度複雜
Chatwoot 社群版MIT 授權、功能完整、有輕量 CRM技術棧是 Rails 加 PostgreSQL 加 Redis,和我現有環境不同;部分進階功能(權限、SLA 等)屬於付費企業版
UseResponse工單、知識庫、聊天一站式比較偏商業授權,自架要按客服席位計費,而且我沒找到明確的機器人對接文件
Tiledesk偏 AI 與機器人,MIT 授權Node.js 技術棧,同樣要多養一套服務
Kaplia 之類的輕量聊天技術上最貼近 WSS沒有 CRM 與工單,要自己補;成熟度與維護狀況也需要額外評估

我最後得到的判斷是:

  1. 完整客服系統的複雜度,是我暫時用不到的成本。 後台、角色、SLA、多渠道收件匣,這些功能都要有人學、有人維護、有人升級。
  2. 我真正缺的只是「一個能接 AstrBot 的聊天窗」。 現成系統的整合點(Webhook、Agent Bot)還是要我再寫一層中轉,等於複雜度沒省到,反而多了一堆我不想管的東西。
  3. 授權與計費模式要看清楚。 有些專案標榜開源,但關鍵功能在企業版目錄裡,商用前必須逐一看授權條款。

所以我的結論不是「這些系統不好」,而是「它們解決的問題,比我現在的問題大得多」。

四、為什麼選擇複用寶塔技術棧

我的伺服器本來就是寶塔面板,Nginx、PHP 8.2、MySQL 都在,網域和 SSL 也設定好了,AstrBot 還掛在同一個網域的根路徑做反向代理。

如果另外引入一個 Node 或 Rails 服務,我要多處理的是:執行環境、進程守護、反向代理、日誌、升級與備份。對一個人維運來說,每多一個技術棧,風險就多一份。

所以我選擇:

唯一的例外是 WebSocket。PHP-FPM 是「一個請求一個程序」的模型,不適合長時間維持連線。我的解法是在旁邊用 Workerman(PHP 的事件驅動 Socket 框架)跑一個只監聽本機的 WSS 服務,再由 Nginx 代理成對外的 wss://。這樣仍然是 PHP,只是多了一個常駐程序,由 systemd 管理。

五、實作細節(簡略版)

整體路徑只有幾段:

瀏覽器 ──WSS──► Nginx ──► Workerman (PHP) ──HTTP/SSE──► AstrBot API

幾個我認為重要的設計選擇:

踩到的坑

這部分我覺得比「怎麼做」更有分享價值:

  1. Nginx 的 location ^~ /chat/ 會擋住 PHP。 帶 ^~ 的前綴規則會讓 Nginx 跳過正則規則,PHP 就不會被處理,頁面變成下載。拿掉 ^~ 即可。
  2. 用 curl 測 WebSocket,結果誤判失敗。 站點開了 HTTP/2,curl 預設走 h2,但 WebSocket 的升級握手要用 HTTP/1.1。測試要加 --http1.1,瀏覽器本身沒有這問題。
  3. Workerman 5 的 onWebSocketConnect 不再填 $_SERVER 與 $_GET。 回呼的第二個參數變成 Request 物件。我照 4.x 寫法讀 Origin 和 token,結果全是空值,連線在握手前就被關掉,Nginx 因此回 502。最後靠版本號(5.2.2)加症狀推斷出原因。
  4. 權限問題:用 root 執行 composer,之後服務以 www 身分執行,pid 與日誌檔寫不進去就直接退出。
  5. 寶塔的 open_basedir:把私有程式放在站點目錄內,再用 Nginx 擋掉外部存取,是比較省事的折衷。

另外,我也寫了診斷腳本和常駐管理腳本,把「環境檢查、握手測試、日誌」包起來。對一個人維運來說,腳本化的 SOP 比記憶可靠。

六、MVP 完成之後,需求開始長大

聊天窗跑起來之後,需求自然冒出來:

這時我才認真檢視:這些功能做在哪裡最合理?

我的結論是:控制中心放在自己的中轉層,AstrBot 只當 AI 引擎與通知出口。 原因是會話狀態、在線人數、人工接手,本質上是「連線與路由」問題,而這些都發生在訪客連線所在的那一層。把它們塞進 AstrBot 插件,狀態會分散在兩個系統;而 AstrBot 對 LINE 這類平台也不一定支援主動推送,客服要在 LINE 回覆訪客這條路在 AstrBot 層面走不通,所以我把 LINE 定位成「通知轉發的目的地」,不是客服的回覆管道。客服的回覆管道以網頁後台為主,Telegram 為輔。

七、雙版本並行:PHP 還是 Python

功能長大後,我開始認真考慮用 Python 重寫。理由與顧慮都很具體,所以我把比較整理在這裡:

面向PHP + WorkermanPython + FastAPI
現況已經運作,與寶塔整合,前端頁面直接用 PHP 模板需要新服務、新 port、新的 Nginx 規則與守護程序
長連線並行多程序加事件迴圈;但我的實作在等 AstrBot 回覆時用同步 curl,會佔住整個 workerasyncio 原生,等待外部服務時不佔用連線
跨程序廣播需要 Redis 或 Workerman Channel需要 Redis Pub/Sub,生態文件與範例多
後台管理要手寫,或用現成 PHP 後台要手寫,但 API 文件(OpenAPI)可自動產生
與 AstrBot 的關係只能走 HTTP API同為 Python,日後可寫輕量插件深度整合
AI 相關處理一般生態強,摘要、向量檢索等有成熟套件
維運寶塔熟悉,PHP-FPM 與 Workerman 兩套進程虛擬環境與依賴管理,但服務模型單純
風險同步 curl 的瓶頸可局部修正全部重寫意味著所有功能要重新驗證

我想特別說明一點:Workerman 本身並不弱,真正的瓶頸是我自己用同步 curl 等待 AstrBot,這是可以在 PHP 裡改成非同步客戶端解決的。所以「為了效能換語言」並不是充分理由。

真正讓我傾向 Python 的,是長期維護:後台、狀態機、轉發連接器、跨程序傳訊,這類「狀態密集」的系統,用 asyncio 寫會比較自然,而且和 AstrBot 同語言,未來整合的空間也比較大。

但我也很清楚,現有 PHP 版已經穩定運作。因此我決定:

  1. PHP 版補完新功能後凍結,不再大改,當作穩定後備。
  2. Python 版從頭依同一份契約重寫,跑在新 port,Nginx 用 /chat2/ 分流。
  3. 兩版共用同一個 MySQL 與 Redis,將來切換時資料不用遷移。
  4. 穩定後再決定是否切換流量,或長期並行。

為什麼先定「契約」

雙版本最怕的是兩邊各長各的。所以在寫任何功能之前,我先定稿了一份共用契約:

這份契約的原則是:訊息內容先寫資料庫,事件只負責通知。Redis Pub/Sub 不保證送達,所以客服後台重連時,要用 REST 以「最後訊息 ID」補抓,才不會漏訊息。

八、還沒驗證、也不想誇大的地方

寫到這裡我必須誠實說明:

九、幾點心得

  1. 先用最小方案驗證需求,再決定要不要長大。 如果一開始就選完整客服系統,我現在可能還在研究它的後台。
  2. 複用手上的技術棧,比追求「最適合」的技術棧更重要。 對一人維運來說,少一個執行環境,就少一份夜間被叫醒的風險。
  3. 遇到問題時,先確認版本、日誌與實際回應,再下結論。 這次最花時間的兩個問題(Nginx 規則、Workerman 5 回呼差異),都是靠「看實際輸出」而不是「憑印象」解決的。
  4. 雙版本並行的關鍵不是程式碼,而是共用契約。 先把資料與事件的語言對齊,兩邊才不會越走越遠。

接下來我會先把契約審閱定稿,再補完 PHP 版的後台與人工接手,然後凍結,並在新 port 上用 Python 重新實作。如果有進展,我再來更新這篇文章。

真正意義/優缺點分析

  • 這篇的核心不是選 PHP 或 Python,而是把 AstrBot 當成 AI 引擎,訪客識別、會話狀態、人工接手與跨渠道路由放在自己的中轉層。
  • 優點:沿用既有 Nginx、PHP、MySQL 與 SSL 環境,用較低成本驗證網站聊天窗 MVP。
  • 優點:API Key 留在伺服器端,WSS、HTTP、Origin、token 與限流可集中治理。
  • 代價:Workerman 若以同步 curl 等待 AstrBot 會佔住 worker;Python 重寫則要承擔新服務、部署與雙版本一致性成本。
  • 風險:SSE 事件格式、附件 API、個資保存與刪除機制仍待實測,Python 效能優勢目前只是推論。
我的判斷:先用最小方案驗證需求,再決定是否擴展成客服後台、人工接手與雙版本服務。對一人維運而言,少一個不必要的技術棧,就是少一份長期風險。

常見問題

Q:為什麼不直接使用完整客服系統?
A:目前只需要網站聊天窗與 AstrBot 中轉層,完整客服系統的後台、角色與 SLA 會增加維運成本。

Q:為什麼 PHP 版與 Python 版要並行?
A:PHP 版已配合現有寶塔環境運作;Python 版針對長期狀態管理與 AstrBot 整合重新設計,兩者先依共用契約並行驗證。

Q:API Key 可以放在前端嗎?
A:不可以。API Key 只放伺服器端,前端經受控中轉層溝通。

本篇文章同時提供 .md 原始檔(見 markdown/astrbot-04-website-widget-architecture.md),供後續匯入 WordPress 或歸檔使用。