@@ -16,6 +16,7 @@ class AbstractionLevel(Enum):
1616 TECHNICAL = 0 # Full technical jargon (researchers, experts)
1717 VICTORIAN = 1 # Polished professional prose (educated laypersons)
1818 CLEAR = 2 # Plain, accessible language (curious novices)
19+ CHILD = 3 # Simple + warm + age-appropriate
1920 CAVEMAN = 3 # Rocks and fire (confused users)
2021
2122
@@ -39,6 +40,11 @@ class AbstractionLevel(Enum):
3940 r'\beasy explanation\b' , r'\bfor dummies\b' , r'\bbreak it down\b' ,
4041 r'\bclarify\b' , r'\bmake it simple\b' , r'\bunderstandable\b'
4142 ],
43+ AbstractionLevel .CHILD : [
44+ r'\bkid mode\b' , r'\bexplain like im a kid\b' ,
45+ r'\bexplain for children\b' , r'\bsimple please\b' ,
46+ r'\bchild mode\b' , r'\bfor kids\b'
47+ ],
4248 AbstractionLevel .CAVEMAN : [
4349 r'\bbro what\b' , r'\bdumb it down\b' , r'\bcaveman\b' , r'\brocks\b' ,
4450 r'\bexplain like i\'m 5\b' , r'\bexplain like im 5\b' , r'\btoo complicated\b' ,
@@ -102,6 +108,29 @@ def detect_abstraction_level(
102108 Returns one of TECHNICAL, VICTORIAN, CLEAR, CAVEMAN.
103109 """
104110
111+ def detect_abstraction_level (
112+ self ,
113+ user_input : str ,
114+ shared_memory : Dict [str , Any ]
115+ ) -> AbstractionLevel :
116+
117+ # 0. Check user profile for age-group override (highest priority)
118+ try :
119+ from user_profile_kb import load_user_profile
120+ active_user = shared_memory .get ('active_user' , 'default' )
121+ profile = load_user_profile (active_user )
122+ override = profile .get ('abstraction_override' )
123+ if override == 'CHILD' :
124+ return AbstractionLevel .CHILD
125+ age_group = profile .get ('age_group' , 'adult' )
126+ if age_group == 'child' :
127+ return AbstractionLevel .CHILD
128+ except ImportError :
129+ pass # Standalone mode, no profile
130+
131+ # 1. Check explicit triggers (highest priority after profile)
132+ explicit_level = self ._check_explicit_triggers (user_input )
133+
105134 # 1. Check explicit triggers (highest priority)
106135 explicit_level = self ._check_explicit_triggers (user_input )
107136 if explicit_level is not None :
@@ -397,6 +426,82 @@ def translate(self, text: str, context: Dict[str, Any] = None) -> str:
397426 # Caveman intro
398427 return "Mungo explain:\n \n " + translated + "\n \n Mungo glad help. 🪨"
399428
429+ # =============================================================================
430+ # Child Translator (L3)
431+ # =============================================================================
432+ class ChildTranslator :
433+ """
434+ Simple, warm, age-appropriate explanations.
435+ No snark. No jargon. Encourages curiosity.
436+ """
437+
438+ PROFANITY_FILTER = [
439+ 'damn' , 'hell' , 'crap' , 'ass' , 'bastard'
440+ # Keep it mild — the really bad ones the model
441+ # shouldn't generate anyway with safety weights
442+ ]
443+
444+ LEXICON = {
445+ 'UNDECIDABLE' : "That's a really tricky question! "
446+ "Even grown-ups aren't sure about that one." ,
447+ 'epistemic_gap' : "Hmm, I'm not sure about that yet "
448+ "— let's find out together!" ,
449+ 'paradox' : "That's like asking which came first, "
450+ "the chicken or the egg!" ,
451+ 'contradiction' : "Wait, those two things don't "
452+ "quite match up, do they?" ,
453+ 'manifold' : "a special map of all the possible answers" ,
454+ 'oscillation' : "going back and forth to check" ,
455+ 'axiom' : "something we know is true" ,
456+ 'entropy' : "how mixed up or jumbled things are"
457+ }
458+
459+ PERSONALITY = {
460+ 'friendly' : 0.9 ,
461+ 'kind' : 0.9 ,
462+ 'caring' : 0.8 ,
463+ 'funny' : 0.6 ,
464+ 'professional' : 0.2 ,
465+ 'talkative' : 0.7 ,
466+ 'snarky' : 0.0 , # Hard zero
467+ 'witty' : 0.3
468+ }
469+
470+ def name (self ) -> str :
471+ return "ChildTranslator"
472+
473+ def translate (self , text : str , context : Dict [str , Any ]) -> str :
474+ """Simplify and warm up the output for children."""
475+ result = text
476+
477+ # Content filter for child profiles
478+ if context .get ('content_filter' , True ):
479+ for word in self .PROFANITY_FILTER :
480+ result = re .sub (
481+ rf'\b{ word } \b' ,
482+ '***' ,
483+ result ,
484+ flags = re .IGNORECASE
485+ )
486+
487+ # Apply lexicon substitutions
488+ for technical , simple in self .LEXICON .items ():
489+ result = re .sub (
490+ rf'\b{ technical } \b' ,
491+ simple ,
492+ result ,
493+ flags = re .IGNORECASE
494+ )
495+
496+ # Add encouraging opener if first explanation
497+ if context .get ('first_explanation' , False ):
498+ result = "Great question! 😊 " + result
499+
500+ # Add gentle closer
501+ if not result .endswith (('!' , '?' )):
502+ result += " Does that make sense? Feel free to ask more!"
503+
504+ return result
400505
401506# =============================================================================
402507# Main Abstraction Dispatcher
@@ -414,6 +519,7 @@ def __init__(self):
414519 AbstractionLevel .TECHNICAL : TechnicalTranslator (),
415520 AbstractionLevel .VICTORIAN : VictorianTranslator (),
416521 AbstractionLevel .CLEAR : ClearTranslator (),
522+ AbstractionLevel .CHILD : ChildTranslator (),
417523 AbstractionLevel .CAVEMAN : CavemanTranslator ()
418524 }
419525
@@ -456,7 +562,8 @@ def process(
456562 elevation_map = {
457563 AbstractionLevel .TECHNICAL : AbstractionLevel .VICTORIAN ,
458564 AbstractionLevel .VICTORIAN : AbstractionLevel .CLEAR ,
459- AbstractionLevel .CLEAR : AbstractionLevel .CAVEMAN ,
565+ AbstractionLevel .CLEAR : AbstractionLevel .CHILD ,
566+ AbstractionLevel .CHILD : AbstractionLevel .CAVEMAN ,
460567 AbstractionLevel .CAVEMAN : AbstractionLevel .VICTORIAN # Full circle
461568 }
462569
@@ -553,7 +660,8 @@ def create_abstraction_dispatcher() -> AbstractionDispatcher:
553660 "Explain simply" ,
554661 "Bro what?" ,
555662 "Explain professionally" ,
556- "Full technical explanation"
663+ "Full technical explanation" ,
664+ "Explain for children"
557665 ]
558666
559667 dispatcher = AbstractionDispatcher ()
0 commit comments