├── README.md ├── requirements.txt ├── vercel.json └── api ├── prompt.py ├── chatgpt.py └── index.py /README.md: -------------------------------------------------------------------------------- 1 | # ChatGpt-LineBot 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==2.2.2 2 | line-bot-sdk 3 | openai 4 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "builds": [ 3 | { 4 | "src": "api/index.py", 5 | "use": "@vercel/python" 6 | } 7 | ], 8 | "routes": [ 9 | { 10 | "src": "/(.*)", 11 | "dest": "api/index.py" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /api/prompt.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | chat_language = os.getenv("INIT_LANGUAGE", default = "zh") 4 | 5 | MSG_LIST_LIMIT = int(os.getenv("MSG_LIST_LIMIT", default = 20)) 6 | LANGUAGE_TABLE = { 7 | "zh": "嗨!", 8 | "en": "Hi!" 9 | } 10 | 11 | class Prompt: 12 | def __init__(self): 13 | self.msg_list = [] 14 | self.msg_list.append(f"AI:{LANGUAGE_TABLE[chat_language]}") 15 | 16 | def add_msg(self, new_msg): 17 | if len(self.msg_list) >= MSG_LIST_LIMIT: 18 | self.remove_msg() 19 | self.msg_list.append(new_msg) 20 | 21 | def remove_msg(self): 22 | self.msg_list.pop(0) 23 | 24 | def generate_prompt(self): 25 | return '\n'.join(self.msg_list) 26 | -------------------------------------------------------------------------------- /api/chatgpt.py: -------------------------------------------------------------------------------- 1 | from api.prompt import Prompt 2 | 3 | import os 4 | import openai 5 | 6 | openai.api_key = os.getenv("OPENAI_API_KEY") 7 | 8 | class ChatGPT: 9 | def __init__(self): 10 | self.prompt = Prompt() 11 | #self.model = os.getenv("OPENAI_MODEL", default = "gpt-3.5-turbo") 12 | self.model = os.getenv("OPENAI_MODEL", default = "text-davinci-003") 13 | self.temperature = float(os.getenv("OPENAI_TEMPERATURE", default = 0)) 14 | self.frequency_penalty = float(os.getenv("OPENAI_FREQUENCY_PENALTY", default = 0)) 15 | self.presence_penalty = float(os.getenv("OPENAI_PRESENCE_PENALTY", default = 0.6)) 16 | self.max_tokens = int(os.getenv("OPENAI_MAX_TOKENS", default = 240)) 17 | 18 | def get_response(self): 19 | response = openai.Completion.create( 20 | model=self.model, 21 | prompt=self.prompt.generate_prompt(), 22 | temperature=self.temperature, 23 | frequency_penalty=self.frequency_penalty, 24 | presence_penalty=self.presence_penalty, 25 | max_tokens=self.max_tokens 26 | ) 27 | return response['choices'][0]['text'].strip() 28 | 29 | def add_msg(self, text): 30 | self.prompt.add_msg(text) 31 | -------------------------------------------------------------------------------- /api/index.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, abort 2 | from linebot import LineBotApi, WebhookHandler 3 | from linebot.exceptions import InvalidSignatureError 4 | from linebot.models import MessageEvent, TextMessage, TextSendMessage 5 | from api.chatgpt import ChatGPT 6 | 7 | import os 8 | 9 | line_bot_api = LineBotApi(os.getenv("LINE_CHANNEL_ACCESS_TOKEN")) 10 | line_handler = WebhookHandler(os.getenv("LINE_CHANNEL_SECRET")) 11 | working_status = os.getenv("DEFALUT_TALKING", default = "true").lower() == "true" 12 | 13 | app = Flask(__name__) 14 | chatgpt = ChatGPT() 15 | 16 | # domain root 17 | @app.route('/') 18 | def home(): 19 | return 'Hello, World!' 20 | 21 | @app.route("/webhook", methods=['POST']) 22 | def callback(): 23 | # get X-Line-Signature header value 24 | signature = request.headers['X-Line-Signature'] 25 | # get request body as text 26 | body = request.get_data(as_text=True) 27 | app.logger.info("Request body: " + body) 28 | # handle webhook body 29 | try: 30 | line_handler.handle(body, signature) 31 | except InvalidSignatureError: 32 | abort(400) 33 | return 'OK' 34 | 35 | 36 | @line_handler.add(MessageEvent, message=TextMessage) 37 | def handle_message(event): 38 | global working_status 39 | 40 | if event.message.type != "text": 41 | return 42 | 43 | if event.message.text == "啟動": 44 | working_status = True 45 | line_bot_api.reply_message( 46 | event.reply_token, 47 | TextSendMessage(text="我是時下流行的AI智能,目前可以為您服務囉,歡迎來跟我互動~")) 48 | return 49 | 50 | if event.message.text == "安靜": 51 | working_status = False 52 | line_bot_api.reply_message( 53 | event.reply_token, 54 | TextSendMessage(text="感謝您的使用,若需要我的服務,請跟我說 「啟動」 謝謝~")) 55 | return 56 | 57 | if working_status: 58 | chatgpt.add_msg(f"Human:{event.message.text}?\n") 59 | reply_msg = chatgpt.get_response().replace("AI:", "", 1) 60 | chatgpt.add_msg(f"AI:{reply_msg}\n") 61 | line_bot_api.reply_message( 62 | event.reply_token, 63 | TextSendMessage(text=reply_msg)) 64 | 65 | 66 | if __name__ == "__main__": 67 | app.run() 68 | --------------------------------------------------------------------------------