Files
SynologyChatbotGPT/basicBot.py
2023-03-22 16:01:29 +08:00

135 lines
4.6 KiB
Python

import json, time
import requests
import openai
from flask import Flask, request, jsonify
from settings import *
# Set up OpenAI API key
openai.api_key = openai_api_key
# In-memory conversation history storage
conversation_history = {}
def send_back_message(user_id, response_text):
payload = 'payload=' + json.dumps({
'text': response_text,
"user_ids": [int(user_id)]
})
# Add a try-except block to handle potential exceptions during the POST request
try:
response = requests.post(INCOMING_WEBHOOK_URL, payload)
# response = requests.post(INCOMING_WEBHOOK_URL, json=payload)
response.raise_for_status() # Raise an exception if the response contains an HTTP error
except requests.exceptions.RequestException as e:
print(f"Error sending message to Synology Chat: {e}")
return "Error sending message to Synology Chat", 500
def process_synology_chat_message(event):
if event.get('token') != OUTGOING_WEBHOOK_TOKEN:
return "Invalid token"
user_id = event.get('user_id')
text = event.get('text')
username = event.get('username')
# generate an instant pre-response
# time.sleep(0.1)
send_back_message(user_id, "...")
# generate and send back the proper response
response_text = generate_gpt_response(user_id, username, text)
print(response_text)
send_back_message(user_id, response_text)
return "Message processed"
def generate_gpt_response(user_id, username, message, max_conversation_length=max_conversation_length, refresh_keywords=None, max_time_gap=max_time_gap):
# max_conversation_length sets the maximum length for each conversation
# refresh_keywords store the keywords to start a new conversation
# Check for refresh_prompt input to start a new conversation
if refresh_keywords is None:
refresh_keywords = ["new", "refresh", "00", "restart", "刷新", "新话题", "退下", "结束", "over"]
if message.strip().lower() in refresh_keywords:
if user_id in conversation_history:
del conversation_history[user_id]
return "----------------------------"
current_timestamp = int(time.time())
# Check if the conversation has been idle for 30 minutes (1800 seconds)
if (user_id in conversation_history and
current_timestamp - conversation_history[user_id]["last_timestamp"] >= max_time_gap*60):
del conversation_history[user_id]
# Maintain conversation history
if user_id not in conversation_history:
conversation_history[user_id] = {"username": username, "messages": [], "last_timestamp": current_timestamp}
else:
conversation_history[user_id]["last_timestamp"] = current_timestamp
# Truncate conversation history if it exceeds the maximum length
if len(conversation_history[user_id]["messages"]) > max_conversation_length:
conversation_history[user_id]["messages"] = conversation_history[user_id]["messages"][-max_conversation_length:]
conversation_history[user_id]["messages"].append({"role": "user", "content": message})
system_prompt = chatbot_character
messages = [{"role": "system", "content": system_prompt}]
for entry in conversation_history[user_id]["messages"]:
role = entry['role']
content = entry['content']
messages.append({"role": role, "content": content})
print(f"messages: {messages}")
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
temperature=temperature,
)
response_role = response['choices'][0]['message']['role']
if response['choices'][0]['finish_reason'] == "stop":
response_text = response['choices'][0]['message']['content']
conversation_history[user_id]["messages"].append({"role": response_role, "content": response_text})
else:
conversation_history[user_id]["messages"].append({"role": response_role, "content": f"error: stop reason - {response['choices'][0]['finish_reason']}"})
return response_text
def handle_request(event):
print(f"event: {event}")
if not event:
return "Empty request body", 400
return process_synology_chat_message(event)
app = Flask(__name__)
@app.route("/webhook", methods=["POST"])
def webhook():
# Parse URL-encoded form data
form_data = request.form
# Convert the form data to a dictionary
event = {key: form_data.get(key) for key in form_data}
return handle_request(event) # Pass the event dictionary instead of the raw request body
if __name__ == "__main__":
app.run(host="0.0.0.0", port=PORT)