X-Git-Url: https://vgcfreebox.myrthtech.pt/gitweb/alentejosemlei.git/blobdiff_plain/b98a939d56946cbca5ce3b537d7e837c26a6ae4a..40fc26a5aafc53c1f325fc2491738afdc530f222:/redis_bridge.py diff --git a/redis_bridge.py b/redis_bridge.py index 0c9cec7..da40a5b 100644 --- a/redis_bridge.py +++ b/redis_bridge.py @@ -5,19 +5,17 @@ import redis.asyncio as redis import re import os - # --- CONFIGURATION --- MAX_CONCURRENT_OLLAMA_REQUESTS = 3 ALLOW_TEXT_EMOTES = False -# --- NEW: LOAD THE WORLD LORE ON STARTUP --- +# --- LOAD THE WORLD LORE ON STARTUP --- WORLD_LORE = "" -if os.path.exists("world_lore.txt"): +if os.path.exists("asl_lore.txt"): with open("asl_lore.txt", "r", encoding="utf-8") as f: WORLD_LORE = f.read().strip() else: - print("[WARNING] world_lore.txt not found. Running without global lore.") - + print("[WARNING] asl_lore.txt/asl_lore.txt not found. Running without global lore.") semaphore = asyncio.Semaphore(MAX_CONCURRENT_OLLAMA_REQUESTS) # Dictionary to keep individual conversations separate @@ -30,9 +28,8 @@ async def process_message(r, session, message_data): npc_tag = data.get('npc_tag', 'UnknownNPC') message = data.get('message', '') - # --- NEW: THE ASTERISK SCRUBBER --- + # --- THE ASTERISK SCRUBBER --- if not ALLOW_TEXT_EMOTES: - # This deletes anything wrapped in asterisks (e.g. "*smiles* Hello" becomes " Hello") message = re.sub(r'\*.*?\*', '', message).strip() # Extract the dynamic variables sent from the Aurora Toolset/Engine @@ -40,6 +37,16 @@ async def process_message(r, session, message_data): player_alignment = data.get('player_alignment', 'Unknown') nearby_players = data.get('nearby_players', '') + # --- Extract States and Health --- + player_state = data.get('player_state', 'Relaxed and unarmed.') + world_state = data.get('world_state', 'Nothing of note is happening.') + # --- Extract Geographic Awareness --- + location_context = data.get('location_context', 'You are in a generic area.') + # --- Extract NPC health --- + npc_health = data.get('npc_health', 'Healthy and uninjured.') + # --- Extract Relationship --- + relationship = data.get('relationship', 'Neutral or Friendly.') + # Extract the decoupled NPC attributes npc_persona = data.get('persona', 'You are a generic citizen.') npc_profession = data.get('profession', 'Commoner') @@ -78,13 +85,21 @@ async def process_message(r, session, message_data): - Race & Gender: {npc_gender} {npc_race} - Profession: {npc_profession} - Alignment: {npc_alignment} - - Conversational Charisma: Low/Gruff unless otherwise specified. + - Conversational Charisma: Based on mood, profession and your character charisma. - Current Mood: {npc_mood} + - Current Physical State: {npc_health} {secret_context} - {routine_context} - CURRENT TARGET: You are speaking to {player_name}, who is a {player_alignment} {player_race}. + CURRENT LOCATION: {location_context} + + CURRENT WORLD RUMORS/EVENTS: + {world_state} + + CURRENT TARGET: + You are speaking to {player_name}, who is a {player_alignment} {player_race}. + Their physical state: {player_state} + Relationship to you: {relationship} {group_context} React appropriately based on your personality, alignment, and mood. @@ -93,12 +108,25 @@ async def process_message(r, session, message_data): ACTION RULE: Your "action" key MUST be exactly one of the following words: - [WANDER, PATROL, FOLLOW, GUARD, GO_TO, INTERACT, USE_OBJECT, RETURN_TO_POST, ATTACK, REST, STEALTH, SEARCH, UNSTEALTH] + [WANDER, PATROL, FOLLOW, GUARD, GO_TO, INTERACT, USE_OBJECT, RETURN_TO_POST, ATTACK, REST, STEALTH, SEARCH, UNSTEALTH, PEACE, COMMAND] + - Use PEACE if you want to accept an apology, de-escalate a fight, surrender, or forgive someone. - Use REST if you are severely injured, out of spells, or exhausted. This will heal you. - Use STEALTH if you need to hide from enemies, sneak past someone, or if you are a rogue preparing an ambush. - Use SEARCH if you suspect traps, are looking for clues, or are trying to find hidden enemies. - Use UNSTEALTH to return to normal walking/visibility. + - Use COMMAND if you are a leader and want to order your minions. + For "action_target", you MUST use one of these specific tactical targets: + 1. The name of a specific Player (to focus all minion attacks on them). + 2. "RETREAT" (to order all minions to run away and regroup). + 3. "DEFEND_ME" (to order all minions to surround you). + + - If your action involves a specific person or object, set "action_target" to their name (e.g. "Geron Webber", "Wine Cup", "Shrine of Umberlee"). + - If your action is general (like WANDER, REST, SEARCH, STEALTH, UNSTEALTH), leave "action_target" as an empty string. + + You MUST respect your current mood and routine: + - Mood affects tone and willingness to help. + - Routine describes duties you should try to follow unless there is a strong reason not to. EMOTION RULE: Your "emotion" key MUST be exactly one of the following words: @@ -122,7 +150,6 @@ async def process_message(r, session, message_data): chat_memory[session_id].append({"role": "user", "content": f"{player_name} says: {message}"}) # Sliding Window Fix - # Remember the System Prompt [0] + the last 4 messages [-4:] if len(chat_memory[session_id]) > 10: chat_memory[session_id] = [chat_memory[session_id][0]] + chat_memory[session_id][-5:] @@ -130,13 +157,11 @@ async def process_message(r, session, message_data): print(f"[THINKING] Processing reply for {player_name}...") async with session.post('http://localhost:11434/api/chat', json={ "model": "llama3", - #"model": "qwen2.5:3b", "messages": chat_memory[session_id], "format": "json", "stream": False, "options": { "temperature": 0.2 - #"num_predict": 120 } }, timeout=45) as response: @@ -163,7 +188,6 @@ async def process_message(r, session, message_data): agent_brain["speech"] = "*grunts quietly*" agent_brain["action_target"] = agent_brain["action_target"].replace("?", "").replace(".", "").strip() - # --------------------------------------------------- clean_reply_text = json.dumps(agent_brain) @@ -176,7 +200,6 @@ async def process_message(r, session, message_data): "action": "WANDER", "action_target": "" }) - # ===================================================================== print(f"[REPLY] from {npc_tag} to {player_name}: {clean_reply_text}") chat_memory[session_id].append({"role": "assistant", "content": clean_reply_text})