# Chapter10. 把 AI 帶到 Discord :+1: 完整程式碼在 https://github.com/iamalex33329/chatgpt-develop-guide-zhtw ## 其他章節 [Chapter1. OpenAI API 入門](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/S1cNMYi6T) [Chapter2. 使用 Python 呼叫 API](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/HyZBg5ia6) [Chapter3. API 參數解析與錯誤處理](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/BJWNtsh6p) [Chapter4. 打造自己的 ChatGPT](https://hackmd.io/@112356044/Hk81U96Tp) [Chapter5. 突破時空限制 - 整合搜尋功能](https://hackmd.io/@112356044/HkbVM-ApT) [Chapter6. 讓 AI 幫 AI - 自動串接流程](https://hackmd.io/@112356044/r1Ke-GR6T) [Chapter7. 網頁版聊天程式與文字生圖 Image API](https://hackmd.io/@112356044/Hyf-AvgAT) [Chapter8. 設計 LINE AI 聊天機器人](https://hackmd.io/@112356044/r1d6HsgAa) [Chapter9. 自媒體業者必看!使用 AI 自動生成高品質字幕](https://hackmd.io/@112356044/rJ2T37V0T) [Chapter11. AI 客製化投資理財應用實戰](https://hackmd.io/@112356044/HkUE0rER6) [Chapter12. 用 LangChain 實作新書宣傳自動小編](https://hackmd.io/@112356044/SybvbdN0p) ## 目錄結構 [TOC] ## 建立第一個 Discord 機器人 ### 前置作業 1. 註冊 Discord 帳號:進入[註冊頁面](https://discord.com/register),填寫個人資訊並完成驗證。 2. 建立伺服器:進入到[首頁](https://discord.com/channels/@me),點擊左側的**加號按鈕**來建立自己的伺服器。 ### 建立 Discord 開發者應用程式 要建立開發者應用程式,才能開發 Discord 機器人 1. 輸入以下網址並登入 Discord 帳號::link: https://discord.com/developers/applications 2. 建立新的開發者應用: ![Screenshot 2024-03-17 at 6.26.50 PM](https://hackmd.io/_uploads/B1VdHS4Aa.png) 3. 開始機器人權限(下滑並勾選這三個選項): ![Screenshot 2024-03-17 at 6.28.13 PM](https://hackmd.io/_uploads/ByDaSSE0T.png) > 記得點選**儲存變更**按鈕 ### 取得 TOKEN 點選左側菜單「BOT」,接著按下「Reset Token」按鈕,輸入完密碼會得到一串 TOKEN ![Screenshot 2024-03-17 at 6.31.58 PM](https://hackmd.io/_uploads/S1YjIr4R6.png) ### 將 Discord 機器人加入伺服器 加入機器人前需要建立 OAuth2 URL 的授權連結,來確定機器人進入伺服器可取得的權限。 點選左側菜單「OAuth2」,接著勾選以下選項,勾選完會得到一串 URL 連結 ![Screenshot 2024-03-17 at 6.35.49 PM](https://hackmd.io/_uploads/B1l5PrN0T.png) ![Screenshot 2024-03-17 at 6.35.59 PM](https://hackmd.io/_uploads/ByF9wBECa.png) ![Screenshot 2024-03-17 at 6.36.21 PM](https://hackmd.io/_uploads/Bkk2PrVCa.png) 將網址複製下來,並開啟 ![Screenshot 2024-03-17 at 6.36.54 PM](https://hackmd.io/_uploads/ry-ADrNCT.png) 回到伺服器會發現 BOT 已經加入到伺服器中了 ![Screenshot 2024-03-17 at 6.37.55 PM](https://hackmd.io/_uploads/rkTbdrE0T.png) ## 建立回聲機器人 首先,先下載 `discord` 套件 ``` python= !pip install discord import discord import apikey token = apikey.DISCORD_BOT_TOKEN intents = discord.Intents.default() # 取得預設的 intent intents.message_content = True # 啟用訊息內容 client = discord.Client(intents=intents) @client.event async def on_ready(): print(f'{client.user} is login!') @client.event async def on_message(message): if message.author == client.user: return await message.channel.send(message.content) client.run(token) ``` ![Screenshot 2024-03-17 at 6.51.11 PM](https://hackmd.io/_uploads/rk2XsSNRa.png) - 在 Discord 中,接收訊息、指令或是成員更新等等,稱之為「事件」,設定 intent 可以決定機器人該對哪些「事件」進行回覆。 - 使用 decorator 設定「當某事件發生時,程式該如何回應」 - 當接收到的訊息是機器人本人時**跳出函式**,避免陷入無窮迴圈 ## 讓 Discord 機器人只處理指名給自己的訊息 若使用者越來越多時,每個人都呼叫機器人會讓版面變得很混亂,因此這邊多加一個設定:當 `@機器人` 時,才會進行回覆 ``` python= import discord import apikey import re token = apikey.DISCORD_BOT_TOKEN intents = discord.Intents.default() # 取得預設的 intent intents.message_content = True # 啟用訊息內容 client = discord.Client(intents=intents) # 標記使用者時在訊息中的格式為 <@username> pattern_mention = re.compile(r'\s{0,1}<@\d+>\s') @client.event async def on_ready(): print(f'{client.user} is login!') @client.event async def on_message(message): if message.author == client.user: return # 只處理 @機器人 的訊息 if client.user in message.mentions: msg = re.sub(pattern_mention, '', message.content) # 移除訊息中指名的資訊 await message.channel.send(f'{message.author.mention} {msg}') # 回覆時指名原發言者 client.run(token) ``` ![Screenshot 2024-03-17 at 6.52.23 PM](https://hackmd.io/_uploads/SJW_oS40p.png) ## 加入 AI 的 Discord 機器人 ``` python= from googlesearch import search import discord import openai import apikey import re openai.api_key = apikey.OPENAI_API_KEY hist = [] backtrace = 2 def get_reply(messages): try: response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=messages ) reply = response["choices"][0]["message"]["content"] except openai.OpenAIError as err: reply = f"An {err.error.type} error occurred\n{err.error.message}" return reply def chat(sys_msg, user_msg, use_web): web_res = [] if use_web: content = "The following are established facts:\n" for res in search(user_msg, advanced=True, num_results=5): content += f"Title: {res.title}\nSummary: {res.description}\n\n" content += "Please answer the following questions based on the above facts:\n" web_res = [{"role": "user", "content": content}] web_res.append({"role": "user", "content": user_msg}) while len(hist) >= 2 * backtrace: hist.pop(0) reply = get_reply(hist + web_res + [{"role": "system", "content": sys_msg}]) hist.append({"role": "user", "content": user_msg}) while len(hist) >= 2 * backtrace: hist.pop(0) hist.append({"role": "assistant", "content": reply}) if use_web: reply = f"The following reply is based on internet information:\n\n{reply}" return reply prompt_for_check_web = """ {} ''' {} ''' If needed, please clearly reply with "Y"; if not, clearly reply with "N", do not add any extra words. """ def check_tool(prompt, msg): reply = get_reply( [{"role": "user", "content": prompt_for_check_web.format(prompt, msg)}] ) print(reply) return reply == "Y" token = apikey.DISCORD_BOT_TOKEN intents = discord.Intents.default() intents.message_content = True client = discord.Client(intents=intents) pattern_mention = re.compile(r"\s{0,1}<@\d+>\s") @client.event async def on_ready(): print(f"{client.user} is logged in") @client.event async def on_message(message): if message.author == client.user: return if not client.user in message.mentions: return msg = re.sub(pattern_mention, "", message.content) draw_pict = check_tool( "Confirm whether drawing a picture is required for the following:", msg ) if draw_pict: response = openai.Image.create(prompt=msg, n=1, size="1024x1024") image_url = response["data"][0]["url"] await message.channel.send(image_url) return use_web = check_tool( "If I want to know the following, confirm if internet search is needed:", msg ) reply_msg = chat("Assistant", msg, use_web) await message.channel.send(f"{message.author.mention} {reply_msg}") client.run(token) ``` ![Screenshot 2024-03-17 at 6.59.19 PM](https://hackmd.io/_uploads/By4MpS4Ap.png) 1. 使用者發送訊息 2. AI 判斷訊息是否需要繪圖工具來完成 - if Y - 呼叫繪圖工具並跳出函式 - else N - AI 判斷訊息是否需要網路搜尋來完成 - if Y - 搜尋網路資訊來回答 - if N - AI 自行回答