├── Dockerfile ├── Makefile ├── README.md ├── docker-compose.yml ├── main.py └── requirements.txt /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-buster 2 | 3 | RUN apt-get update 4 | 5 | COPY requirements.txt /requirements.txt 6 | COPY main.py /main.py 7 | 8 | RUN apt-get clean 9 | 10 | RUN pip install --upgrade pip 11 | 12 | RUN pip install -r requirements.txt 13 | 14 | 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | do1: 2 | apt-get update 3 | 4 | apt-get install -y docker.io 5 | 6 | apt-get install curl git bzip2 -y 7 | 8 | curl https://pyenv.run | bash 9 | do2: 10 | pyenv install miniconda3-3.9-4.12.0 11 | 12 | pyenv global miniconda3-3.9-4.12.0 13 | 14 | pip install docker-compose 15 | dcup: 16 | docker-compose up -d --build 17 | dcdown: 18 | docker-compose down 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python-ChatGPT-TelegramBot-Docker 2 | # 一個Python ChatGPT TelegramBot快速建置平台。 3 | 4 | 5 | ### [English](https://github.com/pyfbsdk59/Python-ChatGPT-TelegramBot-Docker/blob/main/README_en.md) 6 | ### [日本語](https://github.com/pyfbsdk59/Python-ChatGPT-TelegramBot-Docker/blob/main/README_jp.md) 7 | 8 | 9 | #### 1. 初次上傳專案到github,請多包涵。初版沒有設置另外的.env檔案和環境變數。之後會改正。 10 | 11 | 12 | #### 2. 本專案參考了以下前輩的方案改成製作,只針對剛學習Python或Docker的朋友來佈置TelegramBot在VPS上: 13 | 14 | https://github.com/howarder3/GPT-Linebot-python-flask-on-vercel

15 | https://github.com/n3d1117/chatgpt-telegram-bot 16 | 17 | #### 3. 可使用任何VPS建制,例如DigitalOcean, Linode或是vultr。 用ssh連入主機,輸入帳密後, 18 | 19 | --- 20 | # 環境建制(先建制了Makefile) 21 | 22 | ### Step 1: 輸入以下指令(建制docker和pyenv環境) 23 | 24 | make do1 25 | 26 | 27 | ### Step 2: 輸入以下多行的指令。一個一個複製貼上輸入。(一共有7個指令) 28 | 29 | echo 'export LC_ALL=C.UTF-8' >> ~/.bashrc 30 | 31 | echo 'export LANG=C.UTF-8' >> ~/.bashrc 32 | 33 | echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc 34 | 35 | echo 'export PATH="$PYENV_ROOT/shims:$PATH"' >> ~/.bashrc 36 | 37 | echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc 38 | 39 | echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bashrc 40 | 41 | exec $SHELL 42 | 43 | 44 | ### Step 3: 輸入以下指令 (建制python環境且安裝docker-compose) 45 | 46 | make do2 47 | 48 | 49 | ### Step 4: 輸入 cd ~ ,到主目錄,輸入以下指令下載本專案。 50 | 51 | git clone https://github.com/pyfbsdk59/Python-ChatGPT-TelegramBot-Docker.git 52 | 53 | 54 | ### Step 5: 輸入以下指令進入本專案目錄(已建制Makefile)。 55 | 56 | cd Python-ChatGPT-TelegramBot-Docker 57 | 58 | 59 | ### Step 6a: 輸入以下指令,開始建制本專案的容器,完成後會有1個container(記得先用nano指令修改main.py的OEPNAI api key的部分,還有加入自己的TelegramBot token和自己的TG帳號的id。) 60 | 61 | make dcup 62 | 63 | ### Step 6b: 也可以不用設置Docker就直接執行,請輸入以下指令,但要先有Python環境。 64 | 65 | python main.py & 66 | 67 | ------ 68 | ### 創建Telegram機器人和取得token,請參考: 69 | https://ithelp.ithome.com.tw/articles/10245264

70 | https://tcsky.cc/tips-01-telegram-chatbot/ 71 | 72 | ### 取得自己的Telegram user id,加入機器人,取得。請參考: 73 | https://telegram.me/getidsbot

74 | https://blog.csdn.net/qq_40394269/article/details/124832889 75 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | 4 | services: 5 | pyChatGPT_TGbot: 6 | build: ./ 7 | volumes: 8 | - ./app:/app 9 | 10 | 11 | command: python main.py & 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | 4 | 5 | import telegram.constants 6 | from telegram import Update 7 | from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters 8 | import openai 9 | 10 | openai.api_key = "" #加入你的OPENAI的api key #Please add your OPENAI api key between "". 11 | 12 | 13 | chat_language = "zh" #os.getenv("INIT_LANGUAGE", default = "zh") 14 | 15 | MSG_LIST_LIMIT = 20 #int(os.getenv("MSG_LIST_LIMIT", default = 20)) 16 | LANGUAGE_TABLE = { 17 | "zh": "哈囉!", 18 | "en": "Hello!" 19 | } 20 | 21 | 22 | class Prompts: 23 | def __init__(self): 24 | self.msg_list = [] 25 | self.msg_list.append(f"AI:{LANGUAGE_TABLE[chat_language]}") 26 | 27 | def add_msg(self, new_msg): 28 | if len(self.msg_list) >= MSG_LIST_LIMIT: 29 | self.remove_msg() 30 | self.msg_list.append(new_msg) 31 | 32 | def remove_msg(self): 33 | self.msg_list.pop(0) 34 | 35 | def generate_prompt(self): 36 | return '\n'.join(self.msg_list) 37 | 38 | class ChatGPT: 39 | def __init__(self): 40 | self.prompt = Prompts() 41 | self.model = "text-davinci-003" #os.getenv("OPENAI_MODEL", default = "text-davinci-003") 42 | self.temperature = 0.9 #float(os.getenv("OPENAI_TEMPERATURE", default = 0)) 43 | self.frequency_penalty = 0 #float(os.getenv("OPENAI_FREQUENCY_PENALTY", default = 0)) 44 | self.presence_penalty = 0.6 #float(os.getenv("OPENAI_PRESENCE_PENALTY", default = 0.6)) 45 | self.max_tokens = 240 #int(os.getenv("OPENAI_MAX_TOKENS", default = 240)) 46 | 47 | def get_response(self): 48 | response = openai.Completion.create( 49 | model=self.model, 50 | prompt=self.prompt.generate_prompt(), 51 | temperature=self.temperature, 52 | frequency_penalty=self.frequency_penalty, 53 | presence_penalty=self.presence_penalty, 54 | max_tokens=self.max_tokens 55 | ) 56 | 57 | print("AI回答內容:") 58 | print(response['choices'][0]['text'].strip()) 59 | 60 | print("AI原始回覆資料內容:") 61 | print(response) 62 | 63 | return response['choices'][0]['text'].strip() 64 | 65 | def add_msg(self, text): 66 | self.prompt.add_msg(text) 67 | 68 | 69 | class ChatGPT3TelegramBot: 70 | 71 | def __init__(self): 72 | self.chatgpt = ChatGPT() 73 | 74 | # Help menu 75 | async def help(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: 76 | await update.message.reply_text("/start - Start the bot\n/reset - Reset conversation\n/help - Help menu") 77 | 78 | # Start the bot 79 | async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE): 80 | if not self.is_allowed(update): 81 | logging.info(f'User {update.message.from_user.name} is not allowed to start the bot') 82 | return 83 | 84 | logging.info('Bot started') 85 | await context.bot.send_message(chat_id=update.effective_chat.id, text="I'm a Chat-GPT3 Bot, please talk to me!") 86 | 87 | # Reset the conversation 88 | async def reset(self, update: Update, context: ContextTypes.DEFAULT_TYPE): 89 | if not self.is_allowed(update): 90 | logging.info(f'User {update.message.from_user.name} is not allowed to reset the bot') 91 | return 92 | 93 | logging.info('Resetting the conversation...') 94 | # 95 | await context.bot.send_message(chat_id=update.effective_chat.id, text="Done!") 96 | 97 | # Refresh session 98 | async def refresh(self, update: Update, context: ContextTypes.DEFAULT_TYPE): 99 | if not self.is_allowed(update): 100 | logging.info(f'User {update.message.from_user.name} is not allowed to refresh the session') 101 | return 102 | 103 | logging.info('Refreshing session...') 104 | # 105 | await context.bot.send_message(chat_id=update.effective_chat.id, text="Done!") 106 | 107 | 108 | 109 | # React to messages 110 | async def prompt(self, update: Update, context: ContextTypes.DEFAULT_TYPE): 111 | if not self.is_allowed(update): 112 | logging.info(f'User {update.message.from_user.name} is not allowed to use the bot') 113 | return 114 | 115 | logging.info(f'New message received from user {update.message.from_user.name}') 116 | await context.bot.send_chat_action(chat_id=update.effective_chat.id, action=telegram.constants.ChatAction.TYPING) 117 | 118 | ai_reply_response = self.get_chatgpt_response(update.message.text) 119 | 120 | 121 | await context.bot.send_message( 122 | chat_id=update.effective_chat.id, 123 | reply_to_message_id=update.message.message_id, 124 | text= ai_reply_response, #AI回答的內容 125 | #text=response["message"], #原始程式 126 | parse_mode=telegram.constants.ParseMode.MARKDOWN 127 | ) 128 | 129 | def get_chatgpt_response(self, user_message) -> dict: 130 | try: 131 | 132 | #user_message #接收人類問題的字詞變數 133 | self.chatgpt.prompt.add_msg(f"HUMAN:{user_message}?\n") 134 | response = self.chatgpt.get_response() #ChatGPT產生的回答 135 | 136 | print("AI回答內容2:") 137 | print(response) 138 | 139 | return response 140 | 141 | except ValueError as e: 142 | logging.info(f'Error: {e}') 143 | return {"message": "I'm having some trouble talking to you, please try again later."} 144 | 145 | async def error_handler(self, update: object, context: ContextTypes.DEFAULT_TYPE) -> None: 146 | logging.debug(f'Exception while handling an update: {context.error}') 147 | 148 | def is_allowed(self, update: Update) -> bool: 149 | 150 | allowed_chats= "" #引號中填入允許通話的Telegram id #Please add your Telegram id between "". 151 | 152 | return str(update.message.from_user.id) in allowed_chats #self.config['allowed_chats'] 153 | 154 | def run(self): 155 | #以下引號中填入你的TGBot的token #Please add your TelegramBot token between "" below. 156 | application = ApplicationBuilder().token("").build() 157 | 158 | application.add_handler(CommandHandler('start', self.start)) 159 | application.add_handler(CommandHandler('reset', self.reset)) 160 | application.add_handler(CommandHandler('help', self.help)) 161 | application.add_handler(CommandHandler('refresh', self.refresh)) 162 | application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), self.prompt)) 163 | 164 | application.add_error_handler(self.error_handler) 165 | 166 | application.run_polling() 167 | ##################################################################### 168 | 169 | def main(): 170 | logging.basicConfig( 171 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', 172 | level=logging.INFO 173 | ) 174 | 175 | telegram_bot = ChatGPT3TelegramBot() 176 | 177 | 178 | telegram_bot.run() 179 | 180 | 181 | 182 | if __name__ == '__main__': 183 | main() 184 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | python-telegram-bot==20.0a6 2 | openai 3 | 4 | 5 | --------------------------------------------------------------------------------