File size: 7,603 Bytes
7a7b4e7 805c3e0 2523ce2 7a7b4e7 2523ce2 b861d01 d4de117 7a7b4e7 36ad45e 2523ce2 68773aa 2523ce2 78edbdd 7a7b4e7 2523ce2 7a7b4e7 2523ce2 0a19f94 7a7b4e7 1ef8a31 7a7b4e7 0f33e7d 7a7b4e7 4516c53 0f33e7d 4516c53 0f33e7d 7a7b4e7 af40048 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 7a7b4e7 2523ce2 e1104cd 16d556e 7a7b4e7 2523ce2 7a7b4e7 b861d01 7a7b4e7 16d556e b861d01 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
import logging
import os
import re
import time
import traceback
from threading import Thread
from pathlib import Path
import openai
import pandas as pd
import requests
import tweepy
from huggingface_hub import upload_file
import gradio as gr
logger = logging.getLogger()
logging.basicConfig(level=logging.INFO)
logger.setLevel(logging.INFO)
bot_user_id = 1612106815096999936
bot_user_name = "RoastOrToastGPT"
persistent_storage_repo_id = "team6/roast-history"
persistent_storage_file_name = "history.csv"
persistent_storage_file_url = (
f"https://huggingface.co/datasets/{persistent_storage_repo_id}/resolve/main/{persistent_storage_file_name}"
)
# will be used to remove the @roastortoastgpt from the tweet text (case insensitive)
pattern_at_mention = re.compile(re.escape("@roastortoastgpt"), re.IGNORECASE)
print(persistent_storage_file_url)
openai_key = os.environ.get("openai_api_key")
consumer_key = os.environ.get("consumer_key")
consumer_secret_key = os.environ.get("consumer_secret_key")
access_token = os.environ.get("access_token")
access_token_secret = os.environ.get("access_token_secret")
bearer_token = os.environ.get("bearer_token")
hf_token = os.environ.get("hf_token")
client = tweepy.Client(
bearer_token=bearer_token,
consumer_key=consumer_key,
consumer_secret=consumer_secret_key,
access_token=access_token,
access_token_secret=access_token_secret,
wait_on_rate_limit=True,
)
def response(text):
openai.api_key = openai_key
response = openai.Completion.create(
engine="text-davinci-002",
prompt=text,
temperature=0.9,
max_tokens=60,
top_p=1,
frequency_penalty=0,
presence_penalty=1.0,
)
return response.choices[0].text.strip()
def roast(text):
return response(
f"Humorously mock, humiliate and hurt the user's feelings with a well-timed joke, diss or comeback based on the info.\n\nInfo: {text}\n\nResponse:"
)
def toast(text):
return response(
f"Give the user a genuine and unique compliment to make them feel good about themselves based on the info in a good style manner.\n\nInfo: {text}\n\nResponse:"
)
def reply_to_mentions():
df = pd.read_csv(persistent_storage_file_url)
last_tweet_id = df.iloc[-1]["id"]
# List of unique conversation ids that we've already responded to.
# This is to prevent us from responding to the same conversation twice.
all_convo_ids = df["conversation_id"].unique().tolist()
# get the mentions. These are both direct mentions and replies to our tweets
mentions = client.get_users_mentions(
id=bot_user_id,
expansions=["author_id", "in_reply_to_user_id", "referenced_tweets.id"],
tweet_fields=["conversation_id"],
since_id=last_tweet_id,
)
# if there are no new mentions, return
if mentions.data is None:
# log it
logger.info("No new mentions found")
return
data_to_add = {"id": [], "conversation_id": []}
# otherwise, iterate through the mentions and respond to them
# we iterate through the mentions in reverse order so that we respond to the oldest mentions first
for mention in reversed(mentions.data):
if mention.author_id == bot_user_id:
# don't respond to our own tweets
logger.info(f"Skipping {mention.id} as it is from the bot")
continue
if mention.in_reply_to_user_id == bot_user_id:
# don't respond to our own tweets
logger.info(f"Skipping {mention.id} as the tweet to roast is from the bot")
continue
if not mention.referenced_tweets:
logger.info(f"Skipping {mention.id} as it is not a reply")
continue
# if we've already responded to this conversation, skip it
# also should catch the case where we've already responded to this tweet (though that shouldn't happen)
if mention.conversation_id in all_convo_ids:
logger.info(f"Skipping {mention.id} as we've already responded to this conversation")
continue
logger.info(f"Responding to {mention.id}, which said {mention.text}")
tweet_to_roast_id = mention.referenced_tweets[0].id
tweet_to_roast = client.get_tweet(tweet_to_roast_id)
text_to_roast = tweet_to_roast.data.text
mention_text = mention.text
mention_text = pattern_at_mention.sub("", mention_text)
logger.info(f"Mention Text: {mention_text}")
if "roast" in mention_text.lower():
logger.info(f"Roasting {mention.id}")
text_out = roast(text_to_roast)
elif "toast" in mention_text.lower():
logger.info(f"Toasting {mention.id}")
text_out = toast(text_to_roast)
else:
logger.info(f"Skipping {mention.id} as it is not a roast or toast")
continue
# Quote tweet the tweet to roast
logger.info(f"Quote tweeting {tweet_to_roast_id} with response: {text_out}")
quote_tweet_response = client.create_tweet(
text=text_out,
quote_tweet_id=tweet_to_roast_id,
)
print("QUOTE TWEET RESPONSE", quote_tweet_response.data)
response_quote_tweet_id = quote_tweet_response.data.get("id")
logger.info(f"Response Quote Tweet ID: {response_quote_tweet_id}")
response_quote_tweet_url = f"https://twitter.com/{bot_user_name}/status/{response_quote_tweet_id}"
logger.info(f"Response Quote Tweet URL: {response_quote_tweet_url}")
# reply to the mention with the link to the response tweet
logger.info(f"Responding to: {mention.id}")
response_reply = client.create_tweet(
text=f"Here's my response: {response_quote_tweet_url}",
in_reply_to_tweet_id=mention.id,
)
response_reply_id = response_reply.data.get("id")
logger.info(f"Response Reply ID: {response_reply_id}")
# add the mention to the history
data_to_add["id"].append(mention.id)
data_to_add["conversation_id"].append(mention.conversation_id)
# add a line break to the log
logger.info("-" * 100)
# update the history df and upload it to the persistent storage repo
if len(data_to_add["id"]) == 0:
logger.info("No new mentions to add to the history")
return
logger.info(f"Adding {len(data_to_add['id'])} new mentions to the history")
df_to_add = pd.DataFrame(data_to_add)
df = pd.concat([df, df_to_add], ignore_index=True)
df.to_csv(persistent_storage_file_name, index=False)
upload_file(
repo_id=persistent_storage_repo_id,
path_or_fileobj=persistent_storage_file_name,
path_in_repo=persistent_storage_file_name,
repo_type="dataset",
token=hf_token,
)
def main():
logger.info("Starting up...")
while True:
try:
# Dummy request to keep the Hugging Face Space awake
# Not really working as far as I can tell
# logger.info("Pinging Hugging Face Space...")
# requests.get("https://team6-roast.hf.space/", timeout=5)
logger.info("Replying to mentions...")
reply_to_mentions()
except Exception as e:
logger.error(e)
traceback.print_exc()
logger.info("Sleeping for 30 seconds...")
time.sleep(30)
with gr.Blocks() as demo:
gr.Markdown(Path('README.md').read_text())
thread = Thread(target=main, daemon=True)
if __name__ == "__main__":
thread.start()
demo.launch() |