Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
slack-bolt
slack-sdk
openai
requests
85 changes: 55 additions & 30 deletions slackAskBot.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import re
import json
import requests

from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
Expand Down Expand Up @@ -47,53 +48,26 @@ def ask_chatgpt(text, user_id, channel_id, thread_ts=None, ts=None):
messages = []
if thread_ts:
messages = fetch_conversation_history(channel_id, thread_ts)
#print(f"DEBUG: Messages fetched from thread: {messages}")

# Determine channel or user name for settings
channel_name = determine_channel_or_user_name(channel_id, user_id)
print(f"Channel/user name: {channel_name}") # Print the channel name for debugging

# Load channel-specific settings
system_prompt, please_wait_message = load_channel_settings(channel_name)
#print(f"Using system_prompt: '{system_prompt}'")
print(f"Using please_wait_message: '{please_wait_message}' for channel/user name: {channel_name}")

# Get the bot's user ID
bot_user_id = app.client.auth_test()["user_id"]

# Construct the conversation history
conversation_history = construct_conversation_history(messages, bot_user_id, user_id, text, thread_ts, ts)
#print(f"DEBUG: Constructed conversation history: {conversation_history}")

# Send a message to indicate that GPT-4 is working on the request and capture the timestamp
status_message_ts = post_message_to_slack(channel_id, please_wait_message, thread_ts)

def worker():
initial_header_ts = None
initial_response_ts = None
initial_footer_ts = None
initial_status_ts = None

# Generate initial response with GPT-3.5-turbo
#print(conversation_history)
try:
initial_response, initial_status_ts = gpt(conversation_history, system_prompt, model="gpt-3.5-turbo-16k", max_tokens=1000, channel_id=channel_id, thread_ts=thread_ts)
# Modify the markdown to strip out the language specifier after the triple backticks
initial_response = re.sub(r'```[a-zA-Z]+', '```', initial_response)
print(initial_response)
# Post the GPT-3.5-turbo response and save its timestamp
initial_header_ts = post_message_to_slack(channel_id, "Initial GPT-3.5-Turbo response:", thread_ts)
initial_response_ts = post_message_to_slack(channel_id, f"{initial_response}", thread_ts)
initial_footer_ts = post_message_to_slack(channel_id, "Checking that with GPT-4...", thread_ts)
# Append the initial GPT-3.5-turbo response to the conversation history
conversation_history.append({"role": "assistant", "content": f"GPT-3.5 response: {initial_response}"})

# Synthetic review process
synthetic_review = "Let’s review the GPT-3.5 response and determine whether any corrections, clarifications, or elaborations are required. If no changes are needed, reply with 'GOOD AS-IS' in all caps. If the GPT-3.5 response needs to be completely replaced, don't refer to it: just respond with a new message, and the old one be deleted and not visible. DO NOT make reference to 'a misunderstanding in my previous response', 'My mistake', or similar: just write a new and better response. If the GPT-3.5 response only needs clarification or elaboration, not correction, instead reply with 'ADDITIONAL RESPONSE: ' in all caps, followed by a follow-up message with any clarifications or elaborations we want to append to the last reply. If you can't tell for sure without a tool call whether the response is correct or not, go ahead and make the tool call."
conversation_history.append({"role": "assistant", "content": synthetic_review})
except Exception as e:
print(f"Error from GPT-3.5: {e}")
#print(conversation_history)
initial_header_ts, initial_response_ts, initial_footer_ts, initial_status_ts = generate_initial_response(conversation_history, system_prompt, channel_id, thread_ts)

# Enhance response with GPT-4-Turbo
enhanced_response, enhanced_response_ts = gpt(conversation_history, system_prompt, model="gpt-4-turbo-preview", channel_id=channel_id, thread_ts=thread_ts)
Expand Down Expand Up @@ -134,10 +108,30 @@ def worker():
thread = threading.Thread(target=worker)
thread.start()

def generate_initial_response(conversation_history, system_prompt, channel_id, thread_ts):
initial_header_ts = None
initial_response_ts = None
initial_footer_ts = None
initial_status_ts = None

try:
initial_response, initial_status_ts = gpt(conversation_history, system_prompt, model="gpt-3.5-turbo-16k", max_tokens=1000, channel_id=channel_id, thread_ts=thread_ts)
initial_response = re.sub(r'```[a-zA-Z]+', '```', initial_response)
print(initial_response)
initial_header_ts = post_message_to_slack(channel_id, "Initial GPT-3.5-Turbo response:", thread_ts)
initial_response_ts = post_message_to_slack(channel_id, f"{initial_response}", thread_ts)
initial_footer_ts = post_message_to_slack(channel_id, "Checking that with GPT-4...", thread_ts)
conversation_history.append({"role": "assistant", "content": f"GPT-3.5 response: {initial_response}"})
synthetic_review = "Let's review the GPT-3.5 response and determine whether any corrections, clarifications, or elaborations are required. If no changes are needed, reply with 'GOOD AS-IS' in all caps. If the GPT-3.5 response needs to be completely replaced, don't refer to it: just respond with a new message, and the old one be deleted and not visible. DO NOT make reference to 'a misunderstanding in my previous response', 'My mistake', or similar: just write a new and better response. If the GPT-3.5 response only needs clarification or elaboration, not correction, instead reply with 'ADDITIONAL RESPONSE: ' in all caps, followed by a follow-up message with any clarifications or elaborations we want to append to the last reply. If you can't tell for sure without a tool call whether the response is correct or not, go ahead and make the tool call."
conversation_history.append({"role": "assistant", "content": synthetic_review})
except Exception as e:
print(f"Error from GPT-3.5: {e}")

return initial_header_ts, initial_response_ts, initial_footer_ts, initial_status_ts

def fetch_conversation_history(channel_id, thread_ts):
try:
history = app.client.conversations_replies(channel=channel_id, ts=thread_ts)
#print(f"DEBUG: Fetched conversation history for channel {channel_id} and thread {thread_ts}. Messages count: {len(history['messages'])}")
return history['messages']
except SlackApiError as e:
print(f"Failed to fetch conversation history: {e}")
Expand Down Expand Up @@ -197,6 +191,21 @@ def construct_conversation_history(messages, bot_user_id, user_id, current_text,
content = msg.get("text")
if content:
conversation_history.append({"role": role, "content": content})
if 'files' in msg:
for file in msg['files']:
if file['filetype'] in ['text', 'python', 'javascript', 'html', 'diff']: # Add other file types as needed
url = file['url_private']
headers = {"Authorization": f"Bearer {os.environ['SLACK_BOT_TOKEN']}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
print(f"Successfully retrieved file content from URL: {url}")
#print(f"Response: {response.text}")
conversation_history.append({"role": role, "content": response.text})
else:
print(f"Failed to retrieve file content from URL: {url}")
print(f"Response status code: {response.status_code}")
else:
print(f"Not adding file type {file['filetype']}")

# Add the current message to the conversation history if it's not already included
if not thread_ts or thread_ts == ts:
Expand Down Expand Up @@ -338,7 +347,23 @@ def gpt(conversation_history, system_prompt, channel_id, thread_ts=None, model="
if tools_parameter:
request_payload["tools"] = tools_parameter

response = client.chat.completions.create(**request_payload)
# Serialize the request payload to JSON for size check
serialized_payload = json.dumps(request_payload)
if len(serialized_payload.encode('utf-8')) > 128 * 1024: # Check if the payload exceeds 128 KB
print("Payload exceeds 128 KB limit.")
return "This thread is too long. Please start another shorter thread.", None

try:
response = client.chat.completions.create(**request_payload)
except Exception as e:
error_message = str(e)
print(f"Error from GPT: {error_message}")
if "context length" in error_message or "Request too large" in error_message:
if model == "gpt-3.5-turbo-16k":
post_message_to_slack(channel_id, "This thread is too long for GPT-3.5. Please wait for GPT-4.", thread_ts)
elif model == "gpt-4-turbo-preview":
post_message_to_slack(channel_id, "This thread is too long for GPT-4. Please start another shorter thread.", thread_ts)
return None, "error"

# Debugging: Print the entire GPT response
print("GPT Response:", response)
Expand Down