danielritchie commited on
Commit
14637ee
·
verified ·
1 Parent(s): d2785e0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -65
app.py CHANGED
@@ -1,13 +1,15 @@
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
@@ -36,17 +38,22 @@ def apply_passion(raw: dict, passion: float) -> dict:
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"],
@@ -77,13 +84,75 @@ def generate_scatter(raw, amplified, cinematic, label, passion, drama):
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="--",
@@ -91,13 +160,13 @@ def generate_scatter(raw, amplified, cinematic, label, passion, drama):
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="-",
@@ -105,36 +174,6 @@ def generate_scatter(raw, amplified, cinematic, label, passion, drama):
105
  alpha=0.9
106
  )
107
 
108
- # ----------------------------------
109
- # Dynamic Zoom (Centered + 20% Padding)
110
- # ----------------------------------
111
- xs = [raw["V"], amplified["V"], cinematic["V"]]
112
- ys = [raw["A"], amplified["A"], cinematic["A"]]
113
-
114
- min_x, max_x = min(xs), max(xs)
115
- min_y, max_y = min(ys), max(ys)
116
-
117
- span_x = max_x - min_x
118
- span_y = max_y - min_y
119
-
120
- # Use the larger span to keep square framing
121
- span = max(span_x, span_y)
122
-
123
- # Avoid zero-span collapse
124
- span = max(span, 0.05)
125
-
126
- padding = span * 0.20 # 20% larger
127
-
128
- center_x = (min_x + max_x) / 2
129
- center_y = (min_y + max_y) / 2
130
-
131
- half_range = (span / 2) + padding
132
-
133
- ax.set_xlim(center_x - half_range, center_x + half_range)
134
- ax.set_ylim(center_y - half_range, center_y + half_range)
135
-
136
- ax.set_aspect('equal', adjustable='box')
137
-
138
  ax.set_xlabel("Valence")
139
  ax.set_ylabel("Arousal")
140
  ax.set_title(f"{label}\nPassion={round(passion,2)} | Drama={round(drama,2)}")
@@ -163,7 +202,15 @@ def run_pipeline(preset_name, passion, drama):
163
  color_params = infer_color(cinematic)
164
  color_block = render_color(color_params)
165
 
166
- fig = generate_scatter(natural, amplified, cinematic, preset_name, passion, drama)
 
 
 
 
 
 
 
 
167
 
168
  return (
169
  text,
@@ -206,23 +253,17 @@ with gr.Blocks(title="Affection 👁️ — Edge Emotional Intelligence") as dem
206
 
207
  gr.Markdown(
208
  """
209
- This section provides a simplified visualization of a more complex on-device architecture.
210
-
211
- In hardware deployment, the NVIDIA Jetson Orin Nano performs all of the following:
212
-
213
- • Robot hardware daemon service
214
- • Interactive conversational application
215
- • Real-time transcript ingestion
216
- • VAD extraction (NRC-VAD lexicon)
217
- • Structural language metrics (Complexity + Coherence)
218
- • Radial emotional amplification (Passion)
219
- • Cinematic nearest-exemplar alignment (Drama)
220
- • Dual-timescale blending (fast burst + slow baseline via Nemotron/Ollama)
221
- • Continuous emotional state streaming for display on an expression module
222
-
223
  This demo isolates a single loop transformation for clarity.
224
 
225
- Our NVIDIA edge device is capable of running this loop 200x per second.
 
 
 
 
 
 
 
 
226
  """
227
  )
228
 
@@ -253,8 +294,8 @@ Our NVIDIA edge device is capable of running this loop 200x per second.
253
  gr.Markdown(
254
  """
255
  **Note:**
256
- This plot shows a 2D Valence–Arousal projection for visualization only, but results are from the actual model.
257
- Actual transformation and color inference are more complex and operate on the full 5D VAD+CC vector.
258
  """
259
  )
260
 
@@ -267,15 +308,10 @@ Actual transformation and color inference are more complex and operate on the fu
267
 
268
  gr.Markdown(
269
  """
270
- The finalized VAD+CC vector is transmitted to an expressive display module. In this example, we are converting to colors to be used for eyes.
271
-
272
- The module does not compute emotion.
273
- It receives the 5D emotional state and runs a trained neural model to convert it into expressive color.
274
 
275
- Model used here (same as deployment):
276
  https://huggingface.co/danielritchie/vibe-color-model
277
-
278
- VAD+CC (Affect Engine) → Embedded Model → Color Rendering (Expression)
279
  """
280
  )
281
 
@@ -298,6 +334,7 @@ VAD+CC (Affect Engine) → Embedded Model → Color Rendering (Expression)
298
 
299
  demo.load(fn=run_pipeline, inputs=[preset_selector, passion, drama], outputs=outputs)
300
 
 
301
  demo.launch(
302
  server_name="0.0.0.0",
303
  server_port=7860,
 
1
  # app.py — Affection 👁️ (Hugging Face Space)
2
 
3
  import os
 
 
4
 
5
+ # Disable Spaces reload BEFORE importing gradio
6
  os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
7
  os.environ["HF_HUB_DISABLE_TELEMETRY"] = "1"
8
  os.environ["SPACES_DISABLE_RELOAD"] = "1"
9
 
10
+ import gradio as gr
11
+ import matplotlib.pyplot as plt
12
+
13
  from utils.presets import EMOTION_PRESETS
14
  from utils.drama import apply_drama
15
  from utils.color_model import infer_color, render_color
 
38
  # ------------------------------------------------------------
39
  # Valence–Arousal Visualization (2D Projection)
40
  # ------------------------------------------------------------
41
+ def generate_scatter(raw, amplified, cinematic, target, label, passion, drama):
42
 
43
  fig, ax = plt.subplots(figsize=(6, 6))
44
+ base_color = "#2C3E50"
45
 
46
+ # ----------------------------------
47
+ # Background Cinematic Anchors
48
+ # ----------------------------------
49
  for _, preset in EMOTION_PRESETS.items():
50
  t = preset["target"]
51
  ax.scatter(t["V"], t["A"], alpha=0.1, s=90, color="#BBBBBB")
52
 
53
+ # ----------------------------------
54
+ # Active Emotional Trajectory
55
+ # ----------------------------------
56
+
57
  # Natural
58
  ax.scatter(
59
  raw["V"], raw["A"],
 
84
  label="After Drama (Cinematic Alignment)"
85
  )
86
 
87
+ # Cinematic Anchor (Target)
88
+ ax.scatter(
89
+ target["V"],
90
+ target["A"],
91
+ s=160,
92
+ marker="X",
93
+ color="#E74C3C",
94
+ edgecolor="black",
95
+ linewidth=1.2,
96
+ label="Cinematic Anchor"
97
+ )
98
+
99
+ ax.text(
100
+ target["V"],
101
+ target["A"],
102
+ f" {label} Target",
103
+ verticalalignment="center",
104
+ fontsize=9,
105
+ weight="bold",
106
+ color="#E74C3C"
107
+ )
108
+
109
+ # ----------------------------------
110
+ # Dynamic Zoom (20% padded, centered)
111
+ # ----------------------------------
112
+ xs = [
113
+ raw["V"],
114
+ amplified["V"],
115
+ cinematic["V"],
116
+ target["V"]
117
+ ]
118
+
119
+ ys = [
120
+ raw["A"],
121
+ amplified["A"],
122
+ cinematic["A"],
123
+ target["A"]
124
+ ]
125
+
126
+ min_x, max_x = min(xs), max(xs)
127
+ min_y, max_y = min(ys), max(ys)
128
+
129
+ span_x = max_x - min_x
130
+ span_y = max_y - min_y
131
+
132
+ span = max(span_x, span_y)
133
+ span = max(span, 0.05) # prevent collapse
134
+
135
+ padding = span * 0.20
136
+ center_x = (min_x + max_x) / 2
137
+ center_y = (min_y + max_y) / 2
138
+ half_range = (span / 2) + padding
139
+
140
+ ax.set_xlim(center_x - half_range, center_x + half_range)
141
+ ax.set_ylim(center_y - half_range, center_y + half_range)
142
+ ax.set_aspect("equal", adjustable="box")
143
+
144
+ # ----------------------------------
145
+ # Proportional Arrow Heads
146
+ # ----------------------------------
147
+ arrow_head = span * 0.04
148
+
149
+ # Raw → Amplified
150
  ax.arrow(
151
  raw["V"],
152
  raw["A"],
153
  amplified["V"] - raw["V"],
154
  amplified["A"] - raw["A"],
155
+ head_width=arrow_head,
156
  length_includes_head=True,
157
  color=base_color,
158
  linestyle="--",
 
160
  alpha=0.6
161
  )
162
 
163
+ # Amplified → Cinematic
164
  ax.arrow(
165
  amplified["V"],
166
  amplified["A"],
167
  cinematic["V"] - amplified["V"],
168
  cinematic["A"] - amplified["A"],
169
+ head_width=arrow_head,
170
  length_includes_head=True,
171
  color=base_color,
172
  linestyle="-",
 
174
  alpha=0.9
175
  )
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  ax.set_xlabel("Valence")
178
  ax.set_ylabel("Arousal")
179
  ax.set_title(f"{label}\nPassion={round(passion,2)} | Drama={round(drama,2)}")
 
202
  color_params = infer_color(cinematic)
203
  color_block = render_color(color_params)
204
 
205
+ fig = generate_scatter(
206
+ natural,
207
+ amplified,
208
+ cinematic,
209
+ target,
210
+ preset_name,
211
+ passion,
212
+ drama
213
+ )
214
 
215
  return (
216
  text,
 
253
 
254
  gr.Markdown(
255
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  This demo isolates a single loop transformation for clarity.
257
 
258
+ Hardware deployment performs:
259
+ • Transcript ingestion
260
+ • VAD extraction
261
+ • Structural metrics
262
+ • Radial amplification (Passion)
263
+ • Cinematic alignment (Drama)
264
+ • Continuous emotional state streaming
265
+
266
+ Edge loop capable of ~200Hz execution.
267
  """
268
  )
269
 
 
294
  gr.Markdown(
295
  """
296
  **Note:**
297
+ This 2D VA projection is for visualization only.
298
+ The actual transformation operates in 5D VAD+CC space.
299
  """
300
  )
301
 
 
308
 
309
  gr.Markdown(
310
  """
311
+ VAD+CC Embedded Model Color Rendering
 
 
 
312
 
313
+ Model:
314
  https://huggingface.co/danielritchie/vibe-color-model
 
 
315
  """
316
  )
317
 
 
334
 
335
  demo.load(fn=run_pipeline, inputs=[preset_selector, passion, drama], outputs=outputs)
336
 
337
+
338
  demo.launch(
339
  server_name="0.0.0.0",
340
  server_port=7860,