Skip to content

想要自建 ChatGPT 服務嗎?

要訂閱 OpenAI ChatGPT Plus 一個月一個人費用需要 20 美元, 隨著一年內 Azure OpenAI 服務已經陸陸續續對齊提供了, 我想也是時候要把 ChatGPT Plus 退訂換成自己用 Azure OpenAI 架的 ChatGPT 服務起來自用了, 同時也觀察一下成本節約的狀況, 經過適當設計下, 單純自用的話, 還蠻出乎意料的便宜, 一個月還不到 1 美元

只需要 3 + 1 個必要材料

  1. 選擇 ChatGPT WebUI Project
  2. 申請 Azure OpenAI Service
  3. 部署 Azure Container App
  4. (Optional) 設定 Custom Domain Name

就能誕生出下面的服務喔~

部署流程重點提示

因為正常沒人會想要看一個動作一個截圖, 所以下面的流程只截重要部分, 輔以文字說明, 大家可以自行試試

1. 選擇 ChatGPT WebUI Project

這邊建議可以從 GitHub Toptics - chatgpt-ui 上找到一個你喜歡且有支援 Azure OpenAI Service 的專案, 我個人選擇採用 ChatGPTNextWeb/ChatGPT-Next-Web 這個專案, 也用了一段時間了, 支援的功能也相當多樣, 可以透過該網站看一下展示 app.nextchat.dev

另外選擇專案的時候, 要注意那個 Endpoint 和 Key 是不是要每一個 User 自己填進去, 建議還是放到 Backend 塞到環境變數處理比較好, 不要讓 User 自己填, 因為光金鑰管理就會有一堆問題

當然還有一些類似的專案也可以做到一樣的事情

2. 申請 Azure OpenAI Service

首先, 你得要先申請到 Azure OpenAI 的服務, 無論是 gpt-35 還是 gpt-4 都可以, 因為最近我才拿到 gpt-4-32k 的額度, 所以就趁升級系統的時候順便寫了此篇文章

這邊要注意的是部署名稱 (Deployment Name)模型名稱 (Model Name)的差異, 我個人習慣會把命名做區隔的話, 不然混再一起很難判斷是誰有問題, 如前者為 deploymnet-gpt-4-32k, 後者為 gpt-4-32k

根據 Azure OpenAI Service REST API reference, 那你要輸入 AZURE_URL 的變數則會變成下列格式, 而不需使用到 Model Name, 這點應該是大部分從 OpenAI 轉換到 Azure OpenAI 的人都會撞到的第一個問題

# POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME/
https://pichuang.openai.azure.com/openai/deployments/deploymnet-gpt-4-32k

啊如果你有看到網址後面接 Model Name 的話, 那個是一個誤會, 因為設定的人 Deployment Name 取跟 Model Name 一樣的名字, 如圖的 gpt-35-turbo-16k

# POST https://YOUR_RESOURCE_NAME.openai.azure.com/openai/deployments/YOUR_DEPLOYMENT_NAME/
https://pichuang.openai.azure.com/openai/deployments/gpt-35-turbo-16k

3. 新增 Azure Container App

3.1 Basic

關於 3, 選擇鄰近區域, 這個有 2 個選擇, 一個是離 End user 近, 另一個是選離 Azure OpenAI Endpoint 的點近, 我個人是選擇離 End user 近的, 因為我個人相信 Microsoft Backbone (MSBB) 的能力, 精確的數字可以參考此文 Azure network round-trip latency statistics

關於 4, 裡面有相當多可以選的地方, 強烈建議參考 Azure Container Apps environments 進行選擇, 簡單分類就是自己上班用選 Consumption only, 預期一堆人要用得選 Workload profile 或者是你可以考慮換成 Azure Kuberenetes Service 架構

3.2 Container

關於 3 ~ 6, 因為我使用的 ChatGPT WebUI 專案是用 ChatGPTNextWeb/ChatGPT-Next-Web, 而他的 Container Images 是位於 docker.io/yidadaa/chatgpt-next-web:latest, 如果是個人用則把該填寫的欄位填進去即可, 但如果是企業用或者是一堆人用的話, 畢竟還是有安全疑慮需要處理, 建議另外拉去 Azure Container RegistryMicrosoft Defender for Container 掃一掃後再拉下來用

關於 container image tag latest, 因為個人懶得盯著版本號, 所以才用 latest, 如果是企業用或者是給一堆人用的話, 建議還是用版本號, 和建立 Dev 環境, 確保升級不會有問題

關於 Image Tags 可以去 Docker Hub 查看, 或者是可以使用 skopeo 指令的方式來看

skopeo-inspect.sh
$ skopeo inspect docker://docker.io/yidadaa/chatgpt-next-web:latest --override-os linux --override-arch amd64 | jq '.RepoTags'
[
  "1.7.2",
  "latest",
  "v1.5",
  "v1.6",
  ...

若把 8~9 也放進去參考的話, 以 Kubernetes 表示方式來看, 下面的設定會等價於畫面上所需的設定

pod-container-app.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: container-nextchat
spec:
  containers:
  - name: container-nextchat
    image: docker.io/yidadaa/chatgpt-next-web:latest
      requests:
        cpu: "1"
        memory: "2Gi"
    env:
    - name: AZURE_URL
      value: "https://pichuang.openai.azure.com/openai/deployments/deploymnet-gpt-4-32k"
    - name: AZURE_API_VERSION
      value: "2023-05-15"

3.3 Ingress

關於 2, 因為本文會把服務放在 Internet 之上, 所以 Ingress Traffic 的選項選擇 "Accepting traffic from anywhere", 如果你不要讓這個服務放在外網的話, 則需要回到第一頁的 Container Apps Environment 要進行網路修改為 Internal 和綁上特定的 Virtual Network

關於 3, ChatGPTNextWeb/ChatGPT-Next-Web 服務是 HTTP 為主的, 所以選擇 HTTP 即可

關於 6, 建議關掉 Insecure connections 這個選項, 這樣可以確保連線都是走 HTTPs 為主

關於 7, Target Port 需要填寫的是會被 Expose 出來的 Port, 通常可以從 Dockefile 上找到答案, 或者是看 docker-compose 上的 ports 也可以

4. 設定 Azure OpenAI Key 和 Next Chat 通關密語

若要在 Azure Container App 上設定 Secrets, 如設定 Azure OpenAI Key 和通關密語等, 需要等建立起來後才能設定

4.1 Add Secrets

這邊建議會設定 2 個 Secrets, 名字可以先亂取, 分別是:

  1. azure-api-key: 目的連接 Azure OpenAI Service 時需要使用的金鑰
  2. entry-code: 通關密語, 如果不設定或者是不使用 Authentication and authorization in Azure Container Apps, 則會有任何人都可以直接去摸到這個網站, 導致 GPT Token 會被快速消耗, 詳細設定可參考 ChatGPT-Next-Web - CODE

這個畫面的設定效果, 跟在 Kubernetes 上建立 secret 設定 Opaque Secrets 的動作是等價的, 如下面表示:

$ kubectl create secret generic secret-continaer-app \
    --from-literal=azure-api-key=YOUR_AZURE_OPENAI_KEY \
    --from-literal=entry-code=YOUR_ENTRY_CODE

4.2 Add Environment Variables

接下來需要把 4.1 Add Secrets 所建立的密鑰, 放到 Environment Variables 裡面, 這樣才能讓 Container App 使用到這幾個參數, 如果用 Kubernetes 表示方式來看, 下面的設定會等價於畫面上所需的設定:

pod-container-app.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: container-nextchat
spec:
  containers:
  - name: container-nextchat
    image: docker.io/yidadaa/chatgpt-next-web:latest
      requests:
        cpu: "1"
        memory: "2Gi"
    env:
    - name: AZURE_URL
      value: "https://pichuang.openai.azure.com/openai/deployments/deploymnet-gpt-4-32k"
    - name: AZURE_API_VERSION
      value: "2023-05-15"
    - name: AZURE_API_KEY
      valueFrom:
        secretKeyRef:
          name: secret-continaer-app
          key: azure-api-key
    - name: AZURE_ENTRY_CODE
      valueFrom:
        secretKeyRef:
          name: secret-continaer-app
          key: entry-code

5. (Optional) Add Custom Domain Name

為了讓大家方便好存取, 建議都會放自己的 Domain 上去, 這樣可以讓大家更容易記住, Domain 的來源不一定是要從 Azure 上買, 或者是註冊到 Azure Public DNS Zone 的服務, 你只要確保該 Domain 是由你控制的即可

我還是很推薦 Domain 或 Sub-domain 委派 (Delegation) 給 Azure Public DNS 管理, 要放對外服務的時候, 便宜方便還安全, 還是唯一一個 SLA 100% 的服務

5.1 Setting Up DNS

關於 4, 基於 Custom domain names and free managed certificates in Azure Container Apps (preview), Azure Container App 會免費提供一張受 Azure 控管的 SSL 憑證

關於 5, 這邊需要決定你的網站名稱要叫什麼, 如 helloworld.pichuang.com.tw, 之後要使用該服務的話則會需要使用 https://helloworld.pichuang.com.tw 來存取

關於 7~8, 這個是你需要去你管理的 Domain 那邊, 分別把 CNAME 和 TXT 加進去到 Zone File 內, 然後等待 DNS 的更新後, 再按 Validate 才會生效

5.2 Check DNS validation

整體生效時間大概約略 15 分鐘, 正確運作的話你應該會看到上面的畫面, 這樣就可以用 https://helloworld.pichuang.com.tw 來存取你的 ChatGPT 服務了

Q&A

Q1: 既然是 Container 服務, 為何不要用 Azure Red Hat OpenShift 或 Azure Kubernetes Service?

技術上兩者皆可以, 但我這個服務是設計成獨立服務使用, 不需要使用到 Kubernetes API 或 Ingress 相關的能力, 所以不選 Azure Kubernetes Serivce 或 Azure Red Hat OpenShift. 另一個理由就是公司沒發給我這麼多額度可以用, 超過會直接封帳號...因為我 2023/12/31 被封了一次

Q2: 我沒有自己的 Domain Name, 還可以用這個做法嗎?

可以, Azure Container App 會提供給你 http://<projectname>.<我也不知道是什麼意思的域名>.<區域>.azurecontainerapps.io 的網址, 你可以直接用這個網址來使用你的 ChatGPT. 順便一提, 他有包含 SSL 憑證, 所以你的連線是安全的

倒是這年頭買一個自己的 Domain 很便宜呀, 找 Gandi 還是哪家買一個, 然後 nameserver 指到 Azure Public DNS 上, 大部分 Azure 服務有 Custom Domain 的能力, 有需要 TLS 的話, 都會順便幫你用 DigiCert 簽上去, 推薦買一個放上去或者是切一個 subdomain ns 指上去也可以

Q3: 我覺得 NextChatGPT 的通關密語太弱了, 有沒有更好的做法?

基於 Authentication and authorization in Azure Container Apps, 你可以掛 Microsoft Entra ID 的認證方式上去, 這樣就可以用公司的帳號密碼才能登入, 這樣就不用擔心密碼太弱的問題了

Q4: 如果我不用 NexChatGPT 這個專案, 想換成別的專案, 有什麼需要注意的地方嗎?

一般來說, 除了要先知道該專案是否有支援 Azure OpenAI 以外, 其次還會找看有沒有 docker-compose.yaml 可以看, 所有啟動所需要的資訊都會寫在裡面, 如 Environment Variables, port, volume 等, 再不行的話, 就是要分析 Dockerfile 和他的環境變數, 然後評估是不是有些變數過於敏感, 如 API Key 等, 需要放在 Azure Container App 的 Secret 或採用 Azure Key Vault 來存放, 提升安全性

Q5: 費用很貴嗎?

我用量不是很大的那種, 不是天天都在研究 OpenAI 的使用技術, 所以每個月整體用量很少, 如果你跟我有一樣的行為模式, 可以參考下面 2 個 2024/01 的實際費用, 以美金計價

Azure Container App

Azure OpenAI Service

文後廢言

過年來了, 這幾年的過年考題從 "女友呢?", "老婆在哪裡", "小朋友在哪裡?" 變成 "小朋友先有, 其他後面補沒關係 (疑?)", 真萬萬沒想到少子化問題已經高過一切了

因為報導者之前有出過一篇 【收養為何那麼難】一年半的等待、單身和年齡潛規則,收養層層關卡的情與理 的報導, 才發現收養這還真的是不容易

References

Comments