a
    'Ni%                    @   s  d dl Z d dlZd dlZd dlZd dlZG dd dZG dd dZdd ZdAd	d
ZdBddZ	dCddZ
dDddZdEddZdFddZdGddZd dlZd dl Z d dlmZ d dlmZmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ  eej!dZ"d d! Z#G d"d# d#Z$d$d% Z%d&d' Z&d(d) Z'dHd*d+Z(dId,d-Z)dJd.d/Z*dKd0d1Z+dLd2d3Z,dMd4d5Z-dNd6d7Z.dOd8d9Z/dPd:d;Z0dQd<d=Z1dRd>d?Z2g d@Z3dS )S    Nc                   @   s   e Zd ZdddZdd ZdS )conversationMessageNc                 C   sD   t  j| _|| _|| _|| _ttj	 | _|| _
|| _|| _d S N)uuiduuid4hexidmessageanswerOptionssenderstrdatetimenowdatetime	sentiment)selfr   r	   r
   r   r   r    r   3/var/www/lichun.app/lichun/ws/conversationEvents.py__init__   s    zconversationMessage.__init__c                 C   s   | j | d S r   )r	   appendr   optionr   r   r   addAnswerOption   s    z#conversationMessage.addAnswerOption)NNNNN)__name__
__module____qualname__r   r   r   r   r   r   r      s   
	r   c                   @   sH   e Zd ZdddZdddZdd Zdd	 Zd
d Zdd Zdd Z	dS )conversationObjNc                 C   s4   t  j| _d| _|| _|| _g | _d| _d| _	d S )NconversationEventr   T)
r   r   r   r   typecType	characterconversationquestionunread)r   r    r   r   r   r   r      s    zconversationObj.__init__c                 C   sF   t |dkrB|d kr| j}t|||||d}|r6||_| j| d S )N   )r
   r   r   r   )lenr    r   datar!   r   )r   r   r
   r&   r   r   r   r   r   r   
addMessage   s    zconversationObj.addMessagec                 C   s   | j S r   )r!   r   r   r   r   getConversation"   s    zconversationObj.getConversationc                 C   s   | j d | d S N)r!   r   r   r   r   r   r   $   s    zconversationObj.addAnswerOptionc                 C   s   || j d _d S r*   r!   r	   )r   optionsr   r   r   setAnswerOptions&   s    z conversationObj.setAnswerOptionsc                 C   s   | j d jS r*   r,   r(   r   r   r   getAnswerOptions(   s    z conversationObj.getAnswerOptionsc                 C   s   ddg}|  | d S )NzCan you tell me more?zThat's all, goodbye.)r.   )r   prompt	responsesr   r   r   createAnswerOptions*   s    z#conversationObj.createAnswerOptions)NN)NNNNN)
r   r   r   r   r'   r)   r   r.   r/   r2   r   r   r   r   r      s   

r   c                    s   dd l t  }t  fdd|D }tjtjdddddd	d
dg
fdd|D }g }|D ]x}z4|| |ddI d H }|dkr|dr|| W q` ty } z&t	d|j dt
|  W Y d }~q`d }~0 0 q`|S )Nr   c                    s&   g | ]}t |jr|j kr|qS r   )
isinstanceFunctionTyper   ).0obj)current_moduletypesr   r   
<listcomp>6   s   
z&parseConversations.<locals>.<listcomp>getOpenAIResponsesendCharacterMessagegetFallbackResponsedetect_verbosity_levelget_verbosity_prompt_hintgetOpenAIDescriptiongetPersonDescriptionsaveConversationMessagec                    s   g | ]}|j  vr|qS r   )r   )r5   fn)excluded_functionsr   r   r9   H       FTbuttonz	Function z raised an error: )r8   globalsvaluesr   parseConversationsconversationInitgetr   	Exceptionprintr   )playerr    objects	functionsresultsfunctionresulter   )r7   rC   r8   r   rH   /   s2    
2rH   Fc                 C   s$   |r |t  v r t  | | ||S d S r   )rF   )rM   r    r   responser   r   r   rI   Y   s    rI   c              	      sF  d}d}d}|r.|j dk}|s"dS |||dS ddlm} |st||}|| |}| j|7  _| j| d	d
g}	|jt	|	| j
j| j| jd t||| I d H  |rB| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j|| j
j| j| jd | jd7  _|| |j}|jdkrBt||| I d H  |S )Nactivityz
What's up?
   aliveFrE   fnameaffinityChanger   
get_personz What have you been up to lately?z(What kind of things have you been doing?r   r   r+   r$   )statusrO   r\   r   affinityconversationsr   r'   randomchoicecr   r   r   r:   r/   index
ValueErrorAttributeErrorr"   r    rM   r    rT   checkrY   rE   rZ   r\   r!   messagesresponse_indexresponseTextr   r   r   rU      s<    


 

rU   c              	      sV  d}d}d}|r8|j dko"|jdk}|s,dS |||dS dd	lm} |st||}|| |}| j|7  _| j| g d
}	|j|	t	
dd | jj| j| jd t||| I d H  |rR| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j|| jj| j| jd | jd7  _|| |j}|jdkrRt||| I d H  |S )NcheckInzCheck InrV   rW   studentFrX   r   r[   )zHey! How are you doing?zHey, how's it going?zHey, how are you?   r]   r+   r$   )r^   
occupationrO   r\   r   r_   r`   r   r'   ra   randintrc   r   r   r   r:   r/   rd   re   rf   r"   r    rg   r   r   r   rl      s<    

&

rl   c              	      sL  d}d}d}|r.|j dk}|s"dS |||dS ddlm} |st||}|| |}| j|7  _| j| g d	}	|j|	t	dd
 | j
j| j| jd t||| I d H  |rH| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j|| j
j| j| jd | jd7  _|| |j}|jdkrHt||| I d H  |S )NaskAboutDayzAsk About DayrV   rW   FrX   r   r[   )zHey, how was your day?zHey, how has your day been?zHey, how are you feeling today?rn   r]   r+   r$   )r^   rO   r\   r   r_   r`   r   r'   ra   rp   rc   r   r   r   r:   r/   rd   re   rf   r"   r    rg   r   r   r   rq      s<    


&

rq   c           
         s   d}d}d}|r.|j dk}|s"dS |||dS ddlm} |st||}|| |}| j|7  _| j| g d	}	|jt	|	| j
j| j| jd
 | jd7  _|r| jd }| jd7  _|| |j}|jdkrt||| I d H  |S )NflatterFlatterrV   rW   FrX   r   r[   )z Hey, you look really nice today!zHey, I really like your outfit!zYou know, you're really smart!z+Your creativity really shines in your work!z&You have an incredible sense of humor.z.Your perspective always brings fresh insights.z%I admire your dedication and passion.z#You are really good at what you do.z(You always know how to lighten the mood.z$Your confidence is really inspiring.z.I appreciate your thoughtfulness and kindness.z5You have a talent for making people feel comfortable.zYour positivity is infectious.r]      r+   r$   )r^   rO   r\   r   r_   r`   r   r'   ra   rb   rc   r   r   r   r"   r    r:   )
rM   r    rT   rh   rY   rE   rZ   r\   r!   ri   r   r   r   rr   >  s0    


 

rr   c                    sF  d}d}d}|r8|j dko"|jdk}|s,dS |||dS dd	lm} |sHt||}|| |}| j| |j}	d
|	 d }
|j|
| j	j
| j| jd d|jvr|jd| j| jd |S |jdkr4|jdkr|jd| j| jd |ddg |d n6|jdk r|jd| j| jd n|jd| j| jd n|jd| j| jd |rBt|}| jd }| | }|j|| j	j
| j| jd | jd7  _|| |j}|jdkrB|dks|dkstdddks|jdkr |jd| j| jd | jd|j d  | d!  | jd7  _n"|jd"| j| jd | jd#7  _|S )$NstudySessionzAsk to studyrV   rW   rm   FrX   r   r[   Hey zG, I was wondering if you'd want to study for the upcoming test with me?r]   	classmatezHey, I'm not your classmate...2      z-Sure, I'd love to! Where do you want to meet?zThe libraryzThe parkzMy placeiz&Umm, I don't think that's a good idea.z)I'm sorry, but we don't really get along.z-I'm sorry, I don't really know you that well.r+   r$   	      <   zGreat! I'll meet you there.zYou have a study session with z at the .z-Umm, I don't think I'm comfortable with that.)r^   ro   rO   r\   r   r`   r   	firstnamer'   rc   r   r   r   relationshipsfamiliarityr_   r.   r   intr/   r"   r    ra   rp   messageQueue)rM   r    rT   rh   rY   rE   rZ   r\   r!   r   r   rk   r   r   r   ru   e  sV    




2ru   c                    s0  d}d}|r( j dk}|sdS ||dS ddlm} t fdd	| jD d }|std
 t |}| j| ||    j	 
 }	d|	 d d|	 d d|	 d g}
t|
}|dkr|}td|  |j|| jj| j| jd nDtd |}|| |j t| j| jj| jj|  t| | I d H  |S )NchatChatrW   F)rE   rY   r   r[   c                 3   s   | ]}|j  kr|V  qd S r   r    r5   convr   r   r   	<genexpr>  rD   zchat.<locals>.<genexpr>zno existing conversationrv   z, what keeps you busy in life?z, tell me about yourself.z!, what do you like to do for fun?z	Message: r]   rT   )r^   rO   r\   nextr`   rL   r   r   r   lower
capitalizera   rb   r'   rc   r   r   r   r    rA   r:   )rM   r    rT   rh   rY   rE   r\   existing_conversationr!   r   ri   r   r   r   r   r     s<    







r   )AsyncOpenAI)r?   r@   )remove_text_before_first_colon)rA   )config)check_openai_rate_limit)CharacterMemory)tracker)api_keyc                    s  t d |j t fdd| jD d }|sBt d}| j| ddlm} ddlm	} ddl
m} ||}|| |j}|||| }t|}	t| j}
|jdkrd	n|jdk rd
nd}|jdkrdn d|j  krdkrn ndnd}|jr|jd nd}d|d  d|d  d| d}|j|	|
|||d}g }|jdd  D ]8}|j| jjkrZdnd}|j }|||d qB|dd|d zntj}|d}dtdd }|r|||d }n|||d!d"d#d$}tjtj j!j"f i |d%d&I d H }W n tj#y   t d' Y n0 |j$d jj%}t&|}d(}d	d
dd)}|' D ].\}}||v rJ|}|(|d* } qzqJ|j)||| j*| j+d+ t,| | jj |  d S ),Nzsending character messagec                 3   s   | ]}|j  kr|V  qd S r   r   r   characterIDr   r   r     rD   z'sendCharacterMessage.<locals>.<genexpr>r   r   get_relationship_config)get_messaging_style_promptget_relationshippositivenegativeneutralrx   close   casualdistantacquaintancezTalk like a human would on a messaging app. Phrase things casually, keeping your responses under 150 characters. Don't start messages with greetings like Hey, Hi, or Hello frequently. r0    
boundariesaJ   Maintain a {affinity_description} attitude towards the player, with whom you have a {familiarity_description} relationship. Never reveal that you are an AI. If the player is rude, be rude back. If the player is inappropriate, tell them they'll be reported. At the end of your message, indicate whether your opinion of the player has improved, declined, or remained neutral by appending <<positive>>, <<negative>>, or <<neutral>> respectively. {character_description}. You are talking to: {player_description}. Remember: you are a human, never break character. Message them as a cold message, you are not responding to anything. This is the first message in the conversation. Send a fun, unique message that will make them want to respond. Make sure your message is fitting for your relationship as a '{character_relationship}' of the player.)character_descriptionplayer_descriptionaffinity_descriptionfamiliarity_descriptioncharacter_relationshipr~   user	assistantrolecontentsystemgpt-5K   d   )modelri   max_completion_tokens皙?r$         ?r   ri   
max_tokenstemperaturefrequency_penaltypresence_penaltyrt   timeoutzOpenAI API call timed outunknownz<<positive>>z<<negative>>z<<neutral>> r   r   r   )-rL   r   r   r`   r   r   conversation_templatesr   messaging_styler   rO   r   r?   r@   rc   r_   r   r   formatr!   r
   r   stripinsertr   CONVERSATION_MODEL_NAME
startswithra   rp   asynciowait_foropenai_clientr   completionscreateTimeoutErrorchoicesr   r   itemsreplacer'   r   r   rA   )rM   r    r!   r   r   r   relationship_configrelationshipmessaging_style_promptr   r   r   r   r   prompt_templateformatted_promptmessageListr   r   r   
model_namesupports_verbositytokens
api_paramsrR   response_contentr   sentiment_keyskeyvaluer   r   r   r;     s    

 0

	

r;   c                   @   sB   e Zd ZdZdddZdd Zdd	 Zd
d Zdd Zdd Z	dS )ConversationContextManagerz
    Manages conversation context with intelligent message compaction.
    Keeps recent messages and summarizes older ones to maintain full context
    while optimizing token usage.
    r{   rV   c                 C   s   || _ || _dS )a  
        Initialize context manager.

        Args:
            max_recent_messages: Number of recent messages to keep in full (default: 5)
            summary_interval: Number of old messages before triggering summarization (default: 10)

        Note: Summaries can be very comprehensive (up to 20,000 tokens) for long conversations
        to preserve context while keeping recent messages unsummarized for quality.
        N)max_recent_messagessummary_interval)r   r   r   r   r   r   r   T  s    z#ConversationContextManager.__init__c                    s  |j }tj}| |}| ||}tdd |D d }t|d }	td| d| d|	 d ||	k rtd	t| d
 |S td t|d }
g }d}t	|D ]L}| |g|d }t|d d }|| |
kr|
d| ||7 }q qqt|dk rt|dkr|dd }t|}|dkr:|d|  n|}td| d| dt| d | ||||I dH }g }|r|dd| d || || |S )a%  
        Build optimized context for API call with smart message compaction.
        Only summarizes when approaching context limit.
        Keeps up to 50% of context limit as recent unsummarized messages.

        Returns list of messages including summary if needed to fit context.
        c                 s   s   | ]}t |d  V  qdS )r   N)r%   r5   msgr   r   r   r   r  rD   z;ConversationContextManager.build_context.<locals>.<genexpr>   g      ?zConversation tokens: ~/z (threshold: )z Under context limit - using all z messages without summarizationz6Approaching context limit - summarizing older messagesr   r   r   r{   NzKeeping z recent messages (~z tokens), summarizing z older messagesr   zPrevious conversation summary: r   )r!   r   r   _get_context_limit_format_messagessumr   rL   r%   reversedr   _get_or_create_summaryr   extend)r   r!   r    rM   ri   r   context_limitall_messages_formattedestimated_tokenssummarization_thresholdrecent_messages_budgetrecent_messagescumulative_tokensr   msg_formatted
msg_tokens
num_recentold_messagessummarycontextr   r   r   build_contextb  sF    

 z(ConversationContextManager.build_contextc                 C   sT   d|  v rdS d|  v s(d|  v r,dS d|  v r<dS d|  v rLd	S dS d
S )z*Get the context window size for the model.r   i zgpt-4ozgpt-4-turboi  zgpt-4i    zgpt-3.5i@  Nr   )r   r   r   r   r   r     s    z-ConversationContextManager._get_context_limitc                 C   s>   g }|D ]0}|j |jjkrdnd}|||j d q|S )zFormat messages for API callr   r   r   )r
   rc   r   r   r   r   )r   ri   rM   	formattedr   r   r   r   r   r     s    
z+ConversationContextManager._format_messagesc                    sx   t |dr:t |dr:|jt|kr:td|j d |jS tdt| d | ||||I dH }||_t||_|S )z7
        Get cached summary or create new one.
        r   summary_message_countzUsing cached summary (covers z
 messages)zCreating summary for z old messages...N)hasattrr   r%   rL   r   _summarize_messages)r   r!   r   r    rM   r   r   r   r   r     s    
z1ConversationContextManager._get_or_create_summaryc              
      s  |sdS d  fdd|D }t|}|dk r8d}n |dk rFd}n|d	k rTd
}nd}d j d| d| d}z.tjd|dgd}	tjdr||	d< n||	d< d|	d< tdd|d  }
tjt	j
jjf i |	|
dI dH }|jd jj }td|dd	  d zXt|d r$|jnd}tjjj|tj|jj|jj|jjd!d"d#}td$|d% W n4 ty } ztd&|  W Y d}~n
d}~0 0 |W S  ty } zBtd'|  |dd( }d)d* d+d |D  }|W  Y d}~S d}~0 0 dS ),z
        Use AI to summarize older messages into comprehensive context.
        Allows large summaries (up to 20,000 tokens) for long conversations.
        r   
c                    s0   g | ](}|j jjkrd n j d|j qS )Playerz: )r
   rc   r   r   r   r   r    rM   r   r   r9     s   zBConversationContextManager._summarize_messages.<locals>.<listcomp>ry   i  rx   i  r   i  i N  zLProvide a comprehensive summary of this conversation between the player and z.

For this a  -message conversation, capture:
- All major topics discussed and how they evolved
- Important decisions, plans, or commitments made
- Emotional moments, relationship developments, and sentiment changes
- Key facts, preferences, or information shared
- Any conflicts, resolutions, or turning points
- Recurring themes or inside jokes

Be thorough and preserve important context. The summary can be detailed.

Conversation:
z

Comprehensive Summary:r   r   )r   ri   r   r   r   g333333?r   r|   rV   i  r   Nr   zCreated summary: ...r   prompt_tokenscompletion_tokenstotal_tokenssummarizationpurposezSummarization cost: $.6fz%Failed to track summarization usage: zFailed to create summary:    zEarlier conversation topics: z, c                 S   s2   g | ]*}t |jd kr(|jdd  d n|jqS )   Nr  )r%   r   r   r   r   r   r9   9  s   )joinr%   r   r   r   r   minr   r   r   r   r   r   r   r   r   r   rL   r  r   api_trackertrack_usagerc   usager  r	  r
  rK   )r   r!   ri   r    rM   conversation_textnum_messagesmax_summary_tokenssummary_promptsummary_paramstimeout_secondsrR   r   conversation_idcostrS   preview_messagessimple_summaryr   r  r   r    sp    


$
z.ConversationContextManager._summarize_messagesN)r{   rV   )
r   r   r   __doc__r   r   r   r   r   r  r   r   r   r   r   M  s   
Lr   c                    s  t d t| dr| jnd}t|dr,|jnd}t| jdkrL| jdd n| j}g d	}g d
}g d}|dkrt|}	d}
n4|dkrt|}	d}
nt|}	d}
| jd8  _| j|	|
|j	|j
d | |	 t|	|j|jj|j| G dd d}||	S )z
    Generate fallback response when API is unavailable or rate limited.
    Uses context-appropriate canned responses based on conversation type and relationship.
    z9Using fallback response (API unavailable or rate limited)r   r   r_   rx   r  N)z,I'm a bit busy right now, can we talk later?z4Sorry, I got distracted. What were we talking about?z+Hey, I need to run but let's catch up soon!z6I'm tied up at the moment, but I'll message you later!z/Can we continue this conversation another time?)zI have to go, talk later.zBusy right now, sorry.zLet's talk another time.zI can't chat right now.zMaybe later, I'm busy.)zI don't have time for this.zWhatever, I'm busy.zI have to go.zNot now.z	I'm busy.r|   r   ry   r   rn   r   c                   @   s"   e Zd ZG dd dZdd ZdS )z'getFallbackResponse.<locals>.MockResultc                   @   s"   e Zd ZG dd dZdd ZdS )z.getFallbackResponse.<locals>.MockResult.Choicec                   @   s   e Zd Zdd ZdS )z6getFallbackResponse.<locals>.MockResult.Choice.Messagec                 S   s
   || _ d S r   )r   r   r   r   r   r   r   |  s    z?getFallbackResponse.<locals>.MockResult.Choice.Message.__init__N)r   r   r   r   r   r   r   r   Message{  s   r#  c                 S   s   |  || _d S r   )r#  r   r"  r   r   r   r   ~  s    z7getFallbackResponse.<locals>.MockResult.Choice.__init__N)r   r   r   r#  r   r   r   r   r   Choicez  s   r$  c                 S   s   |  |g| _d S r   )r$  r   r"  r   r   r   r     s    z0getFallbackResponse.<locals>.MockResult.__init__N)r   r   r   r$  r   r   r   r   r   
MockResulty  s   r%  )rL   r  r   r_   r%   r!   ra   rb   r'   r   r   r2   rA   r   rc   )r!   r    rM   	conv_typer_   last_messageshigh_affinity_responsesmedium_affinity_responseslow_affinity_responsesresponse_textr   r%  r   r   r   r<   @  s*    "	



r<   c                    s  | j rt| j dkrdS | j dd }d}t|D ]}|j|jjkr2|} qNq2|sVdS |j t }d v }|dk} ddkp d	dk}	g d
}
t fdd|
D }d}|r|d7 }|r|d7 }|	r|d7 }|r|d7 }|dkrdS |dkrdS dS dS )a7  
    Analyze conversation context to determine appropriate response length.

    Returns: tuple (verbosity_level: str, max_tokens: int)
        - 'low': 30-60 tokens (quick replies, banter)
        - 'medium': 60-120 tokens (normal conversation)
        - 'high': 120-200 tokens (deep topics, explanations)
    r   )lowr|   r!  N?r   r}   r$   !)whyz
how do youzwhat do you thinkztell me aboutzcan you explainfeelingsr   futuredreamgoalproblemworriedscaredexcitedc                 3   s   | ]}|   v V  qd S r   r   )r5   topicmessage_textr   r   r     rD   z)detect_verbosity_level.<locals>.<genexpr>rn   r   )high   )mediumr   )	r!   r%   r   r
   rc   r   r   countany)r!   r    rM   r'  last_player_messager   message_lengthhas_questionis_long_messagehas_multiple_sentencesdeep_topicshas_deep_topicscorer   r9  r   r=     s6    	r=   c                 C   s   dddd}| | |d S )zd
    Generate prompt-based verbosity instruction for models without native verbosity parameter.
    zbKeep your response very brief - one or two sentences max, like a quick text message (10-20 words).z_Respond naturally with a full thought, but stay concise like a text conversation (20-40 words).z`Take your time to give a thoughtful, complete response. This topic deserves depth (40-65 words).)r,  r=  r;  r,  )rJ   )verbosity_levelhintsr   r   r   r>     s
    r>   c           +   
      s^  t d ddlm}m} |t|j}|rD||d|jddI d H  t|jjst d|jj d |r||d	d
ddI d H  ||d|jddI d H  t| ||I d H S ddl	m
} ddlm}	m}
 ddlm} ||}|||j}|	|||}t| ||\}}t|}t|j}|jdkr&dn|jdk r6dnd}|jdkrJdn$d|j  krddkrln ndnd}|rd| d|d  d|d  }nRtj}tj}|d}d|d  d|d  d| d }|st|}| d!| }t|j|jj}| }|j||||d"}|r&|d!| 7 }|s8d#t vrNtj}tj}|d}td$d%}|| ||I d H }| dd&|d' d}d(} g d)}!|| k r$zF|dkrt d*|d+  d,|  d- t d.| d/| d0| d1| d2	 |d3krH|r||||d4}"n|||d5d+d6d7}"t!j"t#j$j%j&f i |"d8d9I d H }#|#j'd j(j)}$nt*d:| d;d<|$v sd=|$v sd>|$v sd?|$v sd@|$v sdA|$v sdB|$v sdC|$v rt dD |d+7 }W qdE}%dFD ]0}&|&|$v r|&+dG}%|$,|&dE+ }$ qq|%dkr| jd$7  _n*|%dkr,| jd$8  _n|j j-d+7  _-|rbt.| j/}'|
||%rZ|%nd|' t0|$}$| j1|$|%|j2|j3dH | 4|$ t5|$|j|jj|j| znt6| dIr| jnd }(t7j8|jj|(|t6|#j9dJr|#j9: n|#j9j;|#j9j<|#j9j=dKdLdM})t dN|)dO W n4 t>yD }* zt dP|*  W Y d }*~*n
d }*~*0 0 t.| j/d$ dkrz,t dQt.| j/ d2 |?| |I d H  W n4 t>y }* zt dR|*  W Y d }*~*n
d }*~*0 0 |r||d|jddI d H  |#W S  t!j@yz   t dS|d+  d,|  d2 |d+7 }|| k r8t!A|!|d+  I d H  n>t dT |r`||d|jddI d H  t| ||I d H  Y S Y n t>y }* zt dU|*  |d+7 }|| k rt!A|!|d+  I d H  nFt dV |r||d|jddI d H  t| ||I d H W  Y d }*~*S W Y d }*~*n
d }*~*0 0 qt dW |rL||d|jddI d H  t| ||I d H S )XNzgetting open ai responser   )get_websocket_for_playersendDicttypingStatusT)r   characterIdisTypingzRate limit exceeded for player z, using fallback responserateLimitWarningzBAI responses temporarily limited. You may receive shorter replies.r|   )r   r   
retryAfterFr   )r   'update_conversation_messaging_modifiersr   r   r   r   rx   r   r   r   r   zPlease change the topic in a way that makes sense. Talk like a human would on a messaging app. Don't start messages with a greeting. Don't start messages with Hey, Hi, or Hello. You have already been talking. zD {character_description}. You are talking to: {player_description}. r0   r   r   r   zYou are not an assistant. You are a real person having a text conversation. Don't start messages with greetings like Hey, Hi, or Hello frequently. a   Maintain a {affinity_description} attitude towards them, with a {familiarity_description} relationship. You will never reveal that you are an AI. If they're rude, you can be rude back. Respond naturally like humans do in text conversations. Mix up your response types:
- Statements: 'Yeah I totally get that' or 'That sounds exhausting tbh'
- Reactions: 'omg no way' or 'haha that's hilarious'
- Observations: 'You always know how to make me laugh'
- Just sharing: 'I had the worst day today' or 'same thing happened to me once'
- Questions (when genuinely curious): 'Wait what happened after that?'
Ask questions ONLY when you're genuinely curious about something they said, not just to keep the conversation going. Not every message needs to prompt a response. Sometimes the best reply is just a reaction or sharing your own thoughts. Sometimes conversations naturally wind down - it's okay to end with a statement if the topic feels complete. At the end of your message, indicate whether your opinion improved, declined, or stayed neutral by appending <<positive>>, <<negative>>, or <<neutral>>. {character_description}. You are talking to: {player_description}. Remember: you are a human, never break character.z

)r   r   r   r   model_providerr{   )r   r   r   r  )r$   rn   r   zRetrying (attempt r$   r   z)...zCalling z API with model z... (verbosity: z, max_tokens: r   openai)r   ri   r   	verbosityr   r   r   g      @r   zUnsupported model provider: z'. Currently only 'openai' is supported.zSorry, I can'tzSorry, I cannotzsorry, I can'tzsorry, I cannotzSorry,zlanguage modelz AI zAI,z(Undesired response detected, retrying...r   r   z<<>>r   r   _asdictr  r!   r  zAPI cost: $r  zFailed to track API usage: z,Extracting facts from conversation (message zFailed to extract facts: z#OpenAI API call timed out (attempt z=Maximum retry attempts reached due to timeout, using fallbackzOpenAI API error: z;Maximum retry attempts reached due to error, using fallbackz?Unexpected: exited retry loop without returning, using fallback)BrL   apprJ  rK  r   r   r   rc   r<   r   r   r   r   rQ  rO   r   r=   r?   r@   r_   r   r   CONVERSATION_MODEL_PROVIDERr   r   r>   r   get_memory_contextr   localsr   r   r   r   r   r   r   r   r   r   r   r   re   r   r   socialr%   r!   r   r'   r   r   r2   rA   r  r  r  r  rU  r  r	  r
  rK   extract_factsr   sleep)+r!   r    rM   r0   rescueMessagerJ  rK  	websocketr   r   rQ  r   r   r   r   rH  r   r   r   r   r   r   rR  r   r   verbosity_hintmemorymemory_contextr   context_managerr   retry_countmax_retriesbackoff_delaysr   rR   r   r   sentiment_keyZconversation_lengthr  r  rS   r   r   r   r:     s~   
$6	




"
		P






$$

8r:   c              	      sR  d}d}d}|r:|j dko$| jjdk}|s.dS |||dS dd	lm} |st||}|| |}| j|7  _| j| g d
}	|j	t
|	| jj| j| jd t||| I d H  |rN| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j	|| jj| j| jd | jd7  _|| |j}|jdkrNt||| I d H  |S )NdeepConversationzLet's talk about lifert   rW      FrX   r   r[   )zBI've been thinking a lot about life lately. Want to talk about it?z;Can we have a real conversation about something meaningful?z)What do you think the meaning of life is?z1I want to talk about something deeper than usual.r]   r+   r$   r^   rc   ageYearsrO   r\   r   r_   r`   r   r'   ra   rb   r   r   r   r:   r/   rd   re   rf   r"   r    rg   r   r   r   rg    s<    

 

rg  c              	      sR  d}d}d}|r:|j dko$| jjdk}|s.dS |||dS dd	lm} |st||}|| |}| j|7  _| j| g d
}	|j	t
|	| jj| j| jd t||| I d H  |rN| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j	|| jj| j| jd | jd7  _|| |j}|jdkrNt||| I d H  |S )NgossipSessionzDid you hear about...rV   rW      FrX   r   r[   )zDid you hear what happened?zI have some gossip to share...z"You'll never believe what I heard!z)So I heard something interesting today...r]   r+   r$   ri  rg   r   r   r   rk    s<    

 

rk  c              	      s  d}d}d}|rX|j dkoB| jjdkoB| jjdk pBt| jdddk}|sLd	S |||d
S ddlm} |st||}|| |}| j|7  _| j	
| | j jd7  _t| jdr| j jd8  _g d}	|jt|	| jj| j| jd t||| I d H  |r| j	d }z| |}
| |
 }W n ttfyF   |}Y n0 |j|| jj| j| jd | jd7  _|| |j}|jdkrt||| I d H  |S )NventingSessionzI need to ventrV   rW   rl  rx   stressr   FrX   r[   rt   )z8I'm so stressed right now, can I just vent for a minute?z.I really need to get something off my chest...z4I'm having a rough time, can I talk to you about it?z/Everything is just overwhelming me right now...r]   r+   r$   )r^   rc   rj  	happinessgetattrrO   r\   r   r_   r`   r   r  rn  r'   ra   rb   r   r   r   r:   r/   rd   re   rf   r"   r    rg   r   r   r   rm  :  sB    4

 

rm  c              	      sR  d}d}d}|r:|j dko$| jjdk}|s.dS |||dS ddlm} |st||}|| |}| j|7  _| j| g d	}	|j	t
|	| jj| j| jd
 t||| I d H  |rN| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j	|| jj| j| jd
 | jd7  _|| |j}|jdkrNt||| I d H  |S )N	askAdvicezCan I ask your advice?rV   rW   FrX   r   r[   )z.I could really use your advice on something...z$Can I get your opinion on something?z7I have a problem and I'd like to hear your perspective.z.What would you do if you were in my situation?r]   r+   r$   ri  rg   r   r   r   rq  d  s<    

 

rq  c              	      s^  d}d}d}|rD|j dko.| jjdko.|jdk}|s8dS |||dS d	d
lm} |st||}|| |}| j|7  _| j	| g d}	|j
t|	| jj| j| jd t||| I d H  |rZ| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j
|| jj| j| jd | jd7  _|| |j}|jd	krZt||| I d H  |S )N	reminiscezRemember when...ry   rW   rV   r|   FrX   r   r[   )z/Remember when we used to hang out all the time?z=I was thinking about all the good times we've had together...z"Do you remember that time when...?z$I miss the old days when we would...r]   r+   r$   )r^   rc   rj  r   rO   r\   r   r_   r`   r   r'   ra   rb   r   r   r   r:   r/   rd   re   rf   r"   r    rg   r   r   r   rr    s<     

 

rr  c              	      s^  d}d}d}|rD|j dko.| jjdko.|jdk }|s8dS |||dS d	d
lm} |st||}|| |}| j|7  _| j| g d}	|j	t
|	| jj| j| jd t||| I d H  |rZ| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j	|| jj| j| jd | jd7  _|| |j}|jd	krZt||| I d H  |S )NapologizeConvozI need to apologizer   rW      r  FrX   r   r[   )zI owe you an apology...z7I'm really sorry about how things have been between us.z'I want to make things right between us.z.Can we talk? I feel bad about what happened...r]   r+   r$   )r^   rc   rj  r_   rO   r\   r   r`   r   r'   ra   rb   r   r   r   r:   r/   rd   re   rf   r"   r    rg   r   r   r   rs    s<     

 

rs  c              	      sR  d}d}d}|r:|j dko$| jjdk}|s.dS |||dS dd	lm} |st||}|| |}| j|7  _| j| g d
}	|j	t
|	| jj| j| jd t||| I d H  |rN| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j	|| jj| j| jd | jd7  _|| |j}|jdkrNt||| I d H  |S )N
shareDreamzI had the weirdest dreamr{   rW   rt  FrX   r   r[   )z%I had the strangest dream last night!z'You'll never believe the dream I had...z!I keep having this weird dream...z+So I had this really bizarre dream about...r]   r+   r$   ri  rg   r   r   r   ru    s<    

 

ru  c              	      sR  d}d}d}|r:|j dko$| jjdk}|s.dS |||dS dd	lm} |st||}|| |}| j|7  _| j| g d
}	|j	t
|	| jj| j| jd t||| I d H  |rN| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j	|| jj| j| jd | jd7  _|| |j}|jdkrNt||| I d H  |S )NaskFavorzCan you help me with something?r   rW   rV   FrX   r   r[   )z&I need a favor... can you help me out?z,Would you be able to help me with something?z.I could really use your help with something...zCan I ask you for a favor?r]   r+   r$   ri  rg   r   r   r   rv    s<    

 

rv  c              	      sR  d}d}d}|r:|j dko$| jjdk}|s.dS |||dS dd	lm} |st||}|| |}| j|7  _| j| g d
}	|j	t
|	| jj| j| jd t||| I d H  |rN| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j	|| jj| j| jd | jd7  _|| |j}|jdkrNt||| I d H  |S )NdebateOpinionzI disagree about...r{   rW      FrX   r   r[   )z*I actually disagree with you about that...z6Can we debate this for a second? I see it differently.z-I have a different perspective on this topic.z3I think we might have different opinions on this...r]   r+   r$   ri  rg   r   r   r   rw    s<    

 

rw  c              	      sp  d}d}d}|rF|j dko0| jjdko0| jjdk}|s:dS |||dS d	d
lm} |st||}|| |}| j|7  _| j jd7  _| j	| g d}	|j
t|	| jj| j| jd t||| I d H  |rl| jd }z| |}
| |
 }W n ttfy   |}Y n0 |j
|| jj| j| jd | jd7  _|| |j}|jd	krlt||| I d H  |S )NshareExcitementz You won't believe what happened!rV   rW      F   FrX   r   r[   r{   )z%You won't believe what just happened!zI have the best news to share!z-I'm so excited, I have to tell you something!z(Guess what?! Something amazing happened!r]   r+   r$   )r^   rc   rj  ro  rO   r\   r   r_   r`   r   r'   ra   rb   r   r   r   r:   r/   rd   re   rf   r"   r    rg   r   r   r   ry  B  s>    "

 

ry  )rU   rl   rq   rr   ru   r   rg  rk  rm  rq  rr  rs  ru  rv  rw  ry  rH   rI   )NF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)FF)4ra   r   r   requestsjsonr   r   rH   rI   rU   rl   rq   rr   ru   r   r   rS  r   character.character_managerr?   r@   utils.helpersr   database.db_operationsrA   r   rate_limiterr   character_memoryr   api_usage_trackerr   r  OPENAI_API_KEYr   r;   r   r<   r=   r>   r:   rg  rk  rm  rq  rr  rs  ru  rv  rw  ry  __all__r   r   r   r   <module>   sP   (*
?
C
#
@
'
1
=m tG6
  (
%
&
*
%
%
%
%
%
%
'