Ai-Chat-Friend / AI chat Friend.py
AI chat Friend.py
Raw
"""
The point of this program is to run a chat bot which simulates being a close friend. I thought the idea was very hysterical and ironic which is why I choose it, is it dystopian, one hundred percent.
Due to the heavy reliance on chatgpt no matter how fast or slow the overall language was the speed will remain relatively constant due to the reliance on chatgpt, which makes python
an easy choice. The program is in its infancy and there are many very interesting ways I want to take it. The first problem to fix is the speed, while it still feels like you are talking
to a robot sometimes that problem will be fixed just by fiddling around with the prompts and number analysis the speed is a foundational issue and almost entirely comes from an over reliance on chatGPT.
The first part to cut is where is determines the polarity of each emotion, by instead of having chatgpt determine the msg it is done inside of the program through an algorithm. There are so many ways
I want to take this project whether I go further into the dystopian topics or create something of a customer service machine only time will tell, but I feel the posibilities are endless.

TLDR: This is basically a high level neral net configuration but with the parameters being the users emotional state, all to simulate a friend.

AI Chat Friend
By Hutchison Bray
11/16/2024
"""

import openai


class User:
    global emotionLvlNG,emotionLvlNL,emotionLvlS
    
    #The " " key is here to be used for progam logic
    emotionLvlNG = {"anger":0.0,"sad":0.0,"happy":0.0,"fear":0.0," ":0.0}#Numericalg
    emotionLvlS = {"anger":"not","sad":"not","happy": "not", "fear":"not"," ":""}#As Strings

    #psuedo-local (bascally the emotional state of an individual message)
    emotionLvlNL = {"anger":0.0,"sad":0.0,"happy":0.0,"fear":0.0," ":0.0}#Numerical

    def __init__(self):
        #should ask for api key but just put mine in for sake of time
        openai.api_key = "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"


    def greatestEmotion(self,emotionLvlDic): #determines which emotional level is currently the highest (not used)
        #(doesnt take into account if there is a greatest but the emotions are arranged in such a way that anger is first anylised and will always take priority)
        
        greatestV = -1 #greatest Value (-1 so every value is >)
        greatest = ""
        
        for key in emotionLvlDic:#this is constant time
            if (emotionLvlDic[key] > greatestV):
                greatest=key
                greatestV = emotionLvlDic[key]
        
        return greatest
    
    def updateGlobalEmotionState(self):#gets more accurate as the program goes on
        for emotion in emotionLvlNG:
            emotionLvlNG[emotion] = (emotionLvlNG[emotion] + emotionLvlNL[emotion]) * 0.5

    def setStringState(self): #updates the string value based off the calculated numerical value of emotional state for chat gpt to interpret (could give it numerical values and it would be faster but I found this gives better results)
        
        self.updateGlobalEmotionState()

        for key in emotionLvlNG:#this is constant time (quite a large one but still)
            emotionValue = emotionLvlNG[key]
            
            if(emotionValue <= 0.15):
                emotionLvlS[key] = "not"
                continue

            if(emotionValue <= 0.33):
                emotionLvlS[key] = "kinda"
                continue

            if(emotionValue <= 0.50):
                emotionLvlS[key] = "is"
                continue

            if(emotionValue <= 0.65):
                emotionLvlS[key] = "pretty"
                continue

            if(emotionValue <= 0.80):
                emotionLvlS[key] = "very"
                continue
        return emotionLvlS
    
    def determineEmotionValue(self,message): #determines the decimal representation
    #for the sake of speed this function needs to be taken from relying on chatgpt to being able based off the word usage to determine the emotional state of the message by itself
    #orignially I planned on doing this by find studies on specific words that are used in specific emotonal states, and I did in fact find some but they were all like 30$ so I went with the slow way of relying on chatgpt

        for emotion in emotionLvlNL: #in theory this is constant time but I think it is linear(or something around this dont think its exponental) relating to message size
            evalMSG = "can you evaluate the following messages level of " + emotion + "and only output a decimal between 0-1 as representation; " + message
            message = [{"role": "user", "content": evalMSG}]
            chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=message)
            emotionLvlNL[emotion] = float(chat.choices[0].message.content)

        return  emotionLvlNL
    
    def determineEmotionalSpike(self): #determins if there is a large spike in emotions in a specific message compared to the state in which the preson was in before
        for emotion in emotionLvlNL:
            if((emotionLvlNL[emotion] - emotionLvlNG[emotion]) >= 0.5): #if the local is 0.5 higher than the global there is a spike
                return {"bool": True,"emotion":emotion}
        return {"bool":False}
    
    def updateEmotionalState():#this is run at the end of everycode (this may be not nessacary)
        for emotion in emotionLvlNG:
            emotionLvlNG[emotion] -= 0.1 #so that if you dont exhibit a specific emotion for a while it slowly forgets 
            if emotionLvlNG[emotion] > 1.0: #this should never run
                emotionLvlNG[emotion] = 1.0

    

def newConversation():
    UserInfo = User()
    viewableMsgs = []#the messages (user and Ai) that the user will see

    while(True):
        msgList = [] #this is esentally a hidden message chain that is forgotten ever cycle

        msg = input("Enter Your Message(q to quit): ")
        
        if (msg.strip() == 'q'): break #kills program
        UserInfo.determineEmotionValue(msg)
        UserInfo.setStringState()
            
        temp = UserInfo.determineEmotionalSpike()
        emotionSpike = temp["bool"]
        
        while(True):
            
            if(emotionSpike):
                
                msg = ""
                greatestEmotion = temp["emotion"]
                
                if (greatestEmotion == "sad"):
                    msg = "make a joke about the situation trying to chear your friend up"
                
                if (greatestEmotion == "happy"):
                    msg = "make a joke about the situation do it a little playfully teasing your friend"

                if(greatestEmotion == "anger"):
                    msg = "can you agree with you friend about what they are angry about, so long as it isn't an extremest idea" #This line needs to be retooled as there are a lot of ways I can see this being abused
                
                if(greatestEmotion == "anger"):
                    msg = "either calm your friend down or tell them they have nothing to worry about or tell them that this is serious and that they should seek help depending on the severity of what they are scared of both in magnitude and subject material."

                msgList.append({"role": "user", "content": msg})
                chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=msgList)
                reply = chat.choices[0].message.content
                msgList.append({"role": "assistant", "content": reply})

                msgList.append({"role": "user", "content": "can you say it with less cringe"})
                chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=msgList)
                reply = chat.choices[0].message.content
                msgList.append({"role": "assistant", "content": reply})

                msgList.append({"role": "user", "content": "stop trying to act cool"})
                chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=msgList)
                reply = chat.choices[0].message.content
                msgList.append({"role": "assistant", "content": reply})

                viewableMsgs.append(msgList[len(msgList)-1])

                viewableMsgs.append({"role": "user", "content": "Do you think the previous entry you came up with fits the emotional state of your friend and theme of this conversation so far respond with only true or false"})
                chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=viewableMsgs)
                reply = chat.choices[0].message.content
                msgList.append({"role": "assistant", "content": reply})
                
                
                if(bool(msgList[len(msgList)-1]["content"].upper)):#see if chat gpt belives that the message belongs in the chain of messages or if it should try again (do you belive that belongs in the conversation veiwable Messages)
                    viewableMsgs.pop(len(viewableMsgs)-1)
                    print("Response: " + viewableMsgs[len(viewableMsgs)-1]["content"])
                    break
                
                viewableMsgs.pop(len(viewableMsgs)-1)
                viewableMsgs.pop(len(viewableMsgs)-1)
    
                continue

            #creates the first message that contains the emotional state
            msgHOLD = "keeping in mind that your friend emotional state is currently "
            
            for emotion in UserInfo.emotionLvlS:
                msgHold += UserInfo.emotionLvlS[emotion] + " " +emotion + " "

            msgHold += "can you respond as someone who cares about the individual would: " + msg
            
            msgList.append({"role": "user", "content": msgHOLD})
            chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=msgList)
            reply = chat.choices[0].message.content
            msgList.append({"role": "assistant", "content": reply})

            msgList.append({"role": "user", "content": "can you respond not as a romantic partner but as a friend instead"})
            chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=msgList)
            reply = chat.choices[0].message.content
            msgList.append({"role": "assistant", "content": reply})

            msgList.append({"role": "user", "content": "can you say it with less cringe"})
            chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=msgList)
            reply = chat.choices[0].message.content
            msgList.append({"role": "assistant", "content": reply})

            msgList.append({"role": "user", "content": "stop trying to act cool"})
            chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=msgList)
            reply = chat.choices[0].message.content
            msgList.append({"role": "assistant", "content": reply})

            viewableMsgs.append(msgList[len(msgList)-1])

            viewableMsgs.append({"role": "user", "content": "Do you think the previous entry you came up with fits the emotional state of your friend and theme of this conversation so far respond with only true or false"})
            chat = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=viewableMsgs)
            reply = chat.choices[0].message.content
            msgList.append({"role": "assistant", "content": reply})
            
            if(bool(msgList[len(msgList)-1]["content"].upper)):#see if chat gpt belives that the message belongs in the chain of messages or if it should try again (do you belive that belongs in the conversation veiwable Messages)
                viewableMsgs.pop(len(viewableMsgs)-1)
                print("Response: " + viewableMsgs[len(viewableMsgs)-1]["content"])
                break
            
            viewableMsgs.pop(len(viewableMsgs)-1)
            viewableMsgs.pop(len(viewableMsgs)-1)

newConversation()

if (__name__ == "__main__"):
    newConversation()