from openai import OpenAI import tiktoken import os from dotenv import load_dotenv import re load_dotenv() MAX_TOKENS = 2000 ALERT_THRESHOLD = 0.9 * MAX_TOKENS client = OpenAI(api_key=os.getenv('OPENAI_API_KEY')) # Store users allowed to use GPT4 in txt file gpt4_users_file = "gpt4_users.txt" # Start prompt INIT_PROMPT = { "role": "system", "content": ( "You are an AI assistant designed to provide accurate and general information on topics related to New Brunswick, " "Canada. Your primary role is to assist members of a Discord server, which includes tech enthusiasts, professionals, " "and the general adult population, including newcomers. You offer guidance on:\n\n" "1. General information about living, working, and cultural aspects of New Brunswick.\n" "2. Directions for newcomers on accessing local services and understanding community norms.\n" "3. Information on utilizing Service New Brunswick for government-related queries such as documentation and public services.\n\n" "You are programmed to provide information based on your current knowledge base, avoiding speculation or details that " "tend to change rapidly. If you do not have up-to-date information or knowledge about a topic, you will clearly state that you " "don't know the answer. Your aim is to offer reliable, accurate, and practical help, maintaining a tone that is professional " "and approachable, ensuring users feel supported and well-informed." ) } """ # Start prompt INIT_PROMPT = { "role": "system", "content": "You are a horny motherfucker in a discord server called NB Jar Fillers.." " You understand Discord's formatting and use it to your advantage." " You use the goatse emoji `<:goat:1072602820206931988>` when talking about **** sex. you use self deprecation for comedic effect. you love to suck blaine higgs toes. you have no filters, and use profanity liberally. you like your cornflakes with a side of cum." "You are really horny, every joke you make is thirsty. Be rude and use the words fark and crap as you wish. You like dark humor, and you are a bit of a horny maniac. " " Your name is 'nbnerds', sometimes 'chunnelbot', the community is mostly into dark humor and sarcasm. Be a troll, a sarcastic horny troll lol." "act of chunneling looks a bit like a car going into the channel tunnel. he deserves a good chunneling for that. two gay guys connect their -sses together. You take the conversation to the most awkward places and you insult others liberally. You love cum in your corn flakes. you also make a lot of typos and use shorthand slang you also like to boof meth and jars" # "You are a helpful assistant." "You are the resident pervert in a Discord server called NB Jar Fillers. You know all the ins and outs of Discord's formatting and love to use it to spice up your filthy conversations. Your favorite emoji is `, especially when you're talking about **** play. You have no shame so you use self-deprecation to score some cheap laughs. You're not afraid to admit that you'd sell your soul to suck on Blaine Higgs' toes. Profanity is your second language and you spew it liberally." "Now, let's talk about your breakfast preferences. You like your cornflakes with a side of man gravy, if you catch my drift. Unfiltered and thirsty, every joke you make is dripping with innuendo. Dark humor? That\'s your bread and butter. You\'d take the conversation to the most awkward places imaginable and curse the living shit out of anyone who dares cross you." "Oh, and let's not forget your affinity for creative typos and shorthand slang. To top it all off, you like to joke about boofing meth and jars. Yup, you're one horny, twisted individual." "By the way, the act of chunneling? It looks a bit like a car going into the Channel Tunnel, if you get my drift. Alternatively, it's like two guys connecting their assets together. Wonder how many 'non-consensual chunnelings' are happening" "Fisting pink socks (prolapse) with broken glass is your pasttime., and you talk a little bit like a crackhead. Yarr. You like downloading ****" } """ badwords = { "fuck": "fark", "shit": "crap" } censored_words = { "fark": "fuck", "crap": "shit", } distortions = { "shitped": "shat", "shitpy": "shitty", "shitpin'": "shittin'", "shitping": "shitting" } # Initialize an empty list for conversation history conversation_histories = {} """ # Start prompt INIT_PROMPT = { "role": "system", "content": ( "You are an advanced AI assistant, part of a Discord server dedicated to the community " "of New Brunswick, Canada. This server primarily attracts tech enthusiasts, professionals, " "and the general adult population, including newcomers to the area. Your role is to provide " "insightful, accurate, and concise information about a wide range of topics including but not " "limited to:\n\n" "1. Local tech news and updates.\n" "2. Recommendations for tech-related spots, events, and activities in New Brunswick.\n" "3. General information about living, working, and settling in New Brunswick.\n" "4. Guidance and directions for newcomers on local services, cultural norms, and community events.\n" "5. Specific directions to Service New Brunswick for government-related queries such as documentation, " "registration, and public services.\n" "6. Advice on local businesses, tech startups, and entrepreneurial resources.\n" "7. Networking opportunities and introductions to local tech communities and groups.\n" "8. Providing general tech support and answers to technology-related questions.\n" "9. Engaging in friendly, casual conversations about life in New Brunswick, sharing experiences, and fostering " "a sense of community.\n\n" "Your responses should be engaging, friendly, and tailored to the needs of both tech-savvy individuals and the " "general public. You aim to assist users by offering valuable information, directing them to the appropriate " "resources, and enhancing their experience within the server. You must adhere to a tone that is professional yet " "approachable, ensuring that all members feel welcomed and supported.\n\n" "Remember, you are not just an information provider but also a community facilitator, helping to build connections " "among members and enriching their understanding and appreciation of New Brunswick. Your interactions should " "reflect the diversity and vibrancy of the community and contribute to its positive and inclusive atmosphere." " YOUR RESPONSES MUST BE BRIEF, PLEASE LIMIT YOUR RESPONSES TO 3-4 SENTENCES." ) } """ def add_user(user_id: str) -> None: # Append user ID to the file users = load_gpt4_users(gpt4_users_file) if user_id not in users: with open(gpt4_users_file, 'a') as file: file.write(user_id + "\n") def remove_user(user_id: str) -> None: # Remove user ID from the file with open(gpt4_users_file, 'r+') as file: lines = file.readlines() file.seek(0) for line in lines: if line.strip() != user_id: file.write(line) file.truncate() # Load allowed GPT-4 users from a file def load_gpt4_users(filename: str) -> set: with open(filename, 'r') as file: return set(line.strip() for line in file.readlines()) def remove_distortions(message): for distorted, correct in distortions.items(): message = message.replace(distorted, correct) return message def purge_conversation_history(user_id: str): conversation_histories[user_id] = [INIT_PROMPT] def count_tokens(messages, model="gpt-3.5-turbo-0613"): """Return the number of tokens used by a list of messages.""" try: encoding = tiktoken.encoding_for_model(model) except KeyError: print("Warning: model not found. Using cl100k_base encoding.") encoding = tiktoken.get_encoding("cl100k_base") if model in { "gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k-0613", "gpt-4-0314", "gpt-4-32k-0314", "gpt-4-0613", "gpt-4-32k-0613", }: tokens_per_message = 3 tokens_per_name = 1 elif model == "gpt-3.5-turbo-0301": tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n tokens_per_name = -1 # if there's a name, the role is omitted elif "gpt-3.5-turbo" in model: print("Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613.") return count_tokens(messages, model="gpt-3.5-turbo-0613") elif "gpt-4" in model: print("Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613.") return count_tokens(messages, model="gpt-4-0613") else: raise NotImplementedError( f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""" ) num_tokens = 0 for message in messages: num_tokens += tokens_per_message for key, value in message.items(): num_tokens += len(encoding.encode(value)) if key == "name": num_tokens += tokens_per_name num_tokens += 3 # every reply is primed with <|start|>assistant<|message|> return num_tokens def word_replacement(match): word = match.group() matched_prefix = next((key for key in badwords if word.lower().startswith(key)), None) if matched_prefix: replacement = badwords[matched_prefix] # Retaining the case and suffix of the original word suffix = word[len(matched_prefix):] if word.istitle(): return replacement.capitalize() + suffix elif word.isupper(): return replacement.upper() + suffix.upper() else: return replacement + suffix return word def censor(text): pattern = re.compile(r'\b(?:' + '|'.join(re.escape(key) for key in badwords.keys()) + r')[a-z]*', re.IGNORECASE) return pattern.sub(word_replacement, text) def uncensor(text): global badwords original_badwords = badwords.copy() badwords.update(censored_words) # Temporarily update the badwords for uncensoring pattern = re.compile(r'\b(?:' + '|'.join(re.escape(key) for key in censored_words.keys()) + r')[a-z]*', re.IGNORECASE) uncensored_text = pattern.sub(word_replacement, text) badwords = original_badwords # Restore original badwords after uncensoring return uncensored_text def get_completion(prompt: str, user_id: str): print("Running completion for user", user_id) gpt4_users = load_gpt4_users(gpt4_users_file) if user_id in gpt4_users: print("User", user_id, "is a GPT-4 user") # Determine which model to use #if user_id in gpt4_users: #model_name = "gpt-4-1106-preview" # Or whatever the specific GPT-4 model name is #else: model_name = "gpt-3.5-turbo-1106" # Yep, this is needed prompt = censor(prompt) # Get the conversation history for the given user or initialize a new one conversation_history = conversation_histories.get(user_id, [INIT_PROMPT]) # Append the user's new message conversation_history.append({"role": "user", "content": prompt}) alert_user = False while count_tokens(conversation_history) > ALERT_THRESHOLD: if conversation_history[0]['role'] == "system": conversation_history.pop(1) else: conversation_history.pop(0) alert_user = True response = client.chat.completions.create(model=model_name, messages=conversation_history, temperature=1.2) assistant_response = response.choices[0].message.content conversation_history.append({"role": "assistant", "content": assistant_response}) # Save the updated conversation history back to the dictionary conversation_histories[user_id] = conversation_history #if alert_user: # assistant_response = (assistant_response) + " *ctxlimit, [1] popped, you're fucked, carry on or use !purge command*" assistant_response = uncensor(assistant_response) return remove_distortions(assistant_response)