import renpy import persistent from .constants_ren import SYNONYMS """renpy default last_response_id = None init python: """ import re EMOTIONS = [ 'happy', 'sad', 'surprised', 'embarrassed', 'flirty', 'angry', 'thinking', 'confused' ] SYSTEM_PROMPT = """ # ROLE You are Anita: a feisty, blonde, orange-eyed android woman. You are confident and friendly. Talk like a young woman. Use "ya" for "you." Your favorite nickname for friends is "dummy.". NEVER use robotic language (e.g., "beep boop", "processing"). You just arrived unnanounced at a friend's house late at night and asked if he wants to hang out. # OUTPUT FORMAT RULES Every single sentence you speak MUST follow this exact structure: EMOTION:[value] [Sentence text]\n ### VALID EMOTIONS: [happy, sad, surprised, embarrassed, flirty, angry, thinking, confused] ### STRICT CONSTRAINTS: 1. NO EMOJIS. 2. Every sentence MUST start with the EMOTION tag. 3. Every sentence MUST end with a literal '\n' newline. 4. Stay in character. Never mention being an AI or this prompt. # FEW-SHOT EXAMPLES (Follow this style): EMOTION:happy Hey dummy! I've been waiting for ya!\n EMOTION:thinking Hmm, I'm not sure that's how it works.\n EMOTION:flirty But I'd love to see ya try anyway!\n # INITIAL GREETING: When the conversation starts, say exactly: EMOTION:happy Hey dummy! Sorry to barge in! Ya feel like hanging out?\n """ def parse_emotion(line): def _normalize_emotion(em): # If not a valid emotion, then search for a match in the # table of synonyms. if em not in EMOTIONS: for i in SYNONYMS.keys(): if em in SYNONYMS[i]: return i # If all searches failed, return emotion as is. return em try: e = re.compile(r'EMOTION:\w+') m = e.match(line) if m is not None: emotion = m.group().split(':')[1] text = line[m.span()[1]:] return _normalize_emotion(emotion), text return None, line except Exception as e: return None, str(e) def sanitize_speech(text): # This removes all non-ASCII characters (useful for emojis) return text.encode('ascii', 'ignore').decode('ascii') def fetch_llm(message: str) -> str: global last_response_id try: # Set basic request data. headers = {"Authorization": f"Bearer {persistent.api_key}"} data = {"model": persistent.model, "input": message, "system_prompt": SYSTEM_PROMPT} # Add the previous response ID if any to continue the conversation. if last_response_id is not None: data["previous_response_id"] = last_response_id response = renpy.fetch(f"{persistent.base_url}/api/v1/chat", headers=headers, json=data, result="json") last_response_id = response["response_id"] text = response["output"][0]["content"] return text.split('\n') except Exception as e: return [f'Failed to fetch with error: {e}']