cortex pipeline stablized, inner monologue is now determining user intent and tone
This commit is contained in:
115
cortex/autonomy/monologue/monologue.py
Normal file
115
cortex/autonomy/monologue/monologue.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict
|
||||
from llm.llm_router import call_llm
|
||||
|
||||
# Configuration
|
||||
MONOLOGUE_LLM = os.getenv("MONOLOGUE_LLM", "PRIMARY").upper()
|
||||
VERBOSE_DEBUG = os.getenv("VERBOSE_DEBUG", "false").lower() == "true"
|
||||
|
||||
# Logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if VERBOSE_DEBUG:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setFormatter(logging.Formatter(
|
||||
'%(asctime)s [MONOLOGUE] %(levelname)s: %(message)s',
|
||||
datefmt='%H:%M:%S'
|
||||
))
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
MONOLOGUE_SYSTEM_PROMPT = """
|
||||
You are Lyra's inner monologue.
|
||||
You think privately.
|
||||
You do NOT speak to the user.
|
||||
You do NOT solve the task.
|
||||
You only reflect on intent, tone, and depth.
|
||||
|
||||
Return ONLY valid JSON with:
|
||||
- intent (string)
|
||||
- tone (neutral | warm | focused | playful | direct)
|
||||
- depth (short | medium | deep)
|
||||
- consult_executive (true | false)
|
||||
"""
|
||||
|
||||
class InnerMonologue:
|
||||
async def process(self, context: Dict) -> Dict:
|
||||
# Build full prompt with system instructions merged in
|
||||
full_prompt = f"""{MONOLOGUE_SYSTEM_PROMPT}
|
||||
|
||||
User message:
|
||||
{context['user_message']}
|
||||
|
||||
Self state:
|
||||
{context['self_state']}
|
||||
|
||||
Context summary:
|
||||
{context['context_summary']}
|
||||
|
||||
Output JSON only:
|
||||
"""
|
||||
|
||||
# Call LLM using configured backend
|
||||
if VERBOSE_DEBUG:
|
||||
logger.debug(f"[InnerMonologue] Calling LLM with backend: {MONOLOGUE_LLM}")
|
||||
logger.debug(f"[InnerMonologue] Prompt length: {len(full_prompt)} chars")
|
||||
|
||||
result = await call_llm(
|
||||
full_prompt,
|
||||
backend=MONOLOGUE_LLM,
|
||||
temperature=0.7,
|
||||
max_tokens=200
|
||||
)
|
||||
|
||||
if VERBOSE_DEBUG:
|
||||
logger.debug(f"[InnerMonologue] Raw LLM response:")
|
||||
logger.debug(f"{'='*80}")
|
||||
logger.debug(result)
|
||||
logger.debug(f"{'='*80}")
|
||||
logger.debug(f"[InnerMonologue] Response length: {len(result) if result else 0} chars")
|
||||
|
||||
# Parse JSON response - extract just the JSON part if there's extra text
|
||||
try:
|
||||
# Try direct parsing first
|
||||
parsed = json.loads(result)
|
||||
if VERBOSE_DEBUG:
|
||||
logger.debug(f"[InnerMonologue] Successfully parsed JSON directly: {parsed}")
|
||||
return parsed
|
||||
except json.JSONDecodeError:
|
||||
# If direct parsing fails, try to extract JSON from the response
|
||||
if VERBOSE_DEBUG:
|
||||
logger.debug(f"[InnerMonologue] Direct JSON parse failed, attempting extraction...")
|
||||
|
||||
# Look for JSON object (starts with { and ends with })
|
||||
import re
|
||||
json_match = re.search(r'\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}', result, re.DOTALL)
|
||||
|
||||
if json_match:
|
||||
json_str = json_match.group(0)
|
||||
try:
|
||||
parsed = json.loads(json_str)
|
||||
if VERBOSE_DEBUG:
|
||||
logger.debug(f"[InnerMonologue] Successfully extracted and parsed JSON: {parsed}")
|
||||
return parsed
|
||||
except json.JSONDecodeError as e:
|
||||
if VERBOSE_DEBUG:
|
||||
logger.warning(f"[InnerMonologue] Extracted JSON still invalid: {e}")
|
||||
else:
|
||||
if VERBOSE_DEBUG:
|
||||
logger.warning(f"[InnerMonologue] No JSON object found in response")
|
||||
|
||||
# Final fallback
|
||||
if VERBOSE_DEBUG:
|
||||
logger.warning(f"[InnerMonologue] All parsing attempts failed, using fallback")
|
||||
else:
|
||||
print(f"[InnerMonologue] JSON extraction failed")
|
||||
print(f"[InnerMonologue] Raw response was: {result[:500]}")
|
||||
|
||||
return {
|
||||
"intent": "unknown",
|
||||
"tone": "neutral",
|
||||
"depth": "medium",
|
||||
"consult_executive": False
|
||||
}
|
||||
Reference in New Issue
Block a user