介绍
在本教程中,我们将构建一个可以与Openai的聊天机器人ChatGPT互动的电报机器人。 Chatgpt是一种大型语言模型,可以理解和生成类似人类的文本。
本教程将向您展示如何创建可以将消息发送到chatgpt并从中接收响应的电报机器人。
目录
- Introduction
- Table Of Contents
- Prerequisites
- Step 1: Import the necessary libraries
- Step 2: Setup environment variables
- Step 3: Load the environment variables
- Step 4: Define the ChatGPT methods
- Step 5: Define the send and receive method
- Step 6: Define the telegram methods
- Step 7: Listening for messages
- Step 8: Starting up our app
- Results
- Conclusion
先决条件
- 电报帐户和电报机器人。如果您没有电报机器人,则可以通过关注these steps轻松创建一个。
- 一个OpenAI帐户。您可以创建一个here。
- 系统上安装了3.7或更高的系统
- 使用PIP安装的请求,剧作家和dotenv库
让我们开始!
步骤1:导入必要的库
在我们开始构建电报机器人之前,我们需要导入必要的库。
我们将使用requests
库向Telegram API,playwright
库与Chatgpt进行交互以及dotenv
和os
库向环境变量加载我们的OpenAI API凭据。
此外,我们将使用time
和re
库分别暂停代码执行和检查正则表达式。
如果您没有任何库,只需使用pip install
命令安装它们。
import time
import re
import os
import requests
from dotenv import load_dotenv
from playwright.sync_api import sync_playwright
步骤2:设置环境变量
首先,是时候设置我们的环境变量了。
Telegram_token环境变量用于存储我们的电报机器人的令牌。这是一串长字母和数字,用于用电报API对机器人进行身份验证。我们需要这个令牌能够从电报发送和接收消息。
CHAT_ID环境变量用于存储允许使用我们的机器人的聊天ID的逗号分隔集合。 CHAT_ID是电报上每个聊天的唯一标识符,我们可以使用它来允许某些用户使用我们的机器人。这样,我们可以将机器人保密,只允许我们的朋友使用它。
注意:chat_id env变量是可选的。
我们将在我们项目的根部创建一个.env
文件。它应该看起来像这样:
TELEGRAM_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
CHAT_ID=-246810121416, 0123456789
步骤3:加载环境变量
接下来,我们将从环境变量加载OpenAI API凭据。我们将使用load_dotenv
函数来从与脚本相同的目录中名为.env的文件中加载环境变量。
load_dotenv()
步骤4:定义chatgpt方法
接下来,我们将定义一些方法,使我们能够与chatgpt互动。第一个方法get_input_box
将返回文本中心,我们可以在其中输入邮件到chatgpt。
is_logged_in
方法将通过在输入TextArea上查找root
数据ID来检查我们是否已登录到Chatgpt。
send_message
方法将通过输入输入文本方面的消息并按Enter键来向Chatgpt发送消息。
最后,get_last_message
方法将通过查询页面以使用 convertyItem message class。
这是代码:
def get_input_box():
return PAGE.query_selector("textarea")
def is_logged_in():
return get_input_box() is not None
def send_message(message):
box = get_input_box()
box.click()
box.fill(message)
box.press("Enter")
def get_last_message():
last_page_element_text = PAGE.query_selector_all("div[class*='ConversationItem__Message']")[-1].inner_text()
time.sleep(1)
last_page_element_text_latest = PAGE.query_selector_all("div[class*='ConversationItem__Message']")[-1].inner_text()
if last_page_element_text == last_page_element_text_latest:
return last_page_element_text
else:
# print(f"Last message changed from '{last_page_element_text}' to '{last_page_element_text_latest}'")
return get_last_message()
get_last_message
方法用于检索Chatgpt的最新消息。
它通过查询 div 元素的页面使用 ConvertyItem 消息类来做到这一点。 Chatgpt使用此类来样式消息,因此,通过查询此类元素,我们可以从Chatgpt中找到最新消息。
该方法首先在此类中检索最后一个元素的内部文本,然后等待一秒钟,然后再次通过此类重新检索最后一个元素的内部文本。如果两个文本相同,则返回文本。如果它们与众不同,则意味着最后一条消息已更改,并且再次调用以检索最新消息。
这是必要的,因为Chatgpt可能需要一些时间来生成回复,因此我们需要确保我们只返回完整的响应,而不是Chatgpt仍在生成的答复。
步骤5:定义send_and_receive方法
接下来,我们将定义send_and_receive
方法,该方法将用于向chatgpt发送消息并从中获得响应。此方法将消息作为输入输入,并使用我们之前定义的send_message
方法将其发送到chatgpt。然后,它等待chatgpt的回复并返回。如果chatgpt在一定时间内没有响应,则该方法将在放弃并返回错误消息之前重试几次。
这是send_and_receive
方法的工作方式:
- 该方法将消息作为输入输入,并使用send_message方法将其发送到chatgpt。
- 它等待chatgpt的响应一定时间(需要的时间越长,等待时间就越长)。
- 如果它收到响应,它将返回。
- 如果在那段时间内没有收到响应,它将重试几次(越恢复越多,等待响应的时间越长) )
- 在第三次重试后,它将放弃并返回错误消息。
def send_and_receive(message, trial=1):
if trial == 1:
send_message(message)
time.sleep(5*trial)
response = str(get_last_message()).strip()
# its important to use a regex to check if the response is empty or not
if (not response or re.match(r"^[^a-zA-Z0-9]$", response)) and trial <= 3:
return send_and_receive(message, trial=trial*1.5)
elif trial > 3:
return "<ChatGPT is not responding.>"
return response
步骤6:定义电报方法
接下来,我们将定义一些方法,使我们能够与Telegram API进行交互。第一种方法send_message_to_telegram
将用于向将原始消息发送到我们的机器人的电报用户发送消息。它获取了消息,用户的chat_id
和原始消息的message_id
作为输入,并使用Telegram API将消息发送给用户。
check_chat_id
函数将用户的chat_id
作为输入,如果允许用户使用我们的机器人,则返回true,或者如果不允许使用我们的bot。此功能用于根据我们在CHAT_ID环境变量中指定的允许聊天ID的列表来检查用户是否可以使用我们的机器人。如果CHAT_ID
Env变量无效或不可用,则此函数默认为true。
last_update = 0
url = f"https://api.telegram.org/bot{os.environ['TELEGRAM_TOKEN']}"
def send_message_to_telegram(message, chat_id, message_id):
global url
params = {"chat_id": chat_id, "reply_to_message_id": message_id, "text": message}
response = requests.get(url+"/sendMessage", params)
if response.status_code == 200:
print("Sent response to telegram successfully")
else:
print("Error sending response to telegram:", response.text)
return None
def check_chat_id(chat_id):
try:
chat_id_env = os.environ['CHAT_ID']
except:
return True
if chat_id_env == "":
return True
chat_id_list = chat_id_env.split(',')
chat_id_list = [x.strip() for x in chat_id_list]
return str(chat_id) in chat_id_list
check_for_new_updates
功能用于检查电报API的新更新。此功能定期调用,以检查电报用户的新消息。
这是其工作原理:
- 该功能使用 /getupdates endpoint < /li>从电报API获取更新列表< /li>
- 然后循环浏览更新列表并检查任何新消息。
- 它跳过无效(非消息)更新。
- 如果它找到了有效的新消息,它将检查发送消息的用户是否允许使用Check_chat_id方法使用我们的机器人。
- 如果允许用户使用我们的机器人,它将使用
send_and_receive
方法将消息发送给chatgpt,并从chatgpt获得响应。 - 然后,它将响应发送给使用
send_message_to_telegram
方法发送原始消息的用户。
def check_for_new_updates():
params = {"allowed_updates": ["message"]}
global last_update
if last_update != 0:
params['offset'] = last_update + 1
response = requests.get(url+"/getUpdates", params)
if response.status_code == 200:
data = response.json()
if data["ok"]:
if data["result"]:
for update in data["result"]:
try:
key = 'message' if 'message' in update else 'edited_message'
try:
# get the chat id
chat_id = update[key]["chat"]["id"]
message_id = update[key]["message_id"]
except:
last_update = update['update_id']
# print("Neither message nor edited_message found in update")
continue
if not check_chat_id(chat_id):
last_update = update['update_id']
# print("Chat ID not allowed")
continue
# get the message and send it to openai and receive a response
message = update[key]["text"]
response = send_and_receive(message)
# send the response to telegram
send_message_to_telegram(response, chat_id, message_id)
last_update = update['update_id']
except Exception as e:
print("Error processing update", update['update_id'], e)
return data["result"][0]
else:
print("No new updates")
return None
print("Error getting updates:", response.text)
步骤7:聆听消息
check_for_new_updates_periodically
功能用于定期检查Telegram API的新更新。此功能每5秒调用一次,它调用了我们之前定义的check_for_new_updates
函数,以检查电报用户的新消息。如果有任何新消息,该函数将使用send_and_receive
使用chatgpt处理它们,并以我们之前定义的send_message_to_telegram
方法发送响应。
这是代码:
def check_for_new_updates_periodically():
while True:
check_for_new_updates()
time.sleep(5)
步骤8:启动我们的应用
start_browser
函数用于启动浏览器并创建一个新页面。该功能在我们代码的开头调用,它使用剧作家库启动浏览器并创建一个新页面。
start_browser函数用于启动浏览器,导航到OpenAI聊天网站,并检查用户是否登录。
此功能在我们的代码开头调用,它使用剧作家库启动浏览器,导航到OpenAI聊天网站,并检查用户是否已登录。
def start_browser():
global PAGE
PLAY = sync_playwright().start()
BROWSER = PLAY.chromium.launch_persistent_context(
user_data_dir="/tmp/playwright",
headless=False,
)
PAGE = BROWSER.new_page()
PAGE.goto("https://chat.openai.com/")
if not is_logged_in():
print("Please log in to OpenAI Chat")
print("Press enter when you're done")
input()
else:
check_for_new_updates_periodically()
if __name__ == "__main__":
start_browser()
-
user_data_dir
选项指定将存储浏览器用户数据的目录。 -
headless
选项指定浏览器是否应在无头模式下运行。在这种情况下,浏览器不会以无头模式运行,因此运行代码时可以在屏幕上看到它。 >注意:在代码的第一次运行期间将无头设置很重要,以便您可以使用凭据登录OpenAI。
运行此脚本时,将发生以下内容:
- start_browser函数将被调用以启动浏览器,导航到OpenAI聊天网站,并检查用户是否登录。
- 如果用户未登录OpenAI聊天,将打印一条消息,要求用户登录。
- 如果用户登录,则将调用Check_FOR_NEW_UPDATES_PERIODALICY函数以启动我们代码的主循环,该循环会聆听电报消息并相应地响应。
结果
结论
总而言之,本文向您展示了如何使用剧作家库和Telegram API创建电报机器人。我们详细说明了每个步骤,并为每个步骤提供了代码段。
我们希望本教程有所帮助,现在您可以更好地了解如何为Chatgpt创建电报机器人。请记住,您可以自定义the code来满足您的需求,并尝试不同的设置和选项,以了解它们如何影响机器人的行为。
还值得一提的是,本文的大多数是由openai培训的大型语言模型Chatgpt 撰写的。 Chatgpt能够理解代码并提供明确的解释和示例,因此对于想要了解有关创建机器人和其他应用程序的更多开发人员来说,这是一个很好的工具。您可以通过访问https://beta.openai.com/docs/chat/overview来尝试一下。
您查看此项目的存储库here。
现在就全部。
再见! ð