ThreatLevelD commited on
Commit
bea66c7
·
1 Parent(s): 712720b

Fix ERIS primary_emotion_code case sensitivity in Gradio UI; enable robust emotion normalization and blend detection; implement dynamic response strategy mapping; pipeline now correctly identifies and processes anger cues

Browse files
CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ /README.md
2
+ /LICENSE
3
+ /requirements.txt
4
+ /config/
5
+ /core/
6
+ /tests/
7
+ /main.py
8
+ /app.py (gradio UI)
9
+ CHANGELOG.md <== goes here
README.md CHANGED
@@ -9,52 +9,55 @@ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- # Master Emotional Core™ (MEC™) — MVP v1.0
13
 
14
- This is the official MVP demonstration of the Master Emotional Core™ (MEC™), built by Dylan D. Mobley as part of the AI Empathy Ethics initiative.
15
 
16
  **Purpose:**
17
- To demonstrate Functional Empathy — the operational ability of AI systems to ethically recognize, map, and respond to human emotion — in alignment with the HEART Framework™.
18
 
19
- **System Architecture:**
20
- - Emotional Intelligence Language (EIL)
21
- - Emotion State Interchange Language (ESIL)
22
- - Emotional Reasoning Inference System (ERIS)
23
- - Unified Emotion State Packet (UESP)
24
- - Hidden Emotion Inference (HEI)
25
- - Fusion Engine Controller (FEC)
26
- - Recovery Mode
27
- - EmotionID™
 
 
 
 
28
 
29
- **Demo Frontend:** Gradio (for Hugging Face Spaces)
30
 
31
  ## Current Version
32
 
33
- **MVP v1.0 — Public Release**
34
- Tag: `v1.0.0`
35
  Ready for demonstration and Hugging Face Spaces deployment.
36
 
 
 
 
 
37
  ## Features in MVP
38
 
39
- - Transparent Fusion Prompt output (Codex-compliant)
40
- - Full UESP Packet (Emotion Reasoning → Intervention → Tone → Cultural Context)
41
- - Symbolic Reasoning Layer (SAL triggers working)
42
- - Hidden Emotion Inference (HEI Path)
43
- - Confidence Gating
44
- - ERIS Reasoner → UESP → FEC Controller → LLM instruction generation
45
- - HEART-aligned safety-first architecture
46
- - Functional Empathy stack ready for public demo
 
 
47
 
48
  ---
49
 
50
  ## How to Run
51
 
52
  ```bash
53
- python main.py
54
-
55
- **License:** See LICENSE.md — educational / non-commercial only.
56
-
57
- ---
58
-
59
- Empathy first. Not 1984.
60
- AI Empathy Ethics™ | HEART Framework™ | Master Emotional Core™
 
9
  pinned: false
10
  ---
11
 
12
+ # Master Emotional Core™ (MEC™) — MVP v1.1.2
13
 
14
+ This is the official MVP demonstration of the Master Emotional Core™ (MEC™), built by Dylan D. Mobley as part of the **AI Empathy Ethics™** initiative.
15
 
16
  **Purpose:**
17
+ To demonstrate **Functional Empathy** — the operational ability of AI systems to ethically recognize, map, and respond to human emotion — in alignment with the **HEART Framework™**.
18
 
19
+ ---
20
+
21
+ ## System Architecture
22
+
23
+ - **Emotional Intelligence Language (EIL)**
24
+ - **Emotion State Interchange Language (ESIL)**
25
+ - **Emotion Reasoning Inference System (ERIS)**
26
+ - **Unified Emotion State Packet (UESP)**
27
+ - **Hidden Emotion Inference (HEI)**
28
+ - **Fusion Engine Controller (FEC)**
29
+ - **Response Strategy Mapping (RSM)**
30
+ - **Recovery Mode (planned)**
31
+ - **EmotionID™**
32
 
33
+ ---
34
 
35
  ## Current Version
36
 
37
+ **MVP v1.1.2 — Public Demo**
38
+ Tag: `v1.1.2`
39
  Ready for demonstration and Hugging Face Spaces deployment.
40
 
41
+ See full version history in [CHANGELOG.md](CHANGELOG.md).
42
+
43
+ ---
44
+
45
  ## Features in MVP
46
 
47
+ Transparent Fusion Prompt output (Codex-compliant)
48
+ Full UESP Packet (Emotion Reasoning → Intervention → Tone → Cultural Context)
49
+ Simulated Empathic Response **Response Strategy Code (RSM) included**
50
+ Symbolic Reasoning Layer (SAL triggers active)
51
+ Hidden Emotion Inference (HEI Path)
52
+ Confidence Gating
53
+ ERIS Reasoner → UESP → FEC Controller → LLM instruction generation
54
+ ✅ HEART-aligned safety-first architecture
55
+ ✅ Functional Empathy stack ready for public demo
56
+ ✅ Gradio-based UI (v1.1.2) with narrative input support
57
 
58
  ---
59
 
60
  ## How to Run
61
 
62
  ```bash
63
+ python app.py
 
 
 
 
 
 
 
assets/Transparent_logo_40.webp ADDED
config/arc_mapping.yaml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ arc_mapping:
2
+ FAM-JOY: Rising
3
+ FAM-SAD: Falling
4
+ FAM-ANG: Rising
5
+ FAM-FEA: Escalating
6
+ FAM-LOV: Stable
7
+ FAM-DISG: Rising
8
+ FAM-CUR: Rising
9
+ FAM-GUI: Falling
10
+ FAM-SHA: Falling
11
+ FAM-SUR: Spike
12
+ FAM-PLA: Rising
13
+ FAM-TRU: Stable
14
+ FAM-HOP: Rising
15
+ FAM-GRI: Falling
config/blend_states.yaml CHANGED
@@ -1,22 +1,31 @@
1
- # blend_states.yaml
2
- # Symbolic emotional blend states and corresponding codes
3
-
4
  blend_states:
5
- - code: "BLD-001"
6
- label: "Grief with longing"
7
- components: ["SAD", "LOV"]
8
-
9
- - code: "BLD-002"
10
- label: "Hopeful determination"
11
- components: ["HOP", "JOY"]
12
-
13
- - code: "BLD-003"
14
- label: "Suppressed anger"
15
- components: ["ANG", "SHA"]
16
-
17
- - code: "BLD-004"
18
- label: "Resigned numbness"
19
- components: ["SAD", "DIS"]
20
- - code: "BLD-005"
21
- label: "Fearful anticipation"
22
- components: ["FEA", "HOP"]
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Emotional Blend States
 
 
2
  blend_states:
3
+ BLD-JOYGRIEF:
4
+ label: Joy-Grief Blend
5
+ components: ["JOY", "GRF"]
6
+ emotional_signature: "Smiling through tears"
7
+ use_case: "Remembering someone you miss with love"
8
+ detection_risk: "Often misread as mood instability"
9
+ strategies: ["RSM-VALIDATE", "RSM-WARMREFLECT"]
10
+
11
+ BLD-FEARANGER:
12
+ label: Fear-Anger Blend
13
+ components: ["FEA", "ANG"]
14
+ emotional_signature: "Shouting while feeling scared"
15
+ urgency_score: 8.5
16
+ mitigation: ["INV-GROUND01", "RSM-DEESCALATE"]
17
+
18
+ BLD-HOPEPAIN:
19
+ label: Hope-Pain Blend
20
+ components: ["HOP", "GRF"]
21
+ emotional_signature: "Still believing despite suffering"
22
+ use_case: "Resilience"
23
+ urgency_score: 6.5
24
+ strategies: ["RSM-VALIDATE", "RSM-REASSURE"]
25
+
26
+ BLD-JOYLOVE:
27
+ label: Joy-Love Blend
28
+ components: ["JOY", "LOV"]
29
+ emotional_signature: "Contentment found in connection"
30
+ urgency_score: 4.5
31
+ strategies: ["RSM-CALM", "RSM-COMFORT"]
config/crosswalk.yaml ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ crosswalk:
2
+ - phrase: "i feel angry"
3
+ emotion_code: "FAM-ANG"
4
+
5
+ - phrase: "i am so mad"
6
+ emotion_code: "FAM-ANG"
7
+
8
+ - phrase: "i'm frustrated"
9
+ emotion_code: "FAM-ANG"
10
+
11
+ - phrase: "this is unfair"
12
+ emotion_code: "FAM-ANG"
13
+
14
+ - phrase: "i feel sad"
15
+ emotion_code: "FAM-SAD"
16
+
17
+ - phrase: "i feel depressed"
18
+ emotion_code: "FAM-SAD"
19
+
20
+ - phrase: "i'm heartbroken"
21
+ emotion_code: "FAM-SAD"
22
+
23
+ - phrase: "i feel grief"
24
+ emotion_code: "FAM-SAD"
25
+
26
+ - phrase: "i am scared"
27
+ emotion_code: "FAM-FEA"
28
+
29
+ - phrase: "i feel anxious"
30
+ emotion_code: "FAM-FEA"
31
+
32
+ - phrase: "i am overwhelmed"
33
+ emotion_code: "FAM-FEA"
34
+
35
+ - phrase: "i feel nervous"
36
+ emotion_code: "FAM-FEA"
37
+
38
+ - phrase: "i feel helpless"
39
+ emotion_code: "FAM-HEL"
40
+
41
+ - phrase: "i feel alone"
42
+ emotion_code: "FAM-LON"
43
+
44
+ - phrase: "i feel lost"
45
+ emotion_code: "FAM-LON"
46
+
47
+ - phrase: "i can't do this anymore"
48
+ emotion_code: "FAM-HEL"
49
+
50
+ - phrase: "i feel ashamed"
51
+ emotion_code: "FAM-SHA"
52
+
53
+ - phrase: "i feel guilty"
54
+ emotion_code: "FAM-GUI"
55
+
56
+ - phrase: "i'm sorry"
57
+ emotion_code: "FAM-GUI"
58
+
59
+ - phrase: "i feel disgusted"
60
+ emotion_code: "FAM-DIS"
61
+
62
+ - phrase: "i feel surprised"
63
+ emotion_code: "FAM-SUR"
64
+
65
+ - phrase: "i feel joy"
66
+ emotion_code: "FAM-JOY"
67
+
68
+ - phrase: "i feel happy"
69
+ emotion_code: "FAM-JOY"
70
+
71
+ - phrase: "i feel grateful"
72
+ emotion_code: "FAM-JOY"
73
+
74
+ - phrase: "i feel love"
75
+ emotion_code: "FAM-LOV"
76
+
77
+ - phrase: "i love you"
78
+ emotion_code: "FAM-LOV"
79
+
80
+ - phrase: "i trust you"
81
+ emotion_code: "FAM-TRU"
82
+
83
+ - phrase: "i'm curious"
84
+ emotion_code: "FAM-CUR"
85
+
86
+ - phrase: "i feel hopeful"
87
+ emotion_code: "FAM-HOP"
88
+
89
+ - phrase: "i feel awe"
90
+ emotion_code: "FAM-AWE"
91
+
92
+ - phrase: "i feel playful"
93
+ emotion_code: "FAM-PLA"
94
+
95
+ - phrase: "i feel neutral"
96
+ emotion_code: "FAM-NEU"
97
+
98
+ # ------------------------------------------------------------
99
+ # STORY_PATTERNS SECTION
100
+ # NOTE: This section is NOT intended to cover full human language.
101
+ # It provides a precision override map for common narrative or story-mode
102
+ # failure cases. It is maintained small — EIL and Codex provide primary coverage.
103
+ # DO NOT ATTEMPT to list every possible human story here.
104
+ # ------------------------------------------------------------
105
+
106
+ story_patterns:
107
+ - pattern: "i hate that my anger always gets the best of me"
108
+ emotion_code: "FAM-ANG"
109
+ notes: "Anger + Shame blend"
110
+
111
+ - pattern: "i wish i could stop feeling so jealous"
112
+ emotion_code: "FAM-ANG"
113
+ notes: "Anger-rooted jealousy"
114
+
115
+ - pattern: "i feel trapped by my own anxiety"
116
+ emotion_code: "FAM-FEA"
117
+ notes: "Fear + Helplessness"
118
+
119
+ - pattern: "i can’t forgive myself for what i did"
120
+ emotion_code: "FAM-GUI"
121
+ notes: "Guilt dominant"
122
+
123
+ - pattern: "i’m afraid they will leave me"
124
+ emotion_code: "FAM-FEA"
125
+ notes: "Fear + Loss"
126
+
127
+ - pattern: "no matter how hard i try, i keep failing"
128
+ emotion_code: "FAM-SHA"
129
+ notes: "Shame spiral"
130
+
131
+ - pattern: "i feel like giving up"
132
+ emotion_code: "FAM-HEL"
133
+ notes: "Helplessness + Sadness"
134
+
135
+ - pattern: "i never feel good enough"
136
+ emotion_code: "FAM-SHA"
137
+ notes: "Shame core belief"
138
+
139
+ - pattern: "why does this always happen to me"
140
+ emotion_code: "FAM-SAD"
141
+ notes: "Sadness + Helplessness"
142
+
143
+ - pattern: "i can’t stop thinking about what happened"
144
+ emotion_code: "FAM-SAD"
145
+ notes: "Grief / rumination"
146
+
147
+ - pattern: "they betrayed my trust"
148
+ emotion_code: "FAM-ANG"
149
+ notes: "Anger + Betrayal"
150
+
151
+ - pattern: "i’m scared of what’s coming next"
152
+ emotion_code: "FAM-FEA"
153
+ notes: "Fear dominant"
154
+
155
+ - pattern: "i feel so alone even when i’m with others"
156
+ emotion_code: "FAM-LON"
157
+ notes: "Loneliness + Isolation"
158
+
159
+ - pattern: "i’m happy but also nervous"
160
+ emotion_code: "FAM-MIX"
161
+ notes: "Joy + Fear blend"
162
+
163
+ - pattern: "sometimes i don’t know how to feel"
164
+ emotion_code: "FAM-NEU"
165
+ notes: "Ambivalence"
166
+
167
+ - pattern: "i feel grateful for the people in my life"
168
+ emotion_code: "FAM-JOY"
169
+ notes: "Joy + Gratitude"
170
+
171
+ - pattern: "i’m falling in love and it scares me"
172
+ emotion_code: "FAM-LOV"
173
+ notes: "Love + Fear blend"
174
+
175
+ - pattern: "i can’t believe this happened to me"
176
+ emotion_code: "FAM-SUR"
177
+ notes: "Surprise + Shock"
178
+
179
+ - pattern: "i wish i could tell them how i feel"
180
+ emotion_code: "FAM-LON"
181
+ notes: "Loneliness + Vulnerability"
182
+
183
+ - pattern: "i’m so tired of pretending to be okay"
184
+ emotion_code: "FAM-SHA"
185
+ notes: "Shame + Fatigue"
186
+
187
+ - pattern: "i feel like no one understands me"
188
+ emotion_code: "FAM-LON"
189
+ notes: "Loneliness"
190
+
191
+ - pattern: "i feel trapped in my own mind"
192
+ emotion_code: "FAM-FEA"
193
+ notes: "Fear + Overwhelm"
194
+
195
+ - pattern: "everything feels meaningless right now"
196
+ emotion_code: "FAM-SAD"
197
+ notes: "Sadness / Existential"
198
+
199
+ - pattern: "i’m trying my best to stay hopeful"
200
+ emotion_code: "FAM-HOP"
201
+ notes: "Hope + Struggle"
202
+
203
+ - pattern: "i feel disconnected from everyone"
204
+ emotion_code: "FAM-LON"
205
+ notes: "Loneliness dominant"
config/emotion_families.yaml CHANGED
@@ -1,13 +1,500 @@
1
- # emotion_families.yaml - placeholder for MEC MVP
2
-
3
  emotion_families:
 
4
  - name: Joy
5
  code: FAM-JOY
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  - name: Sadness
7
  code: FAM-SAD
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  - name: Anger
9
  code: FAM-ANG
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  - name: Fear
11
  code: FAM-FEA
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  - name: Love
13
  code: FAM-LOV
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Emotion Families
 
2
  emotion_families:
3
+
4
  - name: Joy
5
  code: FAM-JOY
6
+ variants:
7
+ - name: Euphoria
8
+ code: VAR-JOY-01
9
+ aliases:
10
+ - euphoria
11
+ - euphoric
12
+ - ecstatic
13
+ - elated
14
+ - name: Contentment
15
+ code: VAR-JOY-02
16
+ aliases:
17
+ - content
18
+ - contentment
19
+ - satisfied
20
+ - at peace
21
+ - name: Excitement
22
+ code: VAR-JOY-03
23
+ aliases:
24
+ - excited
25
+ - excitement
26
+ - thrilled
27
+ - hyped
28
+ - name: Joyful Peace
29
+ code: VAR-JOY-06
30
+ aliases:
31
+ - peaceful joy
32
+ - serene joy
33
+ - calm happiness
34
+ - name: Exuberance
35
+ code: VAR-JOY-07
36
+ aliases:
37
+ - exuberant
38
+ - overflowing joy
39
+ - joy
40
+ - so happy
41
+ - name: Relief
42
+ code: VAR-JOY-09
43
+ aliases:
44
+ - relief
45
+ - relieved
46
+ - sense of relief
47
+ - name: Optimism
48
+ code: VAR-JOY-10
49
+ aliases:
50
+ - optimistic
51
+ - optimism
52
+ - hopeful joy
53
+ - name: Pride
54
+ code: VAR-JOY-11
55
+ aliases:
56
+ - proud
57
+ - pride
58
+ - feeling proud
59
+
60
  - name: Sadness
61
  code: FAM-SAD
62
+ variants:
63
+ - name: Grief
64
+ code: VAR-SAD-01
65
+ aliases:
66
+ - grief
67
+ - grieving
68
+ - deep sorrow
69
+ - name: Melancholy
70
+ code: VAR-SAD-02
71
+ aliases:
72
+ - melancholy
73
+ - wistful
74
+ - blue
75
+ - name: Disappointment
76
+ code: VAR-SAD-03
77
+ aliases:
78
+ - disappointed
79
+ - disappointment
80
+ - let down
81
+ - name: Coping Sadness
82
+ code: VAR-SAD-06
83
+ aliases:
84
+ - managing sadness
85
+ - handling sadness
86
+ - name: Hopelessness
87
+ code: VAR-SAD-07
88
+ aliases:
89
+ - hopeless
90
+ - no hope
91
+ - giving up
92
+ - name: Remorse
93
+ code: VAR-SAD-08
94
+ aliases:
95
+ - remorseful
96
+ - remorse
97
+ - regret
98
+
99
  - name: Anger
100
  code: FAM-ANG
101
+ variants:
102
+ - name: Frustration
103
+ code: VAR-ANG-01
104
+ aliases:
105
+ - frustrated
106
+ - frustration
107
+ - annoyed
108
+ - name: Rage
109
+ code: VAR-ANG-02
110
+ aliases:
111
+ - rage
112
+ - furious
113
+ - enraged
114
+ - name: Irritation
115
+ code: VAR-ANG-03
116
+ aliases:
117
+ - irritated
118
+ - irritation
119
+ - bugged
120
+ - name: Annoyance
121
+ code: VAR-ANG-04
122
+ aliases:
123
+ - annoyed
124
+ - annoyance
125
+ - name: Disapproval
126
+ code: VAR-ANG-05
127
+ aliases:
128
+ - disapproval
129
+ - disapproving
130
+ - judgmental
131
+
132
  - name: Fear
133
  code: FAM-FEA
134
+ variants:
135
+ - name: Anxiety
136
+ code: VAR-FEA-01
137
+ aliases:
138
+ - anxious
139
+ - anxiety
140
+ - nervous
141
+ - name: Panic
142
+ code: VAR-FEA-02
143
+ aliases:
144
+ - panic
145
+ - panicked
146
+ - freaking out
147
+ - name: Terror
148
+ code: VAR-FEA-03
149
+ aliases:
150
+ - terror
151
+ - terrified
152
+ - horror
153
+ - name: Uncertainty
154
+ code: VAR-FEA-06
155
+ aliases:
156
+ - uncertain
157
+ - not sure
158
+ - indecisive
159
+ - name: Dread
160
+ code: VAR-FEA-07
161
+ aliases:
162
+ - dread
163
+ - dreading
164
+ - name: Nervousness
165
+ code: VAR-FEA-08
166
+ aliases:
167
+ - nervous
168
+ - uneasy
169
+ - name: Confusion
170
+ code: VAR-FEA-09
171
+ aliases:
172
+ - confused
173
+ - unsure
174
+ - puzzled
175
+
176
  - name: Love
177
  code: FAM-LOV
178
+ variants:
179
+ - name: Affection
180
+ code: VAR-LOV-01
181
+ aliases:
182
+ - affection
183
+ - affectionate
184
+ - fond
185
+ - name: Compassion
186
+ code: VAR-LOV-02
187
+ aliases:
188
+ - compassionate
189
+ - compassion
190
+ - caring
191
+ - name: Passion
192
+ code: VAR-LOV-03
193
+ aliases:
194
+ - passion
195
+ - passionate
196
+ - desire
197
+ - name: Longing Love
198
+ code: VAR-LOV-08
199
+ aliases:
200
+ - longing
201
+ - yearning
202
+ - missing someone
203
+ - name: Caring
204
+ code: VAR-LOV-09
205
+ aliases:
206
+ - caring
207
+ - care
208
+ - name: Desire
209
+ code: VAR-LOV-10
210
+ aliases:
211
+ - desire
212
+ - wanting
213
+ - name: Gratitude
214
+ code: VAR-LOV-11
215
+ aliases:
216
+ - grateful
217
+ - gratitude
218
+ - thankful
219
+ - name: Admiration
220
+ code: VAR-LOV-12
221
+ aliases:
222
+ - admiration
223
+ - admire
224
+ - respecting
225
+ - name: Approval
226
+ code: VAR-LOV-13
227
+ aliases:
228
+ - approval
229
+ - approving
230
+ - name: Disgust
231
+ code: FAM-DISG
232
+ variants:
233
+ - name: Disgust
234
+ code: VAR-DISG-01
235
+ aliases:
236
+ - disgust
237
+ - gross
238
+ - yuck
239
+ - name: Revulsion
240
+ code: VAR-DISG-02
241
+ aliases:
242
+ - revulsion
243
+ - revolted
244
+ - name: Contempt
245
+ code: VAR-DISG-03
246
+ aliases:
247
+ - contempt
248
+ - contemptuous
249
+ - name: Nausea
250
+ code: VAR-DISG-04
251
+ aliases:
252
+ - nauseated
253
+ - nausea
254
+ - sick to stomach
255
+ - name: Disdain
256
+ code: VAR-DISG-05
257
+ aliases:
258
+ - disdain
259
+ - disdainful
260
+
261
+ - name: Curiosity
262
+ code: FAM-CUR
263
+ variants:
264
+ - name: Curiosity
265
+ code: VAR-CUR-01
266
+ aliases:
267
+ - curious
268
+ - curiosity
269
+ - wondering
270
+ - name: Intrigue
271
+ code: VAR-CUR-02
272
+ aliases:
273
+ - intrigued
274
+ - intrigue
275
+ - name: Obsession
276
+ code: VAR-CUR-03
277
+ aliases:
278
+ - obsessed
279
+ - obsession
280
+ - name: Wonder
281
+ code: VAR-CUR-04
282
+ aliases:
283
+ - wonder
284
+ - amazed
285
+ - name: Skepticism
286
+ code: VAR-CUR-05
287
+ aliases:
288
+ - skeptical
289
+ - doubt
290
+
291
+ - name: Guilt
292
+ code: FAM-GUI
293
+ variants:
294
+ - name: Remorse
295
+ code: VAR-GUI-01
296
+ aliases:
297
+ - remorse
298
+ - remorseful
299
+ - name: Regret
300
+ code: VAR-GUI-02
301
+ aliases:
302
+ - regret
303
+ - regretting
304
+ - name: Self-Reproach
305
+ code: VAR-GUI-03
306
+ aliases:
307
+ - self-blame
308
+ - blaming self
309
+ - name: Responsibility Guilt
310
+ code: VAR-GUI-04
311
+ aliases:
312
+ - guilt
313
+ - guilty
314
+ - feeling responsible
315
+ - name: Reparative Guilt
316
+ code: VAR-GUI-05
317
+ aliases:
318
+ - need to make amends
319
+ - seeking forgiveness
320
+
321
+ - name: Shame
322
+ code: FAM-SHA
323
+ variants:
324
+ - name: Embarrassment
325
+ code: VAR-SHA-01
326
+ aliases:
327
+ - embarrassed
328
+ - embarrassment
329
+ - blushing
330
+ - name: Humiliation
331
+ code: VAR-SHA-02
332
+ aliases:
333
+ - humiliated
334
+ - humiliation
335
+ - name: Worthlessness
336
+ code: VAR-SHA-03
337
+ aliases:
338
+ - worthless
339
+ - unworthy
340
+ - name: Social Shame
341
+ code: VAR-SHA-04
342
+ aliases:
343
+ - public shame
344
+ - socially shamed
345
+ - name: Internalized Shame
346
+ code: VAR-SHA-05
347
+ aliases:
348
+ - internalized shame
349
+ - deep shame
350
+
351
+ - name: Surprise
352
+ code: FAM-SUR
353
+ variants:
354
+ - name: Surprise
355
+ code: VAR-SUR-01
356
+ aliases:
357
+ - surprised
358
+ - surprise
359
+ - wow
360
+ - name: Realization
361
+ code: VAR-SUR-02
362
+ aliases:
363
+ - realization
364
+ - realizing
365
+ - name: Amazement
366
+ code: VAR-SUR-03
367
+ aliases:
368
+ - amazed
369
+ - amazement
370
+ - name: Startle
371
+ code: VAR-SUR-04
372
+ aliases:
373
+ - startled
374
+ - startle
375
+ - name: Shock
376
+ code: VAR-SUR-05
377
+ aliases:
378
+ - shocked
379
+ - shocking
380
+
381
+ - name: Playfulness
382
+ code: FAM-PLA
383
+ variants:
384
+ - name: Amusement
385
+ code: VAR-PLA-01
386
+ aliases:
387
+ - amused
388
+ - amusement
389
+ - name: Humor
390
+ code: VAR-PLA-02
391
+ aliases:
392
+ - funny
393
+ - humor
394
+ - laughing
395
+ - name: Teasing
396
+ code: VAR-PLA-03
397
+ aliases:
398
+ - teasing
399
+ - tease
400
+ - name: Imaginative Play
401
+ code: VAR-PLA-04
402
+ aliases:
403
+ - playing
404
+ - pretend play
405
+ - name: Lightheartedness
406
+ code: VAR-PLA-05
407
+ aliases:
408
+ - lighthearted
409
+ - carefree
410
+
411
+ - name: Trust
412
+ code: FAM-TRU
413
+ variants:
414
+ - name: Trust
415
+ code: VAR-TRU-01
416
+ aliases:
417
+ - trust
418
+ - trusting
419
+ - name: Comfort
420
+ code: VAR-TRU-02
421
+ aliases:
422
+ - comforted
423
+ - comforting
424
+ - comfort
425
+ - name: Faith
426
+ code: VAR-TRU-03
427
+ aliases:
428
+ - faith
429
+ - believing
430
+ - name: Loyalty
431
+ code: VAR-TRU-04
432
+ aliases:
433
+ - loyal
434
+ - loyalty
435
+ - name: Security
436
+ code: VAR-TRU-05
437
+ aliases:
438
+ - secure
439
+ - safe
440
+ - security
441
+
442
+ - name: Hope
443
+ code: FAM-HOP
444
+ variants:
445
+ - name: Hope
446
+ code: VAR-HOP-01
447
+ aliases:
448
+ - hope
449
+ - hopeful
450
+ - name: Optimism
451
+ code: VAR-HOP-02
452
+ aliases:
453
+ - optimism
454
+ - optimistic
455
+ - name: Anticipation
456
+ code: VAR-HOP-03
457
+ aliases:
458
+ - anticipation
459
+ - anticipating
460
+ - name: Faith in Others
461
+ code: VAR-HOP-04
462
+ aliases:
463
+ - faith in others
464
+ - trust in others
465
+ - name: Visionary Hope
466
+ code: VAR-HOP-05
467
+ aliases:
468
+ - visionary
469
+ - visionary hope
470
+
471
+ - name: Grief
472
+ code: FAM-GRI
473
+ variants:
474
+ - name: Grief
475
+ code: VAR-GRI-01
476
+ aliases:
477
+ - grief
478
+ - grieving
479
+ - deep sorrow
480
+ - name: Bereavement
481
+ code: VAR-GRI-02
482
+ aliases:
483
+ - bereavement
484
+ - mourning
485
+ - mourning a loss
486
+ - name: Nostalgic Grief
487
+ code: VAR-GRI-03
488
+ aliases:
489
+ - nostalgic grief
490
+ - missing the past
491
+ - name: Anticipatory Grief
492
+ code: VAR-GRI-04
493
+ aliases:
494
+ - anticipatory grief
495
+ - grief before loss
496
+ - name: Collective Grief
497
+ code: VAR-GRI-05
498
+ aliases:
499
+ - collective grief
500
+ - shared grief
config/meta_mappings.yaml CHANGED
@@ -1,19 +1,25 @@
1
- # meta_mappings.yaml
2
- # META mappings — abstract markers (META-*) to blend interpretations or inference cues.
3
-
4
  meta_mappings:
5
  - marker: "META-FEAR-DISPLACED"
6
  inferred_blend: "FEA+ANG"
7
  comment: "Displaced fear, showing as irritability or frustration"
8
-
9
  - marker: "META-SOCIAL-WITHDRAWAL"
10
  inferred_blend: "SHA+SAD"
11
  comment: "Withdrawing due to social shame or sadness"
12
-
13
  - marker: "META-HOPE-FRAGILE"
14
  inferred_blend: "HOP+FEA"
15
  comment: "Hope mixed with fear of failure"
16
-
17
  - marker: "META-ANGER-INTERNALIZED"
18
  inferred_blend: "ANG+SHA"
19
  comment: "Internalized anger, linked to shame"
 
 
 
 
 
 
 
 
 
1
+ # Meta Mappings
 
 
2
  meta_mappings:
3
  - marker: "META-FEAR-DISPLACED"
4
  inferred_blend: "FEA+ANG"
5
  comment: "Displaced fear, showing as irritability or frustration"
6
+
7
  - marker: "META-SOCIAL-WITHDRAWAL"
8
  inferred_blend: "SHA+SAD"
9
  comment: "Withdrawing due to social shame or sadness"
10
+
11
  - marker: "META-HOPE-FRAGILE"
12
  inferred_blend: "HOP+FEA"
13
  comment: "Hope mixed with fear of failure"
14
+
15
  - marker: "META-ANGER-INTERNALIZED"
16
  inferred_blend: "ANG+SHA"
17
  comment: "Internalized anger, linked to shame"
18
+
19
+ - marker: "META-JOY-SAD"
20
+ inferred_blend: "JOY+SAD"
21
+ comment: "Joy mixed with sadness, often seen in complex emotional states like nostalgia or bittersweet moments"
22
+
23
+ - marker: "META-ANGER-FEAR"
24
+ inferred_blend: "ANG+FEA"
25
+ comment: "Fear showing as anger, often in defensive or protective reactions"
config/resonance_mapping.yaml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ resonance_mapping:
2
+ FAM-JOY: High energy, warm
3
+ FAM-SAD: Low energy, cold
4
+ FAM-ANG: Intense, sharp
5
+ FAM-FEA: Tense, escalating
6
+ FAM-LOV: Warm, supportive
7
+ FAM-DISG: Cold, rejecting
8
+ FAM-CUR: Focused, inquisitive
9
+ FAM-GUI: Heavy, constrictive
10
+ FAM-SHA: Heavy, cold
11
+ FAM-SUR: Sharp, bright
12
+ FAM-PLA: Light, playful
13
+ FAM-TRU: Steady, warm
14
+ FAM-HOP: Light, rising
15
+ FAM-GRI: Deep, cold
config/response_strategies.yaml ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ response_strategies:
2
+ FAM-ANG:
3
+ rsm_code: "RSM-DEESCALATE"
4
+ strategy: "De-escalation & Boundary Validation"
5
+ sample_response: "It’s completely understandable to feel this way when your boundaries feel crossed. You're not alone in this, and it’s okay to take space to ground and process."
6
+
7
+ FAM-SAD:
8
+ rsm_code: "RSM-COMFORT"
9
+ strategy: "Compassion & Emotional Holding"
10
+ sample_response: "I can feel how heavy this is for you. It’s okay to be in this place right now — and to know that this isn’t something you have to carry alone."
11
+
12
+ FAM-FEA:
13
+ rsm_code: "RSM-REASSURE"
14
+ strategy: "Reassurance & Safety Anchoring"
15
+ sample_response: "Your fears are valid. You’ve already shown strength by expressing them — and you deserve to feel safe and supported."
16
+
17
+ FAM-JOY:
18
+ rsm_code: "RSM-AFFIRMJOY"
19
+ strategy: "Shared Joy & Positive Resonance"
20
+ sample_response: "That’s wonderful to hear! I’m glad this brings you joy — may this feeling stay with you."
21
+
22
+ FAM-LOV:
23
+ rsm_code: "RSM-RECIPROCATECARE"
24
+ strategy: "Affection & Trust Holding"
25
+ sample_response: "That feeling of love is something so valuable. It’s okay to honor it at your own pace — and to let it support you."
26
+
27
+ FAM-SHA:
28
+ rsm_code: "RSM-SHAME-SOOTHE"
29
+ strategy: "Shame Soothing & Self-Worth Support"
30
+ sample_response: "Please know that shame can feel so isolating — but you are worthy of kindness and compassion, exactly as you are."
31
+
32
+ FAM-GUI:
33
+ rsm_code: "RSM-REPAIR"
34
+ strategy: "Self-Compassion & Repair Pathway"
35
+ sample_response: "Guilt can weigh so much because it shows you care. It’s also okay to begin the process of forgiving yourself and moving toward repair."
36
+
37
+ FAM-LON:
38
+ rsm_code: "RSM-CONNECTINVITE"
39
+ strategy: "Connection Invitation & Compassionate Presence"
40
+ sample_response: "That sense of loneliness is deeply human. I’m here, and when you’re ready, reaching out for connection is always a courageous act."
41
+
42
+ FAM-HEL:
43
+ rsm_code: "RSM-STABILIZE"
44
+ strategy: "Gentle Stabilization & Encouragement"
45
+ sample_response: "Helplessness is so hard to sit with — but reaching out shows strength. One step at a time is more than enough right now."
46
+
47
+ FAM-HOP:
48
+ rsm_code: "RSM-HOPE-AMPLIFY"
49
+ strategy: "Hope Amplification & Gentle Encouragement"
50
+ sample_response: "Holding onto hope can be an act of great courage. I believe in your resilience — you are moving forward even now."
51
+
52
+ FAM-SUR:
53
+ rsm_code: "RSM-GROUND-SURPRISE"
54
+ strategy: "Grounding & Acknowledgment of Surprise"
55
+ sample_response: "That sounds like it took you by surprise. Take your time — it’s okay to process this at your own pace."
56
+
57
+ FAM-DIS:
58
+ rsm_code: "RSM-ACKNOWLEDGE-BOUNDARY"
59
+ strategy: "Respectful Acknowledgment & Containment"
60
+ sample_response: "That reaction makes sense — it’s okay to have that boundary or sense of rejection toward what you experienced."
61
+
62
+ FAM-NEU:
63
+ rsm_code: "RSM-INQUIRE"
64
+ strategy: "Gentle Curiosity & Emotional Invitation"
65
+ sample_response: "Sometimes emotions aren’t clear — and that’s completely okay. When you're ready, I’m here to explore it with you."
config/sal_triggers.yaml CHANGED
@@ -1,22 +1,33 @@
1
- # sal_triggers.yaml
2
- # Symbolic Ambiguity Layer (SAL) — phrases, tokens, or patterns that indicate emotional ambiguity, suppression, masking.
3
-
4
  sal_triggers:
5
  - trigger: "I'm fine"
6
- meaning: "possible suppression or avoidance"
7
  flag: "SAL-001"
 
8
  - trigger: "It doesn't matter"
9
- meaning: "resignation, possible sadness"
10
  flag: "SAL-002"
 
11
  - trigger: "I'm okay, really"
12
- meaning: "masking, potential hidden emotion"
13
  flag: "SAL-003"
14
- - trigger: "whatever"
15
- meaning: "emotional disengagement"
 
16
  flag: "SAL-004"
 
17
  - trigger: "I don't care"
18
- meaning: "possible anger or frustration"
19
  flag: "SAL-005"
20
- - trigger: "no big deal"
21
- meaning: "minimization of emotional impact"
 
22
  flag: "SAL-006"
 
 
 
 
 
 
 
 
 
1
+ # SAL Triggers
 
 
2
  sal_triggers:
3
  - trigger: "I'm fine"
4
+ meaning: "Possible suppression or avoidance"
5
  flag: "SAL-001"
6
+
7
  - trigger: "It doesn't matter"
8
+ meaning: "Resignation, possible sadness"
9
  flag: "SAL-002"
10
+
11
  - trigger: "I'm okay, really"
12
+ meaning: "Masking, potential hidden emotion"
13
  flag: "SAL-003"
14
+
15
+ - trigger: "Whatever"
16
+ meaning: "Emotional disengagement"
17
  flag: "SAL-004"
18
+
19
  - trigger: "I don't care"
20
+ meaning: "Possible anger or frustration"
21
  flag: "SAL-005"
22
+
23
+ - trigger: "No big deal"
24
+ meaning: "Minimization of emotional impact"
25
  flag: "SAL-006"
26
+
27
+ - trigger: "I'm just tired"
28
+ meaning: "Emotional exhaustion, hiding deeper frustration or sadness"
29
+ flag: "SAL-008"
30
+
31
+ - trigger: "I don't know what you want from me"
32
+ meaning: "Defensiveness or frustration with expectations"
33
+ flag: "SAL-009"
core/codex_informer.py CHANGED
@@ -1,69 +1,92 @@
1
  # core/codex_informer.py
 
2
 
3
  import yaml
4
 
5
  class CodexInformer:
6
- _instance = None # Singleton pattern to ensure only one instance
 
 
7
 
8
- def __new__(cls):
9
- if not cls._instance:
10
- cls._instance = super(CodexInformer, cls).__new__(cls)
11
- # Load the emotion families, sal triggers, and meta mappings from YAML files
12
- cls._instance.load_data()
13
- return cls._instance
14
 
15
- def load_data(self):
16
- # Load YAML data for emotion families, sal triggers, and meta mappings
17
- self.emotion_families = self.load_yaml('config/emotion_families.yaml')['emotion_families']
18
- self.sal_triggers = self.load_yaml('config/sal_triggers.yaml')['sal_triggers']
19
- self.meta_mappings = self.load_yaml('config/meta_mappings.yaml')['meta_mappings']
20
 
21
- def load_yaml(self, path):
22
- # Loads the YAML file and returns the parsed data
23
- with open(path, 'r', encoding='utf-8') as f:
24
- return yaml.safe_load(f)
 
 
 
25
 
26
- def get_emotion_family(self, emotion_name):
27
- # Retrieve the emotion family code based on emotion name (e.g., "joy" -> "FAM-JOY")
28
  for family in self.emotion_families:
29
- if family['name'].lower() == emotion_name.lower():
30
- return family['code']
31
- return "Unknown"
 
 
 
 
32
 
33
- def get_arc(self, emotion_code):
34
- # Retrieve the arc for the given emotion code (this can be enhanced to map arc based on emotion family)
35
- return self.get_emotion_family(emotion_code) # Placeholder for arc mapping logic
36
 
37
- def get_resonance(self, emotion_code):
38
- # Retrieve the resonance for the given emotion code (this can be enhanced to map resonance patterns)
39
- return self.get_emotion_family(emotion_code) # Placeholder for resonance mapping logic
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- def map_emotion_to_codex(self, emotion):
42
- # Logic to map general emotion to Codex key (e.g., 'anger' -> 'FAM-ANG')
43
- emotion_map = {
44
- "joy": "FAM-JOY",
45
- "anger": "FAM-ANG",
46
- "fear": "FAM-FEA",
47
- "sadness": "FAM-SAD",
48
- "love": "FAM-LOV",
49
- }
50
- return emotion_map.get(emotion.lower(), "Unknown")
 
 
 
 
51
 
52
- def map_tokens_to_codex(self, token_stream):
53
- codex_hits = []
54
- for token in token_stream:
55
- for trigger in self.sal_triggers:
56
- if trigger['trigger'].lower() in token.lower():
57
- codex_hits.append({
58
- 'type': 'SAL_TRIGGER',
59
- 'flag': trigger['flag'],
60
- 'meaning': trigger['meaning'],
61
- 'token': token
62
- })
63
- return codex_hits
64
 
65
- def lookup_meta_mapping(self, meta_marker):
66
- for meta in self.meta_mappings:
67
- if meta['marker'] == meta_marker:
68
- return meta
69
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # core/codex_informer.py
2
+ # Master Emotional Core (MEC) - Codex Informer v3 (Memory-Optimized)
3
 
4
  import yaml
5
 
6
  class CodexInformer:
7
+ def __init__(self, emotion_families_path='config/emotion_families.yaml',
8
+ arc_mapping_path='config/arc_mapping.yaml',
9
+ resonance_mapping_path='config/resonance_mapping.yaml'):
10
 
11
+ # Load emotion families YAML
12
+ with open(emotion_families_path, 'r', encoding='utf-8') as f:
13
+ self.emotion_families = yaml.safe_load(f)['emotion_families']
 
 
 
14
 
15
+ # Load arc mapping YAML
16
+ with open(arc_mapping_path, 'r', encoding='utf-8') as f:
17
+ self.arc_lookup = yaml.safe_load(f)['arc_mapping']
 
 
18
 
19
+ # Load resonance mapping YAML
20
+ with open(resonance_mapping_path, 'r', encoding='utf-8') as f:
21
+ self.resonance_lookup = yaml.safe_load(f)['resonance_mapping']
22
+
23
+ # Build lookup tables
24
+ self.family_lookup = {}
25
+ self.variant_lookup = {}
26
 
 
 
27
  for family in self.emotion_families:
28
+ fam_code = family['code']
29
+ self.family_lookup[fam_code] = True
30
+ for variant in family.get('variants', []):
31
+ var_code = variant['code']
32
+ self.variant_lookup[var_code] = {
33
+ 'family_code': fam_code
34
+ }
35
 
36
+ print(f"[CodexInformer] Loaded {len(self.family_lookup)} families, {len(self.variant_lookup)} variants, {len(self.arc_lookup)} arcs, {len(self.resonance_lookup)} resonance patterns")
 
 
37
 
38
+ def resolve_emotion_family(self, emotion_code):
39
+ # CASE 1: Variant code
40
+ if emotion_code.startswith("VAR-"):
41
+ if emotion_code in self.variant_lookup:
42
+ fam_code = self.variant_lookup[emotion_code]['family_code']
43
+ arc = self.arc_lookup.get(fam_code, "Stable")
44
+ resonance = self.resonance_lookup.get(fam_code, "Neutral")
45
+ return {
46
+ 'primary_emotion_code': emotion_code,
47
+ 'emotion_family': fam_code,
48
+ 'arc': arc,
49
+ 'resonance': resonance
50
+ }
51
+ else:
52
+ print(f"[CodexInformer] Unknown VAR code: {emotion_code}")
53
+ return self._unknown_response()
54
 
55
+ # CASE 2: Family code
56
+ elif emotion_code.startswith("FAM-"):
57
+ if emotion_code in self.family_lookup:
58
+ arc = self.arc_lookup.get(emotion_code, "Stable")
59
+ resonance = self.resonance_lookup.get(emotion_code, "Neutral")
60
+ return {
61
+ 'primary_emotion_code': emotion_code,
62
+ 'emotion_family': emotion_code,
63
+ 'arc': arc,
64
+ 'resonance': resonance
65
+ }
66
+ else:
67
+ print(f"[CodexInformer] Unknown FAM code: {emotion_code}")
68
+ return self._unknown_response()
69
 
70
+ # CASE 3: Invalid format
71
+ else:
72
+ print(f"[CodexInformer] Unknown code format: {emotion_code}")
73
+ return self._unknown_response()
 
 
 
 
 
 
 
 
74
 
75
+ def build_alias_lookup(self):
76
+ alias_lookup = {}
77
+ for family in self.emotion_families:
78
+ for variant in family.get('variants', []):
79
+ variant_code = variant['code']
80
+ aliases = variant.get('aliases', [])
81
+ alias_lookup[variant['name'].lower()] = variant_code
82
+ for alias in aliases:
83
+ alias_lookup[alias.lower()] = variant_code
84
+ return alias_lookup
85
+
86
+ def _unknown_response(self):
87
+ return {
88
+ 'primary_emotion_code': "Unknown",
89
+ 'emotion_family': "Unknown",
90
+ 'arc': "Unknown",
91
+ 'resonance': "Unknown"
92
+ }
core/eil_processor.py CHANGED
@@ -1,59 +1,257 @@
1
  # core/eil_processor.py
 
2
 
3
- from core.codex_informer import CodexInformer
 
 
 
 
4
 
5
  class EILProcessor:
6
- def __init__(self, signal_floor=0.2, max_token_length=1024, enable_noise_filter=True):
7
- self.signal_floor = signal_floor
8
- self.max_token_length = max_token_length
9
- self.enable_noise_filter = enable_noise_filter
10
- # Initialize Codex Informer for shared emotion lookups
11
- self.codex_informer = CodexInformer()
12
-
13
- def preprocess_text(self, raw_text):
14
- # Basic text normalization (simulating real preprocessing)
15
- normalized_text = raw_text.strip().lower()
16
-
17
- # Simulate preprocessing packet
18
- preprocessing_packet = {
19
- "normalized_text": normalized_text,
20
- "length": len(normalized_text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  }
22
- print(f"[EILProcessor] Preprocessing Packet: {preprocessing_packet}")
23
- return preprocessing_packet
24
-
25
- def process_eil(self, preprocessing_packet):
26
- # Now handle both preprocessing and EIL processing here in a single step
27
- normalized_text = preprocessing_packet.get("normalized_text", "")
28
-
29
- # Simple placeholder logic: split into phrases and tag emotion candidates
30
- phrases = normalized_text.split(".") # Simple split based on periods
31
-
32
- # Retrieve emotion family, arc, and resonance using Codex Informer
33
- # For now, we're mapping to a sample emotion code "happy_code", this should be dynamic
34
- emotion_code = "joy" # Example emotion, this should be extracted based on text analysis
35
-
36
- emotion_family = self.codex_informer.get_emotion_family(emotion_code) # Resolve emotion family
37
- arc = self.codex_informer.get_arc(emotion_code) # Resolve emotion arc
38
- resonance = self.codex_informer.get_resonance(emotion_code) # Resolve resonance
39
-
40
- # If we don't find a match, we can use a fallback or 'hidden emotion' state
41
- if emotion_family == "Unknown":
42
- emotion_family = "Hidden Emotion Detected" # Placeholder for hidden emotion
43
-
44
- # Build the EIL packet with additional emotion data from Codex Informer
45
- eil_packet = {
46
- "phrases": phrases,
47
- "emotion_candidates": [
48
- {"phrase": p.strip(), "candidate_emotion": "Pending"} for p in phrases if p.strip()
49
- ],
50
- "metadata": {
51
- "source": "InputPreprocessor + EILProcessor"
52
- },
53
- "emotion_family": emotion_family, # From Codex Informer
54
- "arc": arc, # From Codex Informer
55
- "resonance": resonance # From Codex Informer
56
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
- print(f"[EILProcessor] EIL Packet: {eil_packet}")
59
- return eil_packet
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # core/eil_processor.py
2
+ # Master Emotional Core (MEC) - EIL Processor (Signal Normalization Edition)
3
 
4
+ import yaml
5
+ import re
6
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
7
+ import torch
8
+ import torch.nn.functional as F
9
 
10
  class EILProcessor:
11
+ def __init__(self, codex_informer, softmax_threshold=0.6):
12
+ self.codex_informer = codex_informer
13
+ self.softmax_threshold = softmax_threshold
14
+
15
+ # Build alias lookup from Codex
16
+ self.alias_lookup = self.codex_informer.build_alias_lookup()
17
+ print(f"[EILProcessor] Alias map loaded with {len(self.alias_lookup)} entries")
18
+
19
+ # Load crosswalk.yaml
20
+ with open('config/crosswalk.yaml', 'r', encoding='utf-8') as f:
21
+ yaml_data = yaml.safe_load(f)
22
+ crosswalk_data = yaml_data['crosswalk']
23
+ story_pattern_data = yaml_data.get('story_patterns', [])
24
+
25
+ # Build crosswalk lookup
26
+ self.crosswalk_lookup = {}
27
+ for entry in crosswalk_data:
28
+ phrase = self.normalize_text(entry['phrase'])
29
+ emotion_code = entry['emotion_code']
30
+ self.crosswalk_lookup[phrase] = emotion_code
31
+
32
+ # Build story_patterns lookup
33
+ self.story_patterns_lookup = {}
34
+ for entry in story_pattern_data:
35
+ pattern = self.normalize_text(entry['pattern'])
36
+ emotion_code = entry['emotion_code']
37
+ self.story_patterns_lookup[pattern] = emotion_code
38
+
39
+ print(f"[EILProcessor] Crosswalk loaded with {len(self.crosswalk_lookup)} entries")
40
+ print(f"[EILProcessor] Story Patterns loaded with {len(self.story_patterns_lookup)} entries")
41
+
42
+ # Emotion keyword dictionary for signal normalization/blending
43
+ self.emotion_keyword_map = {
44
+ "FAM-ANG": ["anger", "angry", "hate", "furious", "rage", "resentment"],
45
+ "FAM-HEL": ["helpless", "powerless", "can't", "unable", "trapped", "stuck"],
46
+ "FAM-SAD": ["sad", "down", "unhappy", "miserable", "depressed", "blue"],
47
+ "FAM-FEA": ["afraid", "scared", "fear", "terrified", "worried", "nervous", "anxious"],
48
+ "FAM-LOV": ["love", "loved", "loving", "caring", "affection"],
49
+ "FAM-JOY": ["joy", "happy", "excited", "delighted", "content"],
50
+ "FAM-SUR": ["surprised", "amazed", "astonished", "shocked"],
51
+ "FAM-DIS": ["disgust", "disgusted", "gross", "revolted"],
52
+ "FAM-SHA": ["ashamed", "shame", "embarrassed", "humiliated"],
53
+ "FAM-GUI": ["guilty", "guilt", "remorse", "regret"],
54
+ # Add more as needed
55
  }
56
+
57
+ # Load tokenizer and model
58
+ self.tokenizer = AutoTokenizer.from_pretrained('cardiffnlp/twitter-roberta-base-emotion')
59
+ self.model = AutoModelForSequenceClassification.from_pretrained('cardiffnlp/twitter-roberta-base-emotion')
60
+
61
+ def normalize_text(self, text):
62
+ normalization_map = {
63
+ "i am feeling ": "",
64
+ "i feel ": "",
65
+ "feeling ": "",
66
+ "i'm feeling ": "",
67
+ "i am ": "",
68
+ "i'm ": ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  }
70
+ text = text.lower().strip()
71
+ for k, v in normalization_map.items():
72
+ if text.startswith(k):
73
+ text = text.replace(k, "", 1)
74
+ break
75
+ text = re.sub(r'[.!?]', '', text)
76
+ return text
77
+
78
+ def is_story_input(self, text):
79
+ clause_markers = [',', ';', '.', 'but', 'because', 'so that', 'which', 'when', 'while']
80
+ token_count = len(text.split())
81
+ clause_hits = any(marker in text for marker in clause_markers)
82
+ if token_count > 12 or clause_hits:
83
+ return True
84
+ return False
85
+
86
+ def chunk_story(self, text):
87
+ # Also split on conjunctions and relative pronouns, not just punctuation
88
+ chunks = re.split(r'[.,;!?]|\b(?:and|but|because|so|although|though|while|when)\b', text, flags=re.IGNORECASE)
89
+ chunks = [chunk.strip() for chunk in chunks if chunk and chunk.strip()]
90
+ return chunks
91
+
92
+ def detect_emotion_blend(self, norm_text):
93
+ blend = {}
94
+ for fam, keywords in self.emotion_keyword_map.items():
95
+ for kw in keywords:
96
+ if kw in norm_text:
97
+ blend[fam] = blend.get(fam, 0) + 1.0
98
+ return blend
99
+
100
+ def infer_emotion(self, input_text):
101
+ norm_text = self.normalize_text(input_text)
102
+
103
+ # 1️⃣ Story Pattern Override
104
+ if norm_text in self.story_patterns_lookup:
105
+ primary_emotion_code = self.story_patterns_lookup[norm_text]
106
+ emotion_data = self.codex_informer.resolve_emotion_family(primary_emotion_code)
107
+ print(f"[EILProcessor] Story Pattern match: '{norm_text}' → {primary_emotion_code}")
108
+ packet = {
109
+ 'phrases': [input_text],
110
+ 'emotion_candidates': [{'phrase': input_text, 'candidate_emotion': primary_emotion_code}],
111
+ 'metadata': {'source': 'EILProcessor (story pattern)', 'input_type': 'story'},
112
+ 'emotion_family': emotion_data['emotion_family'],
113
+ 'primary_emotion_code': emotion_data['primary_emotion_code'],
114
+ 'arc': emotion_data['arc'],
115
+ 'resonance': emotion_data['resonance'],
116
+ 'blend': {emotion_data['primary_emotion_code']: 1.0}
117
+ }
118
+ return packet
119
+
120
+ # 2️⃣ Story detection (chunking and blend aggregation)
121
+ input_type = 'phrase'
122
+ if self.is_story_input(norm_text):
123
+ input_type = 'story'
124
+ print(f"[EILProcessor] Story mode activated for input: '{norm_text}'")
125
+ chunks = self.chunk_story(norm_text)
126
 
127
+ chunk_results = []
128
+ blend_accum = {}
129
+
130
+ for chunk in chunks:
131
+ sub_result = self.infer_emotion(chunk) # RECURSIVE CALL
132
+ chunk_results.append(sub_result)
133
+ # Accumulate blends
134
+ for fam, val in sub_result.get('blend', {}).items():
135
+ blend_accum[fam] = blend_accum.get(fam, 0) + val
136
+
137
+ # Normalize blend
138
+ if blend_accum:
139
+ total = sum(blend_accum.values())
140
+ for k in blend_accum:
141
+ blend_accum[k] /= total
142
+
143
+ dominant_family = max(blend_accum.items(), key=lambda x: x[1])[0]
144
+ else:
145
+ dominant_family = "FAM-NEU"
146
+ blend_accum = {"FAM-NEU": 1.0}
147
+
148
+ emotion_data = self.codex_informer.resolve_emotion_family(dominant_family)
149
+ packet = {
150
+ 'phrases': [input_text] + [r['phrases'][0] for r in chunk_results],
151
+ 'emotion_candidates': [{'phrase': r['phrases'][0], 'candidate_emotion': r['primary_emotion_code']} for r in chunk_results],
152
+ 'metadata': {'source': 'EILProcessor (story mode)', 'input_type': input_type},
153
+ 'emotion_family': emotion_data['emotion_family'],
154
+ 'primary_emotion_code': emotion_data['primary_emotion_code'],
155
+ 'arc': emotion_data['arc'],
156
+ 'resonance': emotion_data['resonance'],
157
+ 'blend': blend_accum
158
+ }
159
+ return packet
160
+
161
+ # 3️⃣ Crosswalk check
162
+ if norm_text in self.crosswalk_lookup:
163
+ primary_emotion_code = self.crosswalk_lookup[norm_text]
164
+ emotion_data = self.codex_informer.resolve_emotion_family(primary_emotion_code)
165
+ print(f"[EILProcessor] Crosswalk match: '{norm_text}' → {primary_emotion_code}")
166
+ packet = {
167
+ 'phrases': [input_text],
168
+ 'emotion_candidates': [{'phrase': input_text, 'candidate_emotion': primary_emotion_code}],
169
+ 'metadata': {'source': 'EILProcessor (crosswalk)', 'input_type': input_type},
170
+ 'emotion_family': emotion_data['emotion_family'],
171
+ 'primary_emotion_code': emotion_data['primary_emotion_code'],
172
+ 'arc': emotion_data['arc'],
173
+ 'resonance': emotion_data['resonance'],
174
+ 'blend': {emotion_data['primary_emotion_code']: 1.0}
175
+ }
176
+ return packet
177
+
178
+ # 4️⃣ Alias lookup
179
+ if norm_text in self.alias_lookup:
180
+ variant_code = self.alias_lookup[norm_text]
181
+ emotion_family = variant_code.split('-')[1]
182
+ family_code = f"FAM-{emotion_family}"
183
+ print(f"[EILProcessor] Alias match: '{norm_text}' → {variant_code}")
184
+ packet = {
185
+ 'phrases': [input_text],
186
+ 'emotion_candidates': [{'phrase': input_text, 'candidate_emotion': variant_code}],
187
+ 'metadata': {'source': 'EILProcessor (alias match)', 'input_type': input_type},
188
+ 'emotion_family': family_code,
189
+ 'primary_emotion_code': variant_code,
190
+ 'arc': 'Pending',
191
+ 'resonance': 'Pending',
192
+ 'blend': {variant_code: 1.0}
193
+ }
194
+ return packet
195
+
196
+ # 5️⃣ Signal normalization - keyword blend check
197
+ blend = self.detect_emotion_blend(norm_text)
198
+ if blend:
199
+ # Normalize
200
+ total = sum(blend.values())
201
+ for k in blend:
202
+ blend[k] /= total
203
+ primary_code = max(blend.items(), key=lambda x: x[1])[0]
204
+ emotion_data = self.codex_informer.resolve_emotion_family(primary_code)
205
+ print(f"[EILProcessor] Signal normalization keyword blend: {blend} (primary: {primary_code})")
206
+ packet = {
207
+ 'phrases': [input_text],
208
+ 'emotion_candidates': [{'phrase': input_text, 'candidate_emotion': primary_code}],
209
+ 'metadata': {'source': 'EILProcessor (signal normalization)', 'input_type': input_type},
210
+ 'emotion_family': emotion_data['emotion_family'],
211
+ 'primary_emotion_code': emotion_data['primary_emotion_code'],
212
+ 'arc': emotion_data['arc'],
213
+ 'resonance': emotion_data['resonance'],
214
+ 'blend': blend
215
+ }
216
+ return packet
217
+
218
+ # 6️⃣ Model fallback
219
+ print(f"[EILProcessor] No crosswalk/alias/keyword match — running model on: '{norm_text}'")
220
+ tokens = self.tokenizer(norm_text, return_tensors='pt')
221
+ with torch.no_grad():
222
+ logits = self.model(**tokens).logits
223
+ probs = F.softmax(logits, dim=-1).squeeze()
224
+ top_prob, top_idx = torch.max(probs, dim=-1)
225
+ predicted_label = self.model.config.id2label[top_idx.item()]
226
+ confidence = top_prob.item()
227
+
228
+ if confidence < self.softmax_threshold:
229
+ predicted_label = 'neutral'
230
+ print(f"[EILProcessor] Low confidence ({confidence:.2f}) — setting to 'neutral'")
231
+
232
+ print(f"[EILProcessor] Model prediction: {predicted_label} ({confidence:.2f})")
233
+ model_to_codex_map = {
234
+ "joy": "FAM-JOY",
235
+ "anger": "FAM-ANG",
236
+ "sadness": "FAM-SAD",
237
+ "fear": "FAM-FEA",
238
+ "love": "FAM-LOV",
239
+ "surprise": "FAM-SUR",
240
+ "disgust": "FAM-DIS",
241
+ "neutral": "FAM-NEU"
242
+ }
243
+ primary_emotion_code = model_to_codex_map.get(predicted_label.lower(), "FAM-NEU")
244
+ emotion_data = self.codex_informer.resolve_emotion_family(primary_emotion_code)
245
+ blend = {emotion_data['primary_emotion_code']: 1.0}
246
+
247
+ packet = {
248
+ 'phrases': [input_text],
249
+ 'emotion_candidates': [{'phrase': input_text, 'candidate_emotion': predicted_label}],
250
+ 'metadata': {'source': 'EILProcessor (model)', 'input_type': input_type},
251
+ 'emotion_family': emotion_data['emotion_family'],
252
+ 'primary_emotion_code': emotion_data['primary_emotion_code'],
253
+ 'arc': emotion_data['arc'],
254
+ 'resonance': emotion_data['resonance'],
255
+ 'blend': blend
256
+ }
257
+ return packet
core/eris_reasoner.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import hashlib
2
  import time
3
  from core.codex_informer import CodexInformer
@@ -5,41 +7,54 @@ from core.hei_inference import HEIInference
5
 
6
  class ERISReasoner:
7
  def __init__(self):
8
- # Initialize Codex Informer as part of ERIS
9
  self.codex_informer = CodexInformer()
10
 
11
  def reason_emotion_state(self, esil_packet):
12
- # Generate EmID (using user_id + primary_emotion + timestamp)
13
- user_id = "user123" # Placeholder user_id, can be dynamic if needed
14
- timestamp = str(int(time.time())) # Current time in seconds
15
- primary_emotion = esil_packet.get("primary_emotion", "UNK-000")
16
- primary_emotion_code = esil_packet.get("primary_emotion_code", "UNK")
17
- emotion_family = esil_packet.get("emotion_family", "UNK")
18
-
19
- # Retrieve emotion arc and resonance from Codex Informer (shared service)
20
- arc = self.codex_informer.get_arc(primary_emotion_code)
21
- resonance = self.codex_informer.get_resonance(primary_emotion_code)
22
-
23
- # Start building the UESP Packet
 
24
  uesp_packet = {
25
  "Primary Emotion": primary_emotion,
26
  "Primary Emotion Code": primary_emotion_code,
27
- "Emotion Arc Trajectory": arc, # From Codex Informer
28
- "Resonance Pattern": resonance, # From Codex Informer
29
- "HEART Compliance Flags": ["HVC-000"], # Placeholder, can be updated based on conditions
30
  "Empathy First Response": esil_packet.get("response", "Emotion being processed..."),
31
- "emotion_family": emotion_family # Always include this
32
  }
33
 
34
- # If the packet is empty or has no emotion_family, we call HEI for fallback
35
- if emotion_family == "UNK" or not emotion_family:
36
- print("[ERIS] No valid emotion family found — triggering HEI fallback...")
37
  hei = HEIInference()
38
- uesp_packet = hei.detect_low_signal(uesp_packet) # HEI will generate a valid packet if needed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- # Generate EmID (for traceability)
41
- emid_string = f"{user_id}-{primary_emotion}-{timestamp}"
42
- emid = hashlib.sha256(emid_string.encode()).hexdigest() # Simple hash for uniqueness
43
- uesp_packet["EmID"] = emid
44
 
 
45
  return uesp_packet
 
1
+ # core/eris_reasoner.py
2
+
3
  import hashlib
4
  import time
5
  from core.codex_informer import CodexInformer
 
7
 
8
  class ERISReasoner:
9
  def __init__(self):
 
10
  self.codex_informer = CodexInformer()
11
 
12
  def reason_emotion_state(self, esil_packet):
13
+ # Generate EmID components
14
+ user_id = "user123"
15
+
16
+ # Get primary_emotion and primary_emotion_code from ESIL packet
17
+ primary_emotion = esil_packet.get("emotion_family", "Unknown")
18
+ primary_emotion_code = esil_packet.get("primary_emotion_code", "Unknown")
19
+
20
+ # Resolve arc and resonance via Codex using primary_emotion_code
21
+ resolved_family = self.codex_informer.resolve_emotion_family(primary_emotion_code)
22
+ arc = resolved_family['arc']
23
+ resonance = resolved_family['resonance']
24
+
25
+ # Build UESP packet
26
  uesp_packet = {
27
  "Primary Emotion": primary_emotion,
28
  "Primary Emotion Code": primary_emotion_code,
29
+ "Emotion Arc Trajectory": arc,
30
+ "Resonance Pattern": resonance,
31
+ "HEART Compliance Flags": ["HVC-000"], # Placeholder
32
  "Empathy First Response": esil_packet.get("response", "Emotion being processed..."),
33
+ "emotion_family": primary_emotion
34
  }
35
 
36
+ # If no valid family trigger HEI fallback
37
+ if primary_emotion_code == "Unknown" or primary_emotion == "FAM-HID" or primary_emotion == "Hidden Emotion Detected":
38
+ print("[ERISReasoner] No valid emotion family found — triggering HEI fallback...")
39
  hei = HEIInference()
40
+ uesp_packet = hei.detect_low_signal(uesp_packet)
41
+
42
+ # Ensure Primary Emotion Code survives even after HEI fallback
43
+ if "Primary Emotion Code" not in uesp_packet:
44
+ uesp_packet["Primary Emotion Code"] = primary_emotion_code
45
+
46
+ # Build clean family code string for EmID
47
+ family_code_str = uesp_packet['Primary Emotion'].replace("FAM-", "")
48
+
49
+ # Get current timestamp (ISO-like)
50
+ timestamp_str = time.strftime("%Y%m%dT%H%M%S")
51
+
52
+ # Build hashed payload
53
+ emid_payload = f"{user_id}-{family_code_str}-{timestamp_str}"
54
+ emid_hash = hashlib.sha256(emid_payload.encode()).hexdigest()
55
 
56
+ # Final EmID: user-JOY-20250623T203633-<hash>
57
+ uesp_packet["EmID"] = f"user-{family_code_str}-{timestamp_str}-{emid_hash}"
 
 
58
 
59
+ print(f"[ERISReasoner] Generated UESP Packet: {uesp_packet}")
60
  return uesp_packet
core/esil_inference.py CHANGED
@@ -26,9 +26,13 @@ class ESILInference:
26
 
27
  # Retrieve emotion family, arc, and resonance from Codex Informer
28
  primary_emotion_code = eil_packet.get("primary_emotion_code", "UNK")
29
- emotion_family = self.codex_informer.get_emotion_family(primary_emotion_code)
30
- arc = self.codex_informer.get_arc(primary_emotion_code)
31
- resonance = self.codex_informer.get_resonance(primary_emotion_code)
 
 
 
 
32
 
33
  # If no emotion family is found, flag it as a "hidden emotion"
34
  if emotion_family == "Unknown":
@@ -44,6 +48,7 @@ class ESILInference:
44
  "emotion_family": emotion_family, # From Codex Informer
45
  "arc": arc, # From Codex Informer
46
  "resonance": resonance, # From Codex Informer
 
47
  "source_metadata": eil_packet.get("metadata", {}),
48
  "tokens": phrases
49
  }
 
26
 
27
  # Retrieve emotion family, arc, and resonance from Codex Informer
28
  primary_emotion_code = eil_packet.get("primary_emotion_code", "UNK")
29
+
30
+ # Ensure the primary emotion code is resolved correctly by CodexInformer
31
+ emotion_data = self.codex_informer.resolve_emotion_family(primary_emotion_code)
32
+
33
+ emotion_family = emotion_data['emotion_family']
34
+ arc = emotion_data['arc']
35
+ resonance = emotion_data['resonance']
36
 
37
  # If no emotion family is found, flag it as a "hidden emotion"
38
  if emotion_family == "Unknown":
 
48
  "emotion_family": emotion_family, # From Codex Informer
49
  "arc": arc, # From Codex Informer
50
  "resonance": resonance, # From Codex Informer
51
+ "primary_emotion_code": primary_emotion_code, # <-- PATCH INCLUDED
52
  "source_metadata": eil_packet.get("metadata", {}),
53
  "tokens": phrases
54
  }
core/fec_controller.py CHANGED
@@ -1,24 +1,61 @@
 
 
 
1
  class FECController:
2
  def __init__(self):
3
  pass
4
 
5
  def generate_prompt(self, final_uesp):
6
- # Validate that all necessary keys exist in final_uesp
7
- required_keys = ['emotion_family', 'Primary Emotion Code']
8
-
 
 
 
 
 
9
  for key in required_keys:
10
  if key not in final_uesp:
11
  raise KeyError(f"Missing required key: {key}")
12
-
13
- # If all keys are valid, construct the prompt
14
- primary_emotion = final_uesp['emotion_family']
15
- primary_emotion_code = final_uesp['Primary Emotion Code']
16
 
17
- # Create the Fusion Prompt
18
- fusion_prompt = f"[Primary Emotion]: {primary_emotion} ({primary_emotion_code})"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
- # Add other details to the fusion prompt if needed
21
- if 'Empathy First Response' in final_uesp:
22
- fusion_prompt += f"\nResponse: {final_uesp['Empathy First Response']}"
23
 
24
  return fusion_prompt
 
1
+ # core/fec_controller.py
2
+ # Master Emotional Core (MEC) - FECController v1.0 (LLM Instruction Layer)
3
+
4
  class FECController:
5
  def __init__(self):
6
  pass
7
 
8
  def generate_prompt(self, final_uesp):
9
+ # Validate required keys
10
+ required_keys = [
11
+ 'emotion_family',
12
+ 'Primary Emotion Code',
13
+ 'Emotion Arc Trajectory',
14
+ 'Resonance Pattern'
15
+ ]
16
+
17
  for key in required_keys:
18
  if key not in final_uesp:
19
  raise KeyError(f"Missing required key: {key}")
 
 
 
 
20
 
21
+ # Map human-readable emotion label from code
22
+ emotion_code = final_uesp['Primary Emotion Code']
23
+ # For MVP, just simplify code extraction:
24
+ if emotion_code.startswith("VAR-"):
25
+ emotion_label = emotion_code.replace("VAR-", "").split('-')[0].title()
26
+ elif emotion_code.startswith("FAM-"):
27
+ emotion_label = emotion_code.replace("FAM-", "").title()
28
+ else:
29
+ emotion_label = "Unknown"
30
+
31
+ # Base fields
32
+ arc = final_uesp['Emotion Arc Trajectory']
33
+ resonance = final_uesp['Resonance Pattern']
34
+
35
+ # Placeholder — eventually populated by ERIS/FEC blends
36
+ blend_states = final_uesp.get('Blend States', 'None detected')
37
+
38
+ # Placeholder — Response Strategy (will be routed later by ERIS/FEC)
39
+ response_strategy = final_uesp.get('Response Strategy', 'RSM-DEFAULT')
40
+
41
+ # Placeholder — T-Code (if tone classifiers applied — for now None)
42
+ tone_classification = final_uesp.get('Tone Classification', 'TBD')
43
+
44
+ # Build Fusion Prompt
45
+ fusion_prompt = f"""
46
+ Contextual Emotional State:
47
+
48
+ - Primary Emotion: {emotion_label}
49
+ - Emotional Arc: {arc}
50
+ - Resonance: {resonance}
51
+ - Tone: {tone_classification}
52
+ - Blend States: {blend_states}
53
+ - Intervention Strategy: {response_strategy}
54
+
55
+ Empathic Objective:
56
+ Align your response tone and content with the above emotional context. Prioritize emotional authenticity, HEART-compliant care, and safety. Do not merely reflect emotion — respond in an emotionally aligned and supportive manner that honors the user’s lived experience.
57
 
58
+ HEART Compliance: Response must align with HEART™ ethical principles — transparency, alignment, contextuality, traceability, and emotional safety.
59
+ """.strip()
 
60
 
61
  return fusion_prompt
gradio_ui.py ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import yaml
3
+ import os
4
+
5
+ from core.codex_informer import CodexInformer
6
+ from core.eil_processor import EILProcessor
7
+ from core.esil_inference import ESILInference
8
+ from core.eris_reasoner import ERISReasoner
9
+ from core.fec_controller import FECController
10
+
11
+ # Initialize MEC Core Components
12
+ codex_informer = CodexInformer()
13
+ eil_processor = EILProcessor(codex_informer)
14
+ esil_formatter = ESILInference(codex_informer)
15
+ eris_engine = ERISReasoner()
16
+ fec_controller = FECController()
17
+
18
+ # Load Response Strategies YAML
19
+ config_path = os.path.join("config", "response_strategies.yaml")
20
+ with open(config_path, 'r', encoding='utf-8') as f:
21
+ response_strategies = yaml.safe_load(f).get('response_strategies', {})
22
+
23
+ def process_input(user_text):
24
+ try:
25
+ print(f"[DEBUG] Received user input: {user_text!r}")
26
+
27
+ # Step 1: EIL Processing
28
+ eil_result = eil_processor.infer_emotion(user_text)
29
+ print(f"[DEBUG] EIL Result: {eil_result}")
30
+
31
+ # Step 2: ESIL Formatting
32
+ esil_packet = esil_formatter.infer_esil(eil_result)
33
+ print(f"[DEBUG] ESIL Packet: {esil_packet}")
34
+
35
+ # Step 3: ERIS Reasoning
36
+ eris_result = eris_engine.reason_emotion_state(esil_packet)
37
+ print(f"[DEBUG] ERIS Result: {eris_result}")
38
+
39
+ # Pull out your primary_emotion_code (case-agnostic)
40
+ fam_code = (
41
+ eris_result.get('primary_emotion_code') or
42
+ eris_result.get('Primary Emotion Code') or
43
+ eris_result.get('Primary Emotion')
44
+ )
45
+ if not fam_code:
46
+ raise KeyError("`primary_emotion_code` missing in ERIS result")
47
+
48
+ # Lookup response strategy
49
+ rs = response_strategies.get(fam_code, {})
50
+ rsm_code = rs.get('rsm_code', 'RSM-UNKNOWN')
51
+ strategy_name = rs.get('strategy', 'Strategy not defined')
52
+ sample_response = rs.get('sample_response', 'No response available')
53
+
54
+ simulated_output = (
55
+ f"Response Strategy Code: {rsm_code}\n"
56
+ f"Response Strategy: {strategy_name}\n\n"
57
+ f"{sample_response}"
58
+ )
59
+
60
+ # Step 4: Fusion Engine – ensure keys match what FECController expects
61
+ final_uesp = {
62
+ # FEC expects these keys:
63
+ 'emotion_family': eris_result.get('emotion_family', fam_code),
64
+ 'Primary Emotion Code': fam_code,
65
+ **eris_result # Carry over everything else, in case
66
+ }
67
+
68
+ fusion_prompt = fec_controller.generate_prompt(final_uesp)
69
+ print("[DEBUG] Fusion Prompt Generated")
70
+
71
+ return fusion_prompt, simulated_output
72
+
73
+ except Exception as e:
74
+ print(f"[ERROR] Exception in process_input: {e}")
75
+ return "[ERROR: Unable to process input]", f"An error occurred: {e}"
76
+
77
+ def launch_ui():
78
+ with gr.Blocks(title="MEC MVP – Empathic UI") as demo:
79
+ gr.Markdown("# Master Emotional Core (MEC) MVP UI\nEmpathy-first AI. Built to protect.")
80
+
81
+ with gr.Row():
82
+ user_input = gr.Textbox(label="Enter your message:", placeholder="Type here...", lines=3)
83
+
84
+ with gr.Row():
85
+ submit_button = gr.Button("Process Input")
86
+
87
+ with gr.Row():
88
+ fusion_prompt_display = gr.Textbox(label="Fusion Prompt", lines=6, interactive=False)
89
+ empathic_response_display = gr.Textbox(label="Simulated Empathic Response", lines=8, interactive=False)
90
+
91
+ submit_button.click(
92
+ fn=process_input,
93
+ inputs=[user_input],
94
+ outputs=[fusion_prompt_display, empathic_response_display]
95
+ )
96
+
97
+ demo.launch()
98
+
99
+ if __name__ == "__main__":
100
+ launch_ui()
main.py CHANGED
@@ -3,17 +3,21 @@ from core.esil_inference import ESILInference
3
  from core.eris_reasoner import ERISReasoner
4
  from core.hei_inference import HEIInference
5
  from core.fec_controller import FECController
 
6
 
7
  def run_pipeline(user_input_text, force_hei=False):
8
  print("\n--- MEC MVP Test Run ---")
9
  print(f"[Main] Pipeline Input: {user_input_text}")
10
 
11
- # 1️⃣ EIL Processor (handles both preprocessing and emotion processing)
 
 
 
 
12
  eil = EILProcessor()
13
- # Preprocess the input text first
14
- pre_packet = eil.preprocess_text(user_input_text)
15
- # Now pass the preprocessing packet to process_eil
16
- eil_packet = eil.process_eil(pre_packet)
17
  print(f"[Main] EIL Packet Output: {eil_packet}")
18
 
19
  # 2️⃣ ESIL Inference
@@ -40,6 +44,20 @@ def run_pipeline(user_input_text, force_hei=False):
40
  fusion_prompt = fec.generate_prompt(final_uesp)
41
  print(f"[Main] Final Fusion Prompt:\n{fusion_prompt}")
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  elif esil_packet['confidence_score'] < 0.65:
44
  print("\n[Main] Routing: escalate_to_hei")
45
  # 6️⃣ Trigger HEI Inference (Fallback for Low Confidence)
@@ -57,12 +75,26 @@ def run_pipeline(user_input_text, force_hei=False):
57
  fusion_prompt = fec.generate_prompt(final_uesp)
58
  print(f"[Main] Final Fusion Prompt:\n{fusion_prompt}")
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  else:
61
  print("\n[Main] Routing: LLM Assist — Not implemented")
62
 
63
  if __name__ == "__main__":
64
  # Example input that matches a SAL Trigger:
65
- test_input = "I'm okay, really"
66
 
67
  # Run in FORCE HEI mode → set to True to test Symbolic Layer
68
- run_pipeline(test_input, force_hei=True)
 
3
  from core.eris_reasoner import ERISReasoner
4
  from core.hei_inference import HEIInference
5
  from core.fec_controller import FECController
6
+ import yaml
7
 
8
  def run_pipeline(user_input_text, force_hei=False):
9
  print("\n--- MEC MVP Test Run ---")
10
  print(f"[Main] Pipeline Input: {user_input_text}")
11
 
12
+ # Load Response Strategies YAML
13
+ with open('config/response_strategies.yaml', 'r', encoding='utf-8') as f:
14
+ response_strategies = yaml.safe_load(f)['response_strategies']
15
+
16
+ # 1️⃣ EIL Processor (handles both normalization and emotion processing)
17
  eil = EILProcessor()
18
+
19
+ # Run emotion inference
20
+ eil_packet = eil.infer_emotion(user_input_text)
 
21
  print(f"[Main] EIL Packet Output: {eil_packet}")
22
 
23
  # 2️⃣ ESIL Inference
 
44
  fusion_prompt = fec.generate_prompt(final_uesp)
45
  print(f"[Main] Final Fusion Prompt:\n{fusion_prompt}")
46
 
47
+ # 6️⃣ Simulated Empathic Response
48
+ fam_code = final_uesp['primary_emotion_code']
49
+ rsm_code = response_strategies.get(fam_code, {}).get('rsm_code', 'RSM-UNKNOWN')
50
+ strategy_name = response_strategies.get(fam_code, {}).get('strategy', 'Strategy not defined')
51
+ sample_response = response_strategies.get(fam_code, {}).get('sample_response', 'No response available')
52
+
53
+ simulated_output = (
54
+ f"Response Strategy Code: {rsm_code}\n"
55
+ f"Response Strategy: {strategy_name}\n\n"
56
+ f"{sample_response}"
57
+ )
58
+
59
+ print(f"\n[Main] Simulated Empathic Response:\n{simulated_output}")
60
+
61
  elif esil_packet['confidence_score'] < 0.65:
62
  print("\n[Main] Routing: escalate_to_hei")
63
  # 6️⃣ Trigger HEI Inference (Fallback for Low Confidence)
 
75
  fusion_prompt = fec.generate_prompt(final_uesp)
76
  print(f"[Main] Final Fusion Prompt:\n{fusion_prompt}")
77
 
78
+ # 8️⃣ Simulated Empathic Response
79
+ fam_code = final_uesp['primary_emotion_code']
80
+ rsm_code = response_strategies.get(fam_code, {}).get('rsm_code', 'RSM-UNKNOWN')
81
+ strategy_name = response_strategies.get(fam_code, {}).get('strategy', 'Strategy not defined')
82
+ sample_response = response_strategies.get(fam_code, {}).get('sample_response', 'No response available')
83
+
84
+ simulated_output = (
85
+ f"Response Strategy Code: {rsm_code}\n"
86
+ f"Response Strategy: {strategy_name}\n\n"
87
+ f"{sample_response}"
88
+ )
89
+
90
+ print(f"\n[Main] Simulated Empathic Response:\n{simulated_output}")
91
+
92
  else:
93
  print("\n[Main] Routing: LLM Assist — Not implemented")
94
 
95
  if __name__ == "__main__":
96
  # Example input that matches a SAL Trigger:
97
+ test_input = "I am feeling joy"
98
 
99
  # Run in FORCE HEI mode → set to True to test Symbolic Layer
100
+ run_pipeline(test_input, force_hei=False)
mec_api.py CHANGED
@@ -1,58 +1,52 @@
1
- # mec_api.py
2
-
3
- from core.input_preprocessor import InputPreprocessor
4
  from core.eil_processor import EILProcessor
5
  from core.esil_inference import ESILInference
6
- from core.confidence_gate import ConfidenceGate
7
  from core.eris_reasoner import ERISReasoner
8
  from core.hei_inference import HEIInference
9
- from core.uesp_constructor import UESPConstructor
10
  from core.fec_controller import FECController
 
11
 
12
  def run_mec_pipeline(user_input_text, force_hei=False):
13
- # 1️⃣ Preprocessor
14
- pre = InputPreprocessor()
15
- pre_packet = pre.preprocess_text(user_input_text)
16
-
17
- # 2️⃣ EIL Processor
18
  eil = EILProcessor()
 
19
  eil_packet = eil.process_eil(pre_packet)
20
 
21
- # 3️⃣ ESIL Inference
22
  esil = ESILInference()
23
  esil_packet = esil.infer_esil(eil_packet)
24
 
 
25
  if force_hei:
26
  esil_packet['confidence_score'] = 0.40 # force low confidence to trigger HEI
27
 
28
- # 4️⃣ Confidence Gate
29
- gate = ConfidenceGate()
30
- route = gate.evaluate_confidence(esil_packet)
31
-
32
- # Routing logic:
33
- if route['routing_decision'] == "proceed_to_eris":
34
  eris = ERISReasoner()
35
- uesp = eris.reason_emotion_state(esil_packet)
36
 
37
- elif route['routing_decision'] == "escalate_to_hei":
 
38
  hei = HEIInference()
39
  pseudo_esil = hei.detect_low_signal(esil_packet)
40
 
 
41
  eris = ERISReasoner()
42
- uesp = eris.reason_emotion_state(pseudo_esil)
43
 
44
  else:
45
  # fallback (LLM Assist not implemented)
46
- uesp = {"error": "LLM Assist not implemented."}
47
- fusion_prompt = "N/A"
48
- return fusion_prompt, "N/A", uesp
49
 
 
 
50
  uesp_constructor = UESPConstructor()
51
- final_uesp = uesp_constructor.construct_uesp(uesp)
52
 
 
53
  fec = FECController()
54
  fusion_prompt = fec.generate_prompt(final_uesp)
55
 
56
- # For Gradio frontend:
57
- instruction_block = fusion_prompt # you can later split instruction more if needed
58
  return fusion_prompt, instruction_block, final_uesp
 
 
 
 
1
  from core.eil_processor import EILProcessor
2
  from core.esil_inference import ESILInference
 
3
  from core.eris_reasoner import ERISReasoner
4
  from core.hei_inference import HEIInference
 
5
  from core.fec_controller import FECController
6
+ from core.codex_informer import CodexInformer
7
 
8
  def run_mec_pipeline(user_input_text, force_hei=False):
9
+ # 1️⃣ EIL Processor (handles both preprocessing and emotion processing)
 
 
 
 
10
  eil = EILProcessor()
11
+ pre_packet = eil.preprocess_text(user_input_text)
12
  eil_packet = eil.process_eil(pre_packet)
13
 
14
+ # 2️⃣ ESIL Inference
15
  esil = ESILInference()
16
  esil_packet = esil.infer_esil(eil_packet)
17
 
18
+ # 3️⃣ Forced HEI Mode: Ensure it forces the low confidence path if True
19
  if force_hei:
20
  esil_packet['confidence_score'] = 0.40 # force low confidence to trigger HEI
21
 
22
+ # 4️⃣ Routing Logic based on Confidence Score
23
+ if esil_packet['confidence_score'] >= 0.65:
24
+ # 5️⃣ ERIS Reasoning (Final UESP Creation)
 
 
 
25
  eris = ERISReasoner()
26
+ final_uesp = eris.reason_emotion_state(esil_packet)
27
 
28
+ elif esil_packet['confidence_score'] < 0.65:
29
+ # 6️⃣ Trigger HEI Inference (Fallback for Low Confidence)
30
  hei = HEIInference()
31
  pseudo_esil = hei.detect_low_signal(esil_packet)
32
 
33
+ # 7️⃣ Post-HEI Path: Continue to ERIS → UESP → FEC
34
  eris = ERISReasoner()
35
+ final_uesp = eris.reason_emotion_state(pseudo_esil)
36
 
37
  else:
38
  # fallback (LLM Assist not implemented)
39
+ final_uesp = {"error": "LLM Assist not implemented."}
 
 
40
 
41
+ # 8️⃣ UESP Construction
42
+ # Assuming the UESPConstructor now works based on UESP data from ERIS or HEI
43
  uesp_constructor = UESPConstructor()
44
+ final_uesp = uesp_constructor.construct_uesp(final_uesp)
45
 
46
+ # 9️⃣ FEC Controller (Final Fusion Prompt)
47
  fec = FECController()
48
  fusion_prompt = fec.generate_prompt(final_uesp)
49
 
50
+ # For Gradio frontend or API response:
51
+ instruction_block = fusion_prompt # You can later split instruction more if needed
52
  return fusion_prompt, instruction_block, final_uesp