更新於 2024/12/16閱讀時間約 18 分鐘

OPEN AI x ChatGPT x LineBot 串接完整全紀錄

步驟:
S1.至OPEN AI 取得 API KEY
S2.至LineBot 取得 Channel access token 、Channel secret 並 進行相關設定
S3.至Vercel 申請免費伺服器並連結 GitHub原碼
S4.GitHub上傳原碼(index.py、chatgpt.py、prompt.py、requirements.txt、vercel.json)
S5.至Vercel進行伺服器設定(此處主要為原碼與環境變數,也就是將S1 & S2 的api key 與 權杖 進行設定,取得進行 Webhook用的網址),成功後可看到 Hello World 字眼
S6.至LineBot 進行 WebHook設定,完成後即可在Line上進行測試

詳細步驟流程:

取得OPEN API KEY

首先至OPEN AI 取得 API KEY,詳細可參閱 OPENAI 聊天機器人 文章

LineBot Channel access token 、Channel secret

取得 LineBot Channel access token 、Channel secret 後 至 Line BOT 控制台 申請 LineBot Key
申請方式,可參照 LineBOt 建置影片
其中要注意,此處為
點擊後方 Edit 可進到中文頁面修改
設定完成後 至 vercel 申請免費伺服器

Vercel 匯入 GitHub 原碼

申請完成後,匯入 GitHub 原碼
若沒 GitHub 則需至 GitHub官網註冊
GitHub上傳原碼 可在官網下載工具使用

原碼部分

from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
from api.chatgpt import ChatGPT

import os

line_bot_api = LineBotApi(os.getenv("LINE_CHANNEL_ACCESS_TOKEN"))
line_handler = WebhookHandler(os.getenv("LINE_CHANNEL_SECRET"))
working_status = os.getenv("DEFALUT_TALKING", default = "true").lower() == "true"

app = Flask(__name__)
chatgpt = ChatGPT()

# domain root
@app.route('/')
def home():
    return 'Hello, World!'

@app.route("/webhook", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']
    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)
    # handle webhook body
    try:
        line_handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'


@line_handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    global working_status
    
    if event.message.type != "text":
        return

    working_status = True

    if working_status:
        chatgpt.add_msg(f"Human:{event.message.text}?\n")
        reply_msg = chatgpt.get_response().replace("AI:", "", 1)
        chatgpt.add_msg(f"AI:{reply_msg}\n")
        line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=reply_msg))


if __name__ == "__main__":
    app.run()

chatgpt.py 可參考 OPEN AI 聊天機器人Chat範例
from api.prompt import Prompt

import os
import openai

openai.api_key = os.getenv("OPENAI_API_KEY")


class ChatGPT:
    def __init__(self):
        self.prompt = Prompt()
        self.model = os.getenv("OPENAI_MODEL", default = "text-davinci-003")
        self.temperature = float(os.getenv("OPENAI_TEMPERATURE", default = 0))
        self.frequency_penalty = float(os.getenv("OPENAI_FREQUENCY_PENALTY", default = 0))
        self.presence_penalty = float(os.getenv("OPENAI_PRESENCE_PENALTY", default = 0.6))
        self.max_tokens = int(os.getenv("OPENAI_MAX_TOKENS", default = 240))

    def get_response(self):
        response = openai.Completion.create(
            model=self.model,
            prompt=self.prompt.generate_prompt(),
            temperature=self.temperature,
            frequency_penalty=self.frequency_penalty,
            presence_penalty=self.presence_penalty,
            max_tokens=self.max_tokens
        )
        return response['choices'][0]['text'].strip()

    def add_msg(self, text):
        self.prompt.add_msg(text)

prompt.py 可參考 vercel 官網提供的 python flask 範例
import os

chat_language = os.getenv("INIT_LANGUAGE", default = "zh")

MSG_LIST_LIMIT = int(os.getenv("MSG_LIST_LIMIT", default = 20))
LANGUAGE_TABLE = {
  "zh": "嗨!",
  "en": "Hi!"
}

class Prompt:
    def __init__(self):
        self.msg_list = []
        self.msg_list.append(f"AI:{LANGUAGE_TABLE[chat_language]}")
    
    def add_msg(self, new_msg):
        if len(self.msg_list) >= MSG_LIST_LIMIT:
            self.remove_msg()
        self.msg_list.append(new_msg)

    def remove_msg(self):
        self.msg_list.pop(0)

    def generate_prompt(self):
        return '\n'.join(self.msg_list)

此外,根據vercel官網提供的 python flask建置,還須注意
You can install dependencies for your Python projects by defining them in requirements.txt or a Pipfile with corresponding Pipfile.lock.
requirements.txt
Flask==2.2.2
這件事,將版本與相關的SDK建立 requirements.txt
Flask==2.2.2
line-bot-sdk
openai
還有,vercel.json 用來,指定路徑進入點的
{
  "builds": [
    {
      "src": "api/index.py",
      "use": "@vercel/python"
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "api/index.py"
    }
  ]
}

完成後,透過 GitHub 工具上傳
上傳完成後,返回 vercel 進行 import

Vercel Environment Variables 環境設定

點擊 Environment Variables 進行環境設定,將OPEN AI & LineBot API KEY 進行輸入設定,完成後 點擊 Deploy

LineBot Webhook 設定

完成後,複製 DOMAINS 路徑,返回 LineBot後台
將路徑貼上,並在路徑後方加上 webhook,原因是我們在 index.py處
@app.route("/webhook", methods=['POST'])
將路徑引到此處與LineBot透過post方式傳輸資料
至此就可以進行測試囉~

QA

chatgpt 與 openai gpt3 有何差異

chatgpt 有api嗎

使用ChatGPT API
若要使用 ChatGPT 作為 Line機器人的串接API
則須將 chatgpt.py 的
def get_response(self):
        response = openai.Completion.create(
            model=self.model,
            prompt=self.prompt.generate_prompt(),
            temperature=self.temperature,
            frequency_penalty=self.frequency_penalty,
            presence_penalty=self.presence_penalty,
            max_tokens=self.max_tokens
        )
        return response['choices'][0]['text'].strip()
透過ChatGPT說的進行合併修改
import openai

openai.api_key = "YOUR_API_KEY"

response = openai.Completion.create(
engine="chatbot",
prompt="Hello, how are you today?",
max_tokens=20
)

print(response.text)
不過經過測試,這裡有點有趣
依上述所言,只要改 model 就應該可以
def __init__(self):
        self.prompt = Prompt()
        self.model = "chatbot"
        self.temperature = float(os.getenv("OPENAI_TEMPERATURE", default = 0))
        self.frequency_penalty = float(os.getenv("OPENAI_FREQUENCY_PENALTY", default = 0))
        self.presence_penalty = float(os.getenv("OPENAI_PRESENCE_PENALTY", default = 0.6))
        self.max_tokens = int(os.getenv("OPENAI_MAX_TOKENS", default = 240))

    def get_response(self):
        response = openai.Completion.create(
            model=self.model,
            prompt=self.prompt.generate_prompt(),
            temperature=self.temperature,
            frequency_penalty=self.frequency_penalty,
            presence_penalty=self.presence_penalty,
            max_tokens=self.max_tokens
        )
        return response['choices'][0]['text'].strip()
But
因此~
目前就是只能用 OpenAI GPT-3 玩~

後記:

經過我的騷擾跟測試,這機器人改口了~
笑死~
本紀錄參考:
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.