使用 n8n 以及 OpenAI API 打造 ChatGPT Telegram 機器人

使用 n8n 以及 OpenAI API 打造 ChatGPT Telegram 機器人

當下最火紅的話題應該就是 ChatGPT,他是一個由 OpenAI 公司打造的智慧型聊天機器人,它跟傳統聊天機器人最大的差別就在於,它不是基於規則的一問一答的回覆方式,而是基於深度學習模型,而且能夠理解使用者對話的上下文關係的智慧型機器人,你可以像跟人類對話一樣去問它很多問題,他都能回答上。

Introducing ChatGPT
We’ve trained a model called ChatGPT which interacts in a conversational way. The dialogue format makes it possible for ChatGPT to answer followup questions, admit its mistakes, challenge incorrect premises, and reject inappropriate requests.

網路上有很多例子,你甚至能叫 ChatGPT 去寫一篇小說出來、推薦你吃甚麼晚餐、甚至還能幫你寫 Code,還有各種很厲害的功能,各種細節有興趣的都可以到網路上搜尋相關的文章。

OpenAI API

當然,在 ChatGPT 網頁上就能直接使用這個機器人做對話,但如果你想要做一些進階應用,當然還是有 API 可以做串接會更方便做一些二次開發。

OpenAI API
An API for accessing new AI models developed by OpenAI

很幸運的是,前陣子 OpenAI 開放了 gpt-3.5-turbo 這個模型的 API 讓大家免費試用,額度為前三個月提供 18 USD 的 API 額度可以免費試用。

計費方式可以參考下面的連結,基本上用傳遞給 API 的文字數量做計費,以自己玩玩的用途,基本上用不太完。

Pricing
Simple and flexible. Only pay for what you use.

前置準備

n8n 環境

首先大家需要有一個可以使用的 n8n 環境,細節之前的文章有介紹過,大家可以參考之前的文章。

n8n 簡單易用的工作流
不知道大家有沒有這樣的情境?每天從某個開放 API 抓資料,然後發個通知,例如:股票、天氣。或是當某個 Webhook 被觸發的時候執行某個操作。 如果你有這樣的需求,又懶得寫程式再把它的部屬起來,那我相信 n8n 可以解決你的問題。 以下內容部分取自官網 介紹 n8n.io - a powerful workflow automation tooln8n is a free and source-available workflow automation toola powerful workflow automation tool0:00/1× n8n 是一個開源而且免費的自動…

想要快速開始的可以使用以下的 docker compose 檔案,裡面包含了稍後會用來儲存機器人 context 的 redis。

version: "3"
services:
  n8n:
    image: n8nio/n8n
    restart: always
    ports:
    - 5678:5678
    command:
    - n8n
    - start
    - --tunnel
    environment:
    - NODE_ENV=production
    - N8N_PORT=5678
    - GENERIC_TIMEZONE=Asia/Taipei
    volumes:
    - n8n-data:/home/node/.n8n
  redis:
    image: redis
    restart: always
    ports:
    - 6379:6379
volumes:
  n8n-data: {}

OpenAI API Key

在使用 OpenAI Chat API 之前需要準備一把 API Key,為此請大家先到這邊註冊一個帳號。

OpenAI API
An API for accessing new AI models developed by OpenAI

接著登入後到平台右上角選 View API Keys

點選 Create new secret key 並把 API Key 保存好,這把Key 只能看到一次萬一搞丟了只能重新生成。

Telegram Bot Token

有寫過 Telegram Bot 的應該都會知道,所有的機器人都需要先到 BotFather 這個機器人發行一把 Token 之後跟 Telegram 平台互動都是靠這個 Token,大家可以到下面的連結開始發行 Token。

BotFather
BotFather is the one bot to rule them all. Use it to create new bot accounts and manage your existing bots.

進入機器人後可以看到說明,解釋機器人的功能。

輸入 /newbot 指令,並指定一個不重複的機器人名稱,就可以拿到 Bot Token,記得有這把 Token 的人可以對機器人的 API 做呼叫,因此一定避免把 Token 分享給別人。

OpenAI Chat API 介紹

在前置作業做完後,簡單介紹一下如何串接,CahtGPT API,我們先到官方文件的網址。

如何發請求

OpenAI API
An API for accessing new AI models developed by OpenAI

文件旁有個 curl 指令,我們複製下來到自己喜歡的工具裡測試一下。

這裡我們用 Postman 做示範,選擇 import 把官方文件的 Curl 貼上後匯入。

接著到 Authorization 選擇 Bearer Token 貼上剛剛申請的 OpenAI API Key。

接著到 Body 的地方貼入以下請求,按下 Send 就可以得到 ChatGPT 的回答。

{
    "model": "gpt-3.5-turbo",
    "messages": [
        {
            "role": "system",
            "content": "用繁體中文回答問題"
        },
        {
            "role": "user",
            "content": "你好"
        }
    ]
}

重要請求參數說明

model

細節可以參考以下的文件,基本上都使用 gpt-3.5-turbo 就可以。

OpenAI API
An API for accessing new AI models developed by OpenAI

messages

傳遞給機器人的訊息,是一個 Array ,裡面可以把對話的歷史紀錄都傳給他,ChatGPT API 會依照對話歷史紀錄來確定對話的上下文,因此大家體會機器人可以依照你整段聊天的歷史來回答你的問題。Array 裡的每個歷史紀錄有三種 role 標籤。

system 代表的是對機器人的一種指示,例如範例中的 "用繁體中文回答問題" ,那麼機器人就會用繁體中文來回答問題,當然你也可以對它輸入,扮演一個很生氣地客服人員之類的指示,可以得到很有趣的效果。
user 代表的是使用者輸入的問題,這邊就不做解釋了。
assistant 代表的是 API 的回覆,也記得要攜帶到歷史紀錄中。

大家可以在 Postman 中手動的發請求,然後把 Array 攜帶歷史紀錄,體會一下機器人可以記住你的上下文的對話感受。

開始串接 n8n

下面是整個 n8n 的工作流的完整存檔大家可以下載後匯入,本文章就不一步一步帶大家來創立工作流,而是解釋一下重點的部分。

匯入

匯入方法也很簡單,先創建一個新的工作流之後。

在右上角選單選擇 Import from File... 匯入剛剛下載的工作流定義就能匯入完整的工作流。

匯入後會看到有很多紅色的驚嘆號圖示,那是因為缺少了各種跟外部系統溝通的 Token 接著來一一匯入。

設定 API Key & Bot Token

首先雙擊 Telegram Trigger 節點,選擇 Create New Credential 後貼上一開始申請的 Telegram Bot Token,按 Save 存檔後關閉彈窗。

如果看到其他 Telegram 節點還有紅色驚嘆號,點進去選擇剛剛存檔的 Token 就可以了。

雙擊 OpenAI 節點,選擇 Create New Credential 後貼上 API Key,按 Save 存檔後關閉彈窗。同時檢查 HTTP Request OpenAI API 節點也設定了 OpenAI API Key。

最後,進入 Redis Get Context 節點,新增 Redis 連線資訊,用文章內附的 docker compose 檔案啟動 n8n 的話照圖片上的填就行,如果是自己另外架的 Redis 就按照自己的設定填入。

最後,右上角存檔後,選 Active 把工作流啟動,接著 n8n 就會開始輪巡 Telegram 事件,就可以來跟機器人對話了。

可以試著先跟機器人說一些話,再問機器人之前對話中提到的內容,可以發現機器人可以根據之前對話的內容來回答問題。大功告成???

整體工作流介紹

大家可以先觀察工作流,可以簡單發現主要就分成兩個分支,下面這條分支主要是第一次對話時,因為沒有上下文所以使用內建的 OpenAI 節點做 API 呼叫後並把對話上下文存入 Redis 中。

而上面的分支是第二次以後的對話,從 Redis 中取出上下文,並把使用者該次的提問附加在上下文中,因為內建的 OpenAI 節點有一點缺陷,沒辦法傳遞 Array 型態的上下文,因此改用 HTTP Request 節點向 OpenAI 發請求。

第一次對話

首先看 Telegram Trigger 節點的內容,主要關心以下幾個欄位。

message.from.username 發訊息的使用名稱
message.chat.id 發訊息的聊天室 ID
message.text 訊息內容

接著的 IF /gpt 節點,則是判斷訊息內容是否為 /gpt 開頭的指令,並且指令後的內容非空才繼續往下執行。

接著的三個節點,分別為從 Redis 用聊天室 ID 以及使用者名稱作為 Key 取出上下文,由於是第一次對話,取出來沒有內容,因此在下一個 Code 節點就會照程式邏輯被填入空 Array,並在第三個節點判斷上下文陣列長度沒有大於 0 進入工作流下方分支。

接著來看在下方分支的第一個節點,用內建的 OpenAI 節點,傳入一個 system messages "用繁體中文回答",以及使用者輸入的聊天內容。

接著用聊天室 ID 以及使用者名稱作為 Key,並從前面的節點中分別把使用者的輸入,跟機器人的回答,組裝成一個 JSON Array 字串,塞進 Redis 中,並設定一小時的過期時間,這樣一小時內沒有任何對話的話機器人會自動忘記對話的上下文。

最後用 Telegram 節點發送機器人的回覆到使用者所在的聊天室。

第二次對話

前兩個節點內容跟第一次對話沒有差別,就不重複說明了,主要看第 3,4,5 個節點。

主要聊天室 ID 以及使用者名稱作為 Key 從 Redis 中取出之前聊天的上下文,必須注意這裡取出來的資料型態是 String,因此在下一個 Code 節點中,用 JSON.parse 函數解析成 Array 型態。

接著就命中了 IF 節點的長度大於 0 的條件,進入上方的分支。

上方分支的第一個節點,利用 Code 節點把使用者的訊息 push 到上下文 Array 中,並在下一個 HTTP Request 節點把完整的上下文傳入,來呼叫 OpenAI API。

接著第三個節點則把機器人的回答附加到歷史的上下文 Array 中,並在第四個節點存入 Redis 並設定一小時過期時間。最後把機器人的回覆利用 Telegram 節點發送到使用者說話的聊天室,這邊之前介紹過就不放截圖了。

結尾

這次透過 n8n 以及 OpenAI API 的整合完成了 ChatGPT Telegram 機器人,過程上沒有太多的開發,部屬也很方便,希望大家可以透過這個應用,能再次體會 n8n 的方便,並且有興趣的話可以給這個機器人增加更多功能,並在下方留言板歡迎大家討論。

感謝大家的支持!!!