danielritchie commited on
Commit
bab55df
·
verified ·
1 Parent(s): b1fe85c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -108
app.py CHANGED
@@ -1,21 +1,126 @@
1
- import gradio as gr
 
2
  import os
 
 
3
 
4
  os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
5
  os.environ["HF_HUB_DISABLE_TELEMETRY"] = "1"
6
  os.environ["SPACES_DISABLE_RELOAD"] = "1"
7
 
8
  from utils.presets import EMOTION_PRESETS
9
- from utils.passion import apply_passion
10
  from utils.drama import apply_drama
11
  from utils.color_model import infer_color, render_color
12
- from utils.visualization import generate_scatter
13
 
14
 
15
  # ------------------------------------------------------------
16
- # Fast Loop Processing (Edge Simulation)
17
  # ------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
 
 
 
19
  def run_pipeline(preset_name, passion, drama):
20
 
21
  preset = EMOTION_PRESETS[preset_name]
@@ -24,168 +129,141 @@ def run_pipeline(preset_name, passion, drama):
24
  natural = preset["raw"]
25
  target = preset["target"]
26
 
27
- # Edge Phase 1 — Natural Extraction (precomputed)
28
- extracted = natural
29
-
30
- # Edge Phase 2 — Passion Amplification
31
- amplified = apply_passion(extracted, passion)
32
-
33
- # Edge Phase 3 — Cinematic Alignment
34
  cinematic = apply_drama(amplified, target, drama)
35
 
36
- # Embedded Phase — Color Model
37
  color_params = infer_color(cinematic)
38
  color_block = render_color(color_params)
39
 
40
- scatter_fig = generate_scatter(extracted, cinematic, preset_name, drama)
41
 
42
  return (
43
  text,
44
- extracted,
45
  amplified,
46
  cinematic,
47
  color_params,
48
  color_block,
49
- scatter_fig
50
  )
51
 
52
 
53
  # ------------------------------------------------------------
54
  # UI
55
  # ------------------------------------------------------------
 
56
 
57
- with gr.Blocks(title="VIBE-Eyes Edge Emotional Intelligence") as demo:
58
-
59
- gr.Markdown("# VIBE-Eyes 👁️")
60
- gr.Markdown("## Edge Emotional Intelligence for Robotics")
61
 
62
  # ---------------------------
63
- # SECTION 1 — Robot Speech
64
  # ---------------------------
65
-
66
  gr.Markdown("### 🗣 Robot Speech")
67
 
68
  preset_selector = gr.Radio(
69
  choices=list(EMOTION_PRESETS.keys()),
70
  label="Select Transcript Sample",
71
- value=list(EMOTION_PRESETS.keys())[0]
72
  )
73
 
74
- transcript_output = gr.Textbox(
75
- label="Transcript",
76
- interactive=False
77
- )
78
 
79
  gr.Markdown("---")
80
 
81
  # ---------------------------
82
- # SECTION 2 — Edge Processing
83
  # ---------------------------
 
84
 
85
- gr.Markdown("### ⚡ Edge Processing — NVIDIA Jetson Orin Nano")
 
 
86
 
87
- passion = gr.Slider(
88
- minimum=0.0,
89
- maximum=3.0,
90
- value=2.25,
91
- step=0.1,
92
- label="Passion (Radial Emotional Amplification)"
93
- )
94
 
95
- drama = gr.Slider(
96
- minimum=0.0,
97
- maximum=1.5,
98
- value=0.65,
99
- step=0.05,
100
- label="Drama (Cinematic Alignment)"
 
 
 
 
101
  )
102
 
103
  with gr.Row():
104
- natural_output = gr.JSON(label="Natural VAD+CC (Extraction)")
105
- amplified_output = gr.JSON(label="After Passion (Radial Gain)")
106
- cinematic_output = gr.JSON(label="After Drama (Cinematic Alignment)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
  scatter_output = gr.Plot(label="Valence–Arousal Projection")
109
 
110
  gr.Markdown(
111
  """
112
- *Note:*
113
- In the full hardware system, a parallel slow-loop baseline
114
- (Nemotron via Ollama) continuously recalibrates the emotional state.
115
- This demo focuses on the real-time fast loop for clarity.
116
  """
117
  )
118
 
119
  gr.Markdown("---")
120
 
121
  # ---------------------------
122
- # SECTION 3 — Embedded Module
123
  # ---------------------------
 
124
 
125
- gr.Markdown("### 💡 Embedded Display Module")
126
-
127
- rgb_output = gr.JSON(label="Color Model Output (RGB + Expressive Parameters)")
128
- color_display = gr.HTML(label="Rendered Expression")
129
-
130
- # ---------------------------
131
- # Bind
132
- # ---------------------------
133
 
134
- preset_selector.change(
135
- fn=run_pipeline,
136
- inputs=[preset_selector, passion, drama],
137
- outputs=[
138
- transcript_output,
139
- natural_output,
140
- amplified_output,
141
- cinematic_output,
142
- rgb_output,
143
- color_display,
144
- scatter_output
145
- ]
146
- )
147
 
148
- passion.change(
149
- fn=run_pipeline,
150
- inputs=[preset_selector, passion, drama],
151
- outputs=[
152
- transcript_output,
153
- natural_output,
154
- amplified_output,
155
- cinematic_output,
156
- rgb_output,
157
- color_display,
158
- scatter_output
159
- ]
160
- )
161
 
162
- drama.change(
163
- fn=run_pipeline,
164
- inputs=[preset_selector, passion, drama],
165
- outputs=[
166
- transcript_output,
167
- natural_output,
168
- amplified_output,
169
- cinematic_output,
170
- rgb_output,
171
- color_display,
172
- scatter_output
173
- ]
174
  )
175
 
176
- demo.load(
177
- fn=run_pipeline,
178
- inputs=[preset_selector, passion, drama],
179
- outputs=[
180
- transcript_output,
181
- natural_output,
182
- amplified_output,
183
- cinematic_output,
184
- rgb_output,
185
- color_display,
186
- scatter_output
187
- ]
188
- )
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
+ # app.py Affection 👁️ (Hugging Face Space)
2
+
3
  import os
4
+ import gradio as gr
5
+ import matplotlib.pyplot as plt
6
 
7
  os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
8
  os.environ["HF_HUB_DISABLE_TELEMETRY"] = "1"
9
  os.environ["SPACES_DISABLE_RELOAD"] = "1"
10
 
11
  from utils.presets import EMOTION_PRESETS
 
12
  from utils.drama import apply_drama
13
  from utils.color_model import infer_color, render_color
 
14
 
15
 
16
  # ------------------------------------------------------------
17
+ # Passion (Radial Amplification)
18
  # ------------------------------------------------------------
19
+ def apply_passion(raw: dict, passion: float) -> dict:
20
+ passion = max(0.0, min(3.5, float(passion)))
21
+ out = {}
22
+
23
+ for k, v in raw.items():
24
+ v = float(v)
25
+ if k in ("V", "A", "D"):
26
+ delta = v - 0.5
27
+ magnitude = abs(delta)
28
+ gain = 1.0 + passion * magnitude
29
+ out[k] = max(0.0, min(1.0, 0.5 + delta * gain))
30
+ else:
31
+ out[k] = max(0.0, min(1.0, v))
32
+
33
+ return out
34
+
35
+
36
+ # ------------------------------------------------------------
37
+ # Valence–Arousal Visualization (2D Projection)
38
+ # ------------------------------------------------------------
39
+ def generate_scatter(raw, amplified, cinematic, label, passion, drama):
40
+
41
+ fig, ax = plt.subplots(figsize=(6, 6))
42
+
43
+ base_color = "#2C3E50" # neutral deep tone
44
+
45
+ # Plot cinematic anchors faintly
46
+ for _, preset in EMOTION_PRESETS.items():
47
+ t = preset["target"]
48
+ ax.scatter(t["V"], t["A"], alpha=0.1, s=90, color="#BBBBBB")
49
+
50
+ # Natural
51
+ ax.scatter(
52
+ raw["V"], raw["A"],
53
+ s=180,
54
+ facecolor=base_color,
55
+ alpha=0.5,
56
+ label="Natural (Extraction)"
57
+ )
58
+
59
+ # After Passion
60
+ ax.scatter(
61
+ amplified["V"], amplified["A"],
62
+ s=180,
63
+ facecolors="none",
64
+ edgecolors=base_color,
65
+ linewidth=2,
66
+ label="After Passion (Radial Gain)"
67
+ )
68
+
69
+ # After Drama
70
+ ax.scatter(
71
+ cinematic["V"], cinematic["A"],
72
+ s=220,
73
+ facecolor=base_color,
74
+ edgecolor="black",
75
+ linewidth=1.5,
76
+ alpha=0.9,
77
+ label="After Drama (Cinematic Alignment)"
78
+ )
79
+
80
+ # Arrow 1 — Raw → Amplified
81
+ ax.arrow(
82
+ raw["V"],
83
+ raw["A"],
84
+ amplified["V"] - raw["V"],
85
+ amplified["A"] - raw["A"],
86
+ head_width=0.02,
87
+ length_includes_head=True,
88
+ color=base_color,
89
+ linestyle="--",
90
+ linewidth=2,
91
+ alpha=0.6
92
+ )
93
+
94
+ # Arrow 2 — Amplified → Cinematic
95
+ ax.arrow(
96
+ amplified["V"],
97
+ amplified["A"],
98
+ cinematic["V"] - amplified["V"],
99
+ cinematic["A"] - amplified["A"],
100
+ head_width=0.02,
101
+ length_includes_head=True,
102
+ color=base_color,
103
+ linestyle="-",
104
+ linewidth=2,
105
+ alpha=0.9
106
+ )
107
+
108
+ ax.set_xlim(0, 1)
109
+ ax.set_ylim(0, 1)
110
+ ax.set_xlabel("Valence")
111
+ ax.set_ylabel("Arousal")
112
+ ax.set_title(f"{label}\nPassion={round(passion,2)} | Drama={round(drama,2)}")
113
+
114
+ ax.legend(loc="lower right")
115
+ ax.grid(alpha=0.15)
116
+
117
+ plt.tight_layout()
118
+ return fig
119
+
120
 
121
+ # ------------------------------------------------------------
122
+ # Fast-Loop Simulation
123
+ # ------------------------------------------------------------
124
  def run_pipeline(preset_name, passion, drama):
125
 
126
  preset = EMOTION_PRESETS[preset_name]
 
129
  natural = preset["raw"]
130
  target = preset["target"]
131
 
132
+ amplified = apply_passion(natural, passion)
 
 
 
 
 
 
133
  cinematic = apply_drama(amplified, target, drama)
134
 
 
135
  color_params = infer_color(cinematic)
136
  color_block = render_color(color_params)
137
 
138
+ fig = generate_scatter(natural, amplified, cinematic, preset_name, passion, drama)
139
 
140
  return (
141
  text,
142
+ natural,
143
  amplified,
144
  cinematic,
145
  color_params,
146
  color_block,
147
+ fig
148
  )
149
 
150
 
151
  # ------------------------------------------------------------
152
  # UI
153
  # ------------------------------------------------------------
154
+ with gr.Blocks(title="Affection 👁️ — Edge Emotional Intelligence") as demo:
155
 
156
+ gr.Markdown("# Affection 👁️")
157
+ gr.Markdown("## Simulation Layer for an Edge AI Emotional Robotics System")
 
 
158
 
159
  # ---------------------------
160
+ # Robot Speech
161
  # ---------------------------
 
162
  gr.Markdown("### 🗣 Robot Speech")
163
 
164
  preset_selector = gr.Radio(
165
  choices=list(EMOTION_PRESETS.keys()),
166
  label="Select Transcript Sample",
167
+ value=list(EMOTION_PRESETS.keys())[0],
168
  )
169
 
170
+ transcript_output = gr.Textbox(label="Input Transcript", interactive=False)
 
 
 
171
 
172
  gr.Markdown("---")
173
 
174
  # ---------------------------
175
+ # Edge Affect Processing
176
  # ---------------------------
177
+ gr.Markdown("### ⚡ Edge Affect Processing — NVIDIA Jetson Orin Nano")
178
 
179
+ gr.Markdown(
180
+ """
181
+ This section provides a simplified visualization of a more complex on-device architecture.
182
 
183
+ In hardware deployment, the NVIDIA Jetson Orin Nano performs:
 
 
 
 
 
 
184
 
185
+ Real-time transcript ingestion
186
+ • VAD extraction (NRC-VAD lexicon)
187
+ • Structural language metrics (Complexity + Coherence)
188
+ • Radial emotional amplification (Passion)
189
+ • Cinematic nearest-exemplar alignment (Drama)
190
+ Dual-timescale blending (fast burst + slow baseline via Nemotron/Ollama)
191
+ • Continuous emotional state streaming to the display module
192
+
193
+ This demo isolates the fast-loop transformation for clarity.
194
+ """
195
  )
196
 
197
  with gr.Row():
198
+ passion = gr.Slider(
199
+ minimum=0.0,
200
+ maximum=3.0,
201
+ value=2.25,
202
+ step=0.1,
203
+ label="Passion (Radial Emotional Amplification)"
204
+ )
205
+
206
+ drama = gr.Slider(
207
+ minimum=0.0,
208
+ maximum=1.5,
209
+ value=0.65,
210
+ step=0.05,
211
+ label="Drama (Cinematic Alignment)"
212
+ )
213
+
214
+ with gr.Row():
215
+ natural_output = gr.JSON(label="Natural VAD+CC")
216
+ amplified_output = gr.JSON(label="After Passion")
217
+ cinematic_output = gr.JSON(label="After Drama")
218
 
219
  scatter_output = gr.Plot(label="Valence–Arousal Projection")
220
 
221
  gr.Markdown(
222
  """
223
+ **Note:**
224
+ This plot shows a 2D Valence–Arousal projection for visualization only.
225
+ All transformations and color inference operate on the full 5D VAD+CC vector.
 
226
  """
227
  )
228
 
229
  gr.Markdown("---")
230
 
231
  # ---------------------------
232
+ # Emotional Expression
233
  # ---------------------------
234
+ gr.Markdown("### 💡 Emotional Expression")
235
 
236
+ gr.Markdown(
237
+ """
238
+ The finalized VAD+CC vector is transmitted to an embedded display module.
 
 
 
 
 
239
 
240
+ The module does not compute emotion.
241
+ It receives the 5D emotional state and runs a trained neural model to convert it into expressive color.
 
 
 
 
 
 
 
 
 
 
 
242
 
243
+ Model used here (same as deployment):
244
+ https://huggingface.co/danielritchie/vibe-color-model
 
 
 
 
 
 
 
 
 
 
 
245
 
246
+ VAD+CC → Embedded Model ��� Color Rendering
247
+ """
 
 
 
 
 
 
 
 
 
 
248
  )
249
 
250
+ rgb_output = gr.JSON(label="Model Output (RGB + Expressive Parameters)")
251
+ color_display = gr.HTML(label="Rendered Expression")
 
 
 
 
 
 
 
 
 
 
 
252
 
253
+ outputs = [
254
+ transcript_output,
255
+ natural_output,
256
+ amplified_output,
257
+ cinematic_output,
258
+ rgb_output,
259
+ color_display,
260
+ scatter_output
261
+ ]
262
+
263
+ preset_selector.change(fn=run_pipeline, inputs=[preset_selector, passion, drama], outputs=outputs)
264
+ passion.change(fn=run_pipeline, inputs=[preset_selector, passion, drama], outputs=outputs)
265
+ drama.change(fn=run_pipeline, inputs=[preset_selector, passion, drama], outputs=outputs)
266
+
267
+ demo.load(fn=run_pipeline, inputs=[preset_selector, passion, drama], outputs=outputs)
268
 
269
  demo.launch(server_name="0.0.0.0", server_port=7860)