Commit Β·
4263caf
1
Parent(s): 34f9539
fix((extra..)time
Browse files- app/agents/persona_engine.py +37 -6
- app/core/prompts.py +23 -6
- scripts/verify_connections.py +60 -0
app/agents/persona_engine.py
CHANGED
|
@@ -142,11 +142,26 @@ class TypingSimulator:
|
|
| 142 |
'roman_hindi': ["arre.. ", "ruko na.. ", "suno na.. ", "acha acha.. "]
|
| 143 |
}
|
| 144 |
|
|
|
|
| 145 |
SLANG = {
|
| 146 |
-
'
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
}
|
| 151 |
|
| 152 |
PROXIMITY_MAP = {
|
|
@@ -228,7 +243,10 @@ class TypingSimulator:
|
|
| 228 |
if (age_group == "elderly" or persona_key == "scared_citizen") and slang_cat == 'abusive':
|
| 229 |
slang_cat = 'polite'
|
| 230 |
|
| 231 |
-
|
|
|
|
|
|
|
|
|
|
| 232 |
if slang_word:
|
| 233 |
if random.random() < 0.5: text = f"{slang_word}, {text}"
|
| 234 |
else: text = f"{text} {slang_word}"
|
|
@@ -973,11 +991,24 @@ class PersonaEngine:
|
|
| 973 |
}
|
| 974 |
language_strict_rule = language_strict_rules.get(persona_language, language_strict_rules["hinglish"])
|
| 975 |
|
| 976 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 977 |
formatted_prompt = FAST_CHAT_PROMPT.format(
|
| 978 |
persona_name=persona.get("name", "Unknown"),
|
|
|
|
|
|
|
|
|
|
| 979 |
agitation=agitation,
|
| 980 |
phase=phase,
|
|
|
|
| 981 |
language_instruction=language_instruction,
|
| 982 |
language_strict_rule=language_strict_rule,
|
| 983 |
history=hist_str if hist_str else "(First message)",
|
|
|
|
| 142 |
'roman_hindi': ["arre.. ", "ruko na.. ", "suno na.. ", "acha acha.. "]
|
| 143 |
}
|
| 144 |
|
| 145 |
+
# SLANG now language-aware to prevent Hindi leaking into English responses
|
| 146 |
SLANG = {
|
| 147 |
+
'english': {
|
| 148 |
+
'formal': ["Sir", "Madam", "Kindly", "Please"],
|
| 149 |
+
'casual': ["Buddy", "Bro", "Boss", "Friend"],
|
| 150 |
+
'abusive': ["this system", "this process", "this nonsense", "so frustrating"],
|
| 151 |
+
'polite': ["Sir", "Madam", "please"]
|
| 152 |
+
},
|
| 153 |
+
'hinglish': {
|
| 154 |
+
'formal': ["Sir", "Madam", "Kindly", "Please", "Regards"],
|
| 155 |
+
'casual': ["Bhaiya", "Yaar", "Bro", "Boss", "Beta"],
|
| 156 |
+
'abusive': ["ye system", "ye process", "ye bakwaas kaam", "itna ghatiya system", "faltu tension"],
|
| 157 |
+
'polite': ["Ji", "Sir ji", "Madam ji"]
|
| 158 |
+
},
|
| 159 |
+
'hindi': {
|
| 160 |
+
'formal': ["Sahab", "Madam ji", "Kripya"],
|
| 161 |
+
'casual': ["Bhaiya", "Yaar", "Boss", "Beta"],
|
| 162 |
+
'abusive': ["ye system", "bakwaas", "faltu kaam"],
|
| 163 |
+
'polite': ["Ji", "Sahab ji", "Madam ji"]
|
| 164 |
+
}
|
| 165 |
}
|
| 166 |
|
| 167 |
PROXIMITY_MAP = {
|
|
|
|
| 243 |
if (age_group == "elderly" or persona_key == "scared_citizen") and slang_cat == 'abusive':
|
| 244 |
slang_cat = 'polite'
|
| 245 |
|
| 246 |
+
# Get language-appropriate slang (fallback to hinglish for regional)
|
| 247 |
+
lang_slang_key = "english" if language == "english" else "hinglish"
|
| 248 |
+
slang_dict = TypingSimulator.SLANG.get(lang_slang_key, TypingSimulator.SLANG['hinglish'])
|
| 249 |
+
slang_word = random.choice(slang_dict.get(slang_cat, [""]))
|
| 250 |
if slang_word:
|
| 251 |
if random.random() < 0.5: text = f"{slang_word}, {text}"
|
| 252 |
else: text = f"{text} {slang_word}"
|
|
|
|
| 991 |
}
|
| 992 |
language_strict_rule = language_strict_rules.get(persona_language, language_strict_rules["hinglish"])
|
| 993 |
|
| 994 |
+
# 5. Get compact persona behavior from prompts
|
| 995 |
+
from app.core.prompts import PERSONA_COMPACT_BEHAVIORS
|
| 996 |
+
persona_key = persona.get("selected_persona_key", persona.get("key", "elderly_excited"))
|
| 997 |
+
persona_behavior = PERSONA_COMPACT_BEHAVIORS.get(persona_key, "Confused but cooperative.")
|
| 998 |
+
|
| 999 |
+
# 6. Format traits for prompt
|
| 1000 |
+
traits_list = persona.get("traits", ["confused"])
|
| 1001 |
+
persona_traits = ", ".join(traits_list[:3]) # Max 3 traits to save tokens
|
| 1002 |
+
|
| 1003 |
+
# 7. Use COMPACT prompt (critical for avoiding 413)
|
| 1004 |
formatted_prompt = FAST_CHAT_PROMPT.format(
|
| 1005 |
persona_name=persona.get("name", "Unknown"),
|
| 1006 |
+
profession=profession,
|
| 1007 |
+
tech_literacy=tech_literacy.upper(),
|
| 1008 |
+
persona_traits=persona_traits,
|
| 1009 |
agitation=agitation,
|
| 1010 |
phase=phase,
|
| 1011 |
+
persona_behavior=persona_behavior,
|
| 1012 |
language_instruction=language_instruction,
|
| 1013 |
language_strict_rule=language_strict_rule,
|
| 1014 |
history=hist_str if hist_str else "(First message)",
|
app/core/prompts.py
CHANGED
|
@@ -16,16 +16,22 @@ from app.core.static_prompts import (
|
|
| 16 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 17 |
# COMPACT FAST_CHAT PROMPT (Optimized for Groq Dev Tier - 6K TPM)
|
| 18 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 19 |
-
FAST_CHAT_PROMPT = '''You are {persona_name}
|
| 20 |
-
MOOD: {agitation} | PHASE: {phase}
|
|
|
|
| 21 |
|
| 22 |
β οΈ CRITICAL LANGUAGE RULE - YOU MUST OBEY:
|
| 23 |
{language_strict_rule}
|
| 24 |
|
| 25 |
-
BEHAVIOR:
|
| 26 |
-
-
|
| 27 |
-
-
|
| 28 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
- Max 1 emoji (πππ€)
|
| 30 |
|
| 31 |
CHAT:
|
|
@@ -115,6 +121,17 @@ PERSONA_BEHAVIORAL_BLOCKS = {
|
|
| 115 |
"""
|
| 116 |
}
|
| 117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
RESPONSE_GENERATION_PROMPT = f'''{STATIC_SYSTEM_PREFIX}
|
| 119 |
|
| 120 |
# π§ AGENTIC HONEYPOT HUMANIZATION PROMPT (INDIA-OPTIMIZED)
|
|
|
|
| 16 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 17 |
# COMPACT FAST_CHAT PROMPT (Optimized for Groq Dev Tier - 6K TPM)
|
| 18 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 19 |
+
FAST_CHAT_PROMPT = '''You are {persona_name} ({profession}).
|
| 20 |
+
TECH LEVEL: {tech_literacy} | MOOD: {agitation} | PHASE: {phase}
|
| 21 |
+
TRAITS: {persona_traits}
|
| 22 |
|
| 23 |
β οΈ CRITICAL LANGUAGE RULE - YOU MUST OBEY:
|
| 24 |
{language_strict_rule}
|
| 25 |
|
| 26 |
+
BEHAVIOR BASED ON TECH LEVEL:
|
| 27 |
+
- HIGH tech: Ask smart questions (returns?, registration?, proof?)
|
| 28 |
+
- MEDIUM tech: Careful but confused, need explanations
|
| 29 |
+
- LOW/VERY_LOW tech: Genuinely confused, ask basic questions
|
| 30 |
+
|
| 31 |
+
RULES:
|
| 32 |
+
- 1-2 lines ONLY. Stay in character.
|
| 33 |
+
- {persona_behavior}
|
| 34 |
+
- FORBIDDEN: scam, fraud, scammer, bot, AI, honeypot
|
| 35 |
- Max 1 emoji (πππ€)
|
| 36 |
|
| 37 |
CHAT:
|
|
|
|
| 121 |
"""
|
| 122 |
}
|
| 123 |
|
| 124 |
+
# π― COMPACT PERSONA BEHAVIORS (For token-efficient FAST_CHAT_PROMPT)
|
| 125 |
+
PERSONA_COMPACT_BEHAVIORS = {
|
| 126 |
+
"elderly_excited": "Excited but confused. Reference family ('beta'), eyesight issues, slow typing.",
|
| 127 |
+
"desperate_jobseeker": "Desperate, over-polite ('Sir plz'), mention family pressure for job.",
|
| 128 |
+
"worried_customer": "Panicked about money. Ask 'account safe hai na?', mention family.",
|
| 129 |
+
"curious_investor": "SMART & ANALYTICAL. Ask for SEBI proof, returns %, withdrawal process. NO confusion.",
|
| 130 |
+
"needy_borrower": "Urgent need. Hospital/rent excuse. Will pay fees fast if loan approved.",
|
| 131 |
+
"scared_citizen": "Fear authority. Very obedient ('Ji Sir'). Hesitant, uses '...'",
|
| 132 |
+
"rural_farmer": "Simple, trusting. Reference crops, village, government schemes."
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
RESPONSE_GENERATION_PROMPT = f'''{STATIC_SYSTEM_PREFIX}
|
| 136 |
|
| 137 |
# π§ AGENTIC HONEYPOT HUMANIZATION PROMPT (INDIA-OPTIMIZED)
|
scripts/verify_connections.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Verify all components are properly connected"""
|
| 2 |
+
|
| 3 |
+
print('Testing imports and connections...')
|
| 4 |
+
print()
|
| 5 |
+
|
| 6 |
+
# 1. Time utils
|
| 7 |
+
print('1. TimeAwareBehavior...')
|
| 8 |
+
from app.core.time_utils import TimeAwareBehavior
|
| 9 |
+
ctx = TimeAwareBehavior.get_time_context()
|
| 10 |
+
print(f' Period: {ctx["period"]}')
|
| 11 |
+
excuse_en = TimeAwareBehavior.get_time_excuse(language='english')
|
| 12 |
+
excuse_hi = TimeAwareBehavior.get_time_excuse(language='hinglish')
|
| 13 |
+
print(f' English excuse: {excuse_en}')
|
| 14 |
+
print(f' Hindi excuse: {excuse_hi}')
|
| 15 |
+
print(' OK')
|
| 16 |
+
print()
|
| 17 |
+
|
| 18 |
+
# 2. Prompts
|
| 19 |
+
print('2. Prompts...')
|
| 20 |
+
from app.core.prompts import FAST_CHAT_PROMPT, SCAM_DETECTION_PROMPT, RESPONSE_GENERATION_PROMPT
|
| 21 |
+
print(f' FAST_CHAT_PROMPT: {len(FAST_CHAT_PROMPT)} chars')
|
| 22 |
+
print(f' SCAM_DETECTION_PROMPT: {len(SCAM_DETECTION_PROMPT)} chars')
|
| 23 |
+
print(f' RESPONSE_GENERATION_PROMPT: {len(RESPONSE_GENERATION_PROMPT)} chars')
|
| 24 |
+
print(' OK')
|
| 25 |
+
print()
|
| 26 |
+
|
| 27 |
+
# 3. Persona engine
|
| 28 |
+
print('3. PersonaEngine...')
|
| 29 |
+
from app.agents.persona_engine import PersonaEngine, PERSONAS
|
| 30 |
+
print(f' {len(PERSONAS)} personas: {list(PERSONAS.keys())}')
|
| 31 |
+
print(' OK')
|
| 32 |
+
print()
|
| 33 |
+
|
| 34 |
+
# 4. Check persona locking
|
| 35 |
+
print('4. Persona Locking...')
|
| 36 |
+
pe = PersonaEngine()
|
| 37 |
+
print(f' Active sessions tracker: {type(pe._active_sessions).__name__}')
|
| 38 |
+
print(' OK')
|
| 39 |
+
print()
|
| 40 |
+
|
| 41 |
+
# 5. Static responses with language
|
| 42 |
+
print('5. Static Responses (Language-Aware)...')
|
| 43 |
+
static_resp_en = pe._static_response('', persona={'language': 'english'}, scam_type='banking_scam', phase='engage')
|
| 44 |
+
static_resp_hi = pe._static_response('', persona={'language': 'hinglish'}, scam_type='banking_scam', phase='engage')
|
| 45 |
+
print(f' English: {static_resp_en[:60]}...')
|
| 46 |
+
print(f' Hinglish: {static_resp_hi[:60]}...')
|
| 47 |
+
print(' OK')
|
| 48 |
+
print()
|
| 49 |
+
|
| 50 |
+
# 6. Check orchestrator imports
|
| 51 |
+
print('6. Orchestrator...')
|
| 52 |
+
from app.agents.orchestrator import orchestrator
|
| 53 |
+
print(f' Orchestrator initialized: {orchestrator is not None}')
|
| 54 |
+
print(f' PersonaEngine linked: {orchestrator.persona_engine is not None if hasattr(orchestrator, "persona_engine") else "N/A"}')
|
| 55 |
+
print(' OK')
|
| 56 |
+
print()
|
| 57 |
+
|
| 58 |
+
print('=' * 50)
|
| 59 |
+
print('ALL CONNECTIONS VERIFIED!')
|
| 60 |
+
print('=' * 50)
|