ataeff commited on
Commit
0f90eb0
·
verified ·
1 Parent(s): 914e48b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +329 -176
app.py CHANGED
@@ -47,6 +47,178 @@ except ImportError as e:
47
  CHAMBER_NAMES = []
48
 
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  # ============================================================================
51
  # HAZE SESSION WITH FULL CLOUD INTEGRATION
52
  # ============================================================================
@@ -137,91 +309,39 @@ class HazeSession:
137
  if not self._initialized:
138
  await self.initialize()
139
 
140
- # ===== 1. CLOUD PING =====
141
  cloud_data = {}
142
- cloud_response = None
143
-
144
- if self.cloud:
145
- try:
146
- cloud_response = await self.cloud.ping(user_input)
147
- self._cloud_responses.append(cloud_response)
148
-
149
- cloud_data = {
150
- "primary": cloud_response.primary,
151
- "secondary": cloud_response.secondary,
152
- "chambers": cloud_response.chamber_activations,
153
- "iterations": cloud_response.iterations,
154
- "anomaly": {
155
- "has_anomaly": cloud_response.anomaly.has_anomaly,
156
- "description": cloud_response.anomaly.description,
157
- "severity": cloud_response.anomaly.severity,
158
- } if cloud_response.anomaly else None,
159
- }
160
-
161
- # Get dominant chamber
162
- if cloud_response.chamber_activations:
163
- dominant = max(
164
- cloud_response.chamber_activations.items(),
165
- key=lambda x: x[1]
166
- )
167
- cloud_data["dominant_chamber"] = dominant[0]
168
- cloud_data["dominant_activation"] = dominant[1]
169
-
170
- except Exception as e:
171
- cloud_data = {"error": str(e)}
172
-
173
- # ===== 2. UPDATE HAZE AMK FROM CLOUD =====
174
- # CLOUD chambers directly influence HAZE field dynamics
175
- if cloud_response and cloud_response.chamber_activations:
176
- self.haze.update_from_cloud(cloud_response.chamber_activations)
177
-
178
- # ===== 3. HAZE RESPOND =====
179
  response = await self.haze.respond(user_input)
180
 
181
- # ===== BUILD METADATA =====
182
- metadata = {
183
- "internal_seed": response.internal_seed,
184
- "temperature": response.temperature,
185
- "generation_time": f"{response.generation_time:.3f}s",
186
- "turn_count": self.haze.turn_count,
187
- "enrichment": response.enrichment_count,
188
- }
189
-
190
- if cloud_data:
191
- metadata["cloud"] = cloud_data
192
-
193
- # AMK state from response (now integrated into HAZE)
194
- if response.amk_state:
195
- metadata["amk"] = response.amk_state
196
- metadata["prophecy_debt"] = response.amk_state.get("debt", 0)
197
- metadata["pain"] = response.amk_state.get("pain", 0)
198
-
199
- if response.trauma:
200
- metadata["trauma_level"] = response.trauma.level
201
- metadata["trauma_triggers"] = list(response.trauma.trigger_words)[:5]
202
-
203
- if response.trauma_influence:
204
- metadata["trauma_influence"] = {
205
- "temp_modifier": response.trauma_influence.temperature_modifier,
206
- "identity_weight": response.trauma_influence.identity_weight,
207
- "should_prefix": response.trauma_influence.should_prefix,
208
- }
209
-
210
- if response.expert_mixture:
211
- metadata["experts"] = response.expert_mixture
212
-
213
- if response.pulse:
214
- metadata["pulse"] = {
215
- "novelty": response.pulse.novelty,
216
- "arousal": response.pulse.arousal,
217
- "entropy": response.pulse.entropy,
218
- }
219
 
220
  # Update history
221
  self.history.append((user_input, response.text))
222
 
223
  return response.text, metadata
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  def get_cloud_summary(self) -> dict:
226
  """Get summary of CLOUD activity across session."""
227
  if not self._cloud_responses:
@@ -275,47 +395,13 @@ async def async_respond(
275
  message: str,
276
  history: List[Tuple[str, str]],
277
  ) -> Tuple[str, str]:
278
- """
279
- Async handler for Gradio.
280
- """
281
  session = get_session()
282
 
283
  try:
284
  response_text, metadata = await session.respond(message)
285
-
286
- # Format metadata for display
287
- meta_lines = []
288
-
289
- # CLOUD info
290
- if "cloud" in metadata:
291
- cloud = metadata["cloud"]
292
- if "primary" in cloud:
293
- meta_lines.append(f"💭 {cloud['primary']}")
294
- if "dominant_chamber" in cloud:
295
- meta_lines.append(f"🏛️ {cloud['dominant_chamber']}")
296
-
297
- # Temperature and timing
298
- if "temperature" in metadata:
299
- meta_lines.append(f"🌡️ {metadata['temperature']:.2f}")
300
- meta_lines.append(f"⏱️ {metadata.get('generation_time', 'N/A')}")
301
-
302
- # DSL state
303
- if "pain" in metadata:
304
- meta_lines.append(f"💔 pain:{metadata['pain']:.2f}")
305
- if "prophecy_debt" in metadata:
306
- meta_lines.append(f"📜 debt:{metadata['prophecy_debt']:.2f}")
307
-
308
- # Trauma
309
- if "trauma_level" in metadata:
310
- meta_lines.append(f"🩹 trauma:{metadata['trauma_level']:.2f}")
311
-
312
- # Turn count
313
- meta_lines.append(f"🔄 turn:{metadata.get('turn_count', 0)}")
314
-
315
- metadata_str = " | ".join(meta_lines)
316
-
317
  return response_text, metadata_str
318
-
319
  except Exception as e:
320
  import traceback
321
  traceback.print_exc()
@@ -336,44 +422,131 @@ def respond(
336
 
337
 
338
  def create_interface():
339
- """Create Gradio interface."""
340
  try:
341
  import gradio as gr
342
  except ImportError:
343
  print("[error] gradio not installed. Run: pip install gradio")
344
- return None
345
 
346
- # Custom CSS for dark gothic theme
347
- custom_css = """
348
- .gradio-container {
349
- background-color: #0a0a0c !important;
350
- }
351
- .chatbot .message {
352
- font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace !important;
353
- }
354
- """
355
 
356
- # ASCII art logo
357
- logo = """
358
- ```
359
- ██╗ ██╗ █████╗ ███████╗███████╗
360
- ██║ ██║██╔══██╗╚══███╔╝██╔════╝
361
- ███████║███████║ ███╔╝ █████╗
362
- ██╔══██║██╔══██║ ███╔╝ ██╔══╝
363
- ██║ ██║██║ ██║███████╗███████╗
364
- ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝
365
- ```
366
- **Hybrid Attention Entropy System** + **CLOUD** (~181K params)
367
-
368
- *"emergence is not creation but recognition"*
369
-
370
- **NO SEED FROM PROMPT** — Haze speaks from its internal field, not your input.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  """
372
 
373
- with gr.Blocks(css=custom_css, title="HAZE + CLOUD") as demo:
374
- gr.Markdown(logo)
375
 
376
  with gr.Row():
 
377
  with gr.Column(scale=3):
378
  chatbot = gr.Chatbot(
379
  label="Conversation",
@@ -398,50 +571,27 @@ def create_interface():
398
  max_lines=2,
399
  )
400
 
 
401
  with gr.Column(scale=1):
402
- gr.Markdown("""
403
- ### Architecture
404
-
405
- **CLOUD** (~181K params):
406
- - 6 Chambers: FEAR, LOVE, RAGE, VOID, FLOW, COMPLEX
407
- - Cross-fire stabilization
408
- - Meta-observer (secondary emotion)
409
-
410
- **HAZE** (emergent field):
411
- - Subjectivity (NO SEED FROM PROMPT)
412
- - Trauma module (identity)
413
- - Expert mixture (4 temperatures)
414
- - Co-occurrence field
415
-
416
- **DSL** (Arianna Method):
417
- - prophecy_debt: |destined - manifested|
418
- - pain, tension, dissonance
419
-
420
- ### Philosophy
421
-
422
- > *"presence > intelligence"*
423
- >
424
- > *"prophecy ≠ prediction"*
425
- >
426
- > *"minimize(destined - manifested)"*
427
- """)
428
 
 
429
  def chat(message, history):
430
  response, metadata = respond(message, history)
431
- history = history + [(message, response)]
 
 
 
432
  return "", history, metadata
433
 
 
434
  msg.submit(chat, [msg, chatbot], [msg, chatbot, metadata_display])
435
  submit.click(chat, [msg, chatbot], [msg, chatbot, metadata_display])
436
 
437
- gr.Markdown("""
438
- ---
439
- **Part of the Arianna Method** | [GitHub](https://github.com/ariannamethod/haze) | [Leo](https://github.com/ariannamethod/leo) | [PITOMADOM](https://github.com/ariannamethod/pitomadom)
440
-
441
- *Co-authored by Claude (GitHub Copilot Coding Agent), January 2026*
442
- """)
443
 
444
- return demo
445
 
446
 
447
  # ============================================================================
@@ -458,16 +608,19 @@ def main():
458
  print("=" * 60)
459
  print()
460
 
461
- demo = create_interface()
462
 
463
- if demo is None:
464
  print("[error] Could not create interface")
465
  return
466
 
 
 
467
  print("Starting Gradio server...")
468
  print()
469
 
470
  # Launch with HuggingFace Spaces compatible settings
 
471
  demo.launch(
472
  server_name="0.0.0.0",
473
  server_port=7860,
 
47
  CHAMBER_NAMES = []
48
 
49
 
50
+ # ============================================================================
51
+ # CONSTANTS
52
+ # ============================================================================
53
+
54
+ LOGO_TEXT = """
55
+ <pre style="color: #ffb347; background: transparent;">
56
+ ██╗ ██╗ █████╗ ███████╗███████╗
57
+ ██║ ██║██╔══██╗╚══███╔╝██╔════╝
58
+ ███████║███████║ ███╔╝ █████╗
59
+ ██╔══██║██╔══██║ ███╔╝ ██╔══╝
60
+ ██║ ██║██║ ██║███████╗███████╗
61
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝
62
+ </pre>
63
+
64
+ **Hybrid Attention Entropy System** + **CLOUD** (~181K params)
65
+
66
+ *"emergence is not creation but recognition"*
67
+
68
+ **NO SEED FROM PROMPT** — Haze speaks from its internal field, not your input.
69
+ """
70
+
71
+ ARCHITECTURE_INFO = """
72
+ ### Architecture
73
+
74
+ **CLOUD** (~181K params):
75
+ - 6 Chambers: FEAR, LOVE, RAGE, VOID, FLOW, COMPLEX
76
+ - Cross-fire stabilization
77
+ - Meta-observer (secondary emotion)
78
+
79
+ **HAZE** (emergent field):
80
+ - Subjectivity (NO SEED FROM PROMPT)
81
+ - Trauma module (identity)
82
+ - Expert mixture (4 temperatures)
83
+ - Co-occurrence field
84
+
85
+ **DSL** (Arianna Method):
86
+ - prophecy_debt: |destined - manifested|
87
+ - pain, tension, dissonance
88
+
89
+ ### Philosophy
90
+
91
+ > *"presence > intelligence"*
92
+ >
93
+ > *"prophecy ≠ prediction"*
94
+ >
95
+ > *"minimize(destined - manifested)"*
96
+ """
97
+
98
+ FOOTER_TEXT = """
99
+ ---
100
+ **Part of the Arianna Method** | [GitHub](https://github.com/ariannamethod/haze) | [Leo](https://github.com/ariannamethod/leo) | [PITOMADOM](https://github.com/ariannamethod/pitomadom)
101
+
102
+ *Co-authored by Claude (GitHub Copilot Coding Agent), January 2026*
103
+ """
104
+
105
+
106
+ # ============================================================================
107
+ # HELPER FUNCTIONS
108
+ # ============================================================================
109
+
110
+ def format_cloud_metadata(cloud_data: dict) -> list:
111
+ """Format CLOUD metadata for display."""
112
+ meta_lines = []
113
+ if "primary" in cloud_data:
114
+ meta_lines.append(f"💭 {cloud_data['primary']}")
115
+ if "dominant_chamber" in cloud_data:
116
+ meta_lines.append(f"🏛️ {cloud_data['dominant_chamber']}")
117
+ return meta_lines
118
+
119
+
120
+ def format_field_metadata(metadata: dict) -> str:
121
+ """Format field metadata into a readable string."""
122
+ meta_lines = []
123
+
124
+ # CLOUD info
125
+ if "cloud" in metadata:
126
+ meta_lines.extend(format_cloud_metadata(metadata["cloud"]))
127
+
128
+ # Temperature and timing
129
+ if "temperature" in metadata:
130
+ meta_lines.append(f"🌡️ {metadata['temperature']:.2f}")
131
+ meta_lines.append(f"⏱️ {metadata.get('generation_time', 'N/A')}")
132
+
133
+ # DSL state
134
+ if "pain" in metadata:
135
+ meta_lines.append(f"💔 pain:{metadata['pain']:.2f}")
136
+ if "prophecy_debt" in metadata:
137
+ meta_lines.append(f"📜 debt:{metadata['prophecy_debt']:.2f}")
138
+
139
+ # Trauma
140
+ if "trauma_level" in metadata:
141
+ meta_lines.append(f"🩹 trauma:{metadata['trauma_level']:.2f}")
142
+
143
+ # Turn count
144
+ meta_lines.append(f"🔄 turn:{metadata.get('turn_count', 0)}")
145
+
146
+ return " | ".join(meta_lines)
147
+
148
+
149
+ def build_response_metadata(response: HazeResponse, cloud_data: dict, haze_field) -> dict:
150
+ """Build metadata dictionary from HAZE response and CLOUD data."""
151
+ metadata = {
152
+ "internal_seed": response.internal_seed,
153
+ "temperature": response.temperature,
154
+ "generation_time": f"{response.generation_time:.3f}s",
155
+ "turn_count": haze_field.turn_count,
156
+ "enrichment": response.enrichment_count,
157
+ }
158
+
159
+ if cloud_data:
160
+ metadata["cloud"] = cloud_data
161
+
162
+ # AMK state
163
+ if response.amk_state:
164
+ metadata["amk"] = response.amk_state
165
+ metadata["prophecy_debt"] = response.amk_state.get("debt", 0)
166
+ metadata["pain"] = response.amk_state.get("pain", 0)
167
+
168
+ # Trauma info
169
+ if response.trauma:
170
+ metadata["trauma_level"] = response.trauma.level
171
+ metadata["trauma_triggers"] = list(response.trauma.trigger_words)[:5]
172
+
173
+ # Trauma influence
174
+ if response.trauma_influence:
175
+ metadata["trauma_influence"] = {
176
+ "temp_modifier": response.trauma_influence.temperature_modifier,
177
+ "identity_weight": response.trauma_influence.identity_weight,
178
+ "should_prefix": response.trauma_influence.should_prefix,
179
+ }
180
+
181
+ # Expert mixture
182
+ if response.expert_mixture:
183
+ metadata["experts"] = response.expert_mixture
184
+
185
+ # Pulse
186
+ if response.pulse:
187
+ metadata["pulse"] = {
188
+ "novelty": response.pulse.novelty,
189
+ "arousal": response.pulse.arousal,
190
+ "entropy": response.pulse.entropy,
191
+ }
192
+
193
+ return metadata
194
+
195
+
196
+ def process_cloud_response(cloud_response: CloudResponse) -> dict:
197
+ """Process CLOUD response into metadata dictionary."""
198
+ cloud_data = {
199
+ "primary": cloud_response.primary,
200
+ "secondary": cloud_response.secondary,
201
+ "chambers": cloud_response.chamber_activations,
202
+ "iterations": cloud_response.iterations,
203
+ "anomaly": {
204
+ "has_anomaly": cloud_response.anomaly.has_anomaly,
205
+ "description": cloud_response.anomaly.description,
206
+ "severity": cloud_response.anomaly.severity,
207
+ } if cloud_response.anomaly else None,
208
+ }
209
+
210
+ # Get dominant chamber
211
+ if cloud_response.chamber_activations:
212
+ dominant = max(
213
+ cloud_response.chamber_activations.items(),
214
+ key=lambda x: x[1]
215
+ )
216
+ cloud_data["dominant_chamber"] = dominant[0]
217
+ cloud_data["dominant_activation"] = dominant[1]
218
+
219
+ return cloud_data
220
+
221
+
222
  # ============================================================================
223
  # HAZE SESSION WITH FULL CLOUD INTEGRATION
224
  # ============================================================================
 
309
  if not self._initialized:
310
  await self.initialize()
311
 
312
+ # CLOUD ping
313
  cloud_data = {}
314
+ cloud_response = await self._ping_cloud(user_input)
315
+ if cloud_response:
316
+ cloud_data = process_cloud_response(cloud_response)
317
+ # Update HAZE field from CLOUD chambers
318
+ if cloud_response.chamber_activations:
319
+ self.haze.update_from_cloud(cloud_response.chamber_activations)
320
+
321
+ # HAZE respond
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  response = await self.haze.respond(user_input)
323
 
324
+ # Build and return metadata
325
+ metadata = build_response_metadata(response, cloud_data, self.haze)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
  # Update history
328
  self.history.append((user_input, response.text))
329
 
330
  return response.text, metadata
331
 
332
+ async def _ping_cloud(self, user_input: str) -> Optional[CloudResponse]:
333
+ """Ping CLOUD for emotion detection."""
334
+ if not self.cloud:
335
+ return None
336
+
337
+ try:
338
+ cloud_response = await self.cloud.ping(user_input)
339
+ self._cloud_responses.append(cloud_response)
340
+ return cloud_response
341
+ except Exception as e:
342
+ print(f"[app] CLOUD ping failed: {e}")
343
+ return None
344
+
345
  def get_cloud_summary(self) -> dict:
346
  """Get summary of CLOUD activity across session."""
347
  if not self._cloud_responses:
 
395
  message: str,
396
  history: List[Tuple[str, str]],
397
  ) -> Tuple[str, str]:
398
+ """Async handler for Gradio."""
 
 
399
  session = get_session()
400
 
401
  try:
402
  response_text, metadata = await session.respond(message)
403
+ metadata_str = format_field_metadata(metadata)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  return response_text, metadata_str
 
405
  except Exception as e:
406
  import traceback
407
  traceback.print_exc()
 
422
 
423
 
424
  def create_interface():
425
+ """Create and return Gradio interface with custom theme."""
426
  try:
427
  import gradio as gr
428
  except ImportError:
429
  print("[error] gradio not installed. Run: pip install gradio")
430
+ return None, None
431
 
432
+ from gradio import ChatMessage
 
 
 
 
 
 
 
 
433
 
434
+ # Create custom dark theme for HAZE
435
+ haze_theme = gr.themes.Base(
436
+ primary_hue="orange",
437
+ secondary_hue="slate",
438
+ neutral_hue="slate",
439
+ font=gr.themes.GoogleFont("IBM Plex Mono"),
440
+ ).set(
441
+ # Global colors
442
+ body_background_fill="#0a0a0c",
443
+ body_background_fill_dark="#0a0a0c",
444
+ background_fill_primary="#0a0a0c",
445
+ background_fill_primary_dark="#0a0a0c",
446
+ background_fill_secondary="#1a1a1f",
447
+ background_fill_secondary_dark="#1a1a1f",
448
+
449
+ # Text colors - important for visibility!
450
+ body_text_color="#e8e8e8",
451
+ body_text_color_dark="#e8e8e8",
452
+ body_text_color_subdued="#d0d0d0",
453
+ body_text_color_subdued_dark="#d0d0d0",
454
+
455
+ # Borders - remove white borders
456
+ border_color_primary="transparent",
457
+ border_color_primary_dark="transparent",
458
+
459
+ # Input/textbox styling
460
+ input_background_fill="#1a1a1f",
461
+ input_background_fill_dark="#1a1a1f",
462
+ input_border_color="transparent",
463
+ input_border_color_dark="transparent",
464
+ input_border_width="0px",
465
+
466
+ # Button styling
467
+ button_primary_background_fill="#ffb347",
468
+ button_primary_background_fill_dark="#ffb347",
469
+ button_primary_text_color="#0a0a0c",
470
+ button_primary_text_color_dark="#0a0a0c",
471
+
472
+ # Block styling
473
+ block_background_fill="transparent",
474
+ block_background_fill_dark="transparent",
475
+ block_border_width="0px",
476
+ block_border_color="transparent",
477
+ block_border_color_dark="transparent",
478
+
479
+ # Shadow removal
480
+ shadow_drop="none",
481
+ shadow_drop_lg="none",
482
+ )
483
+
484
+ # Additional CSS for chatbot message visibility
485
+ custom_css = """
486
+ /* Force dark background and visible text for all elements */
487
+ * {
488
+ color: #e8e8e8 !important;
489
+ }
490
+
491
+ /* Chatbot container - dark background */
492
+ .chatbot {
493
+ background: #0a0a0c !important;
494
+ }
495
+
496
+ /* Message bubbles with strong contrast */
497
+ .message-wrap {
498
+ background: transparent !important;
499
+ }
500
+
501
+ /* User messages - dark gray background with white text */
502
+ .message.user, .user-message, [data-testid="user"] {
503
+ background-color: #1a1a1f !important;
504
+ color: #ffffff !important;
505
+ }
506
+
507
+ .message.user *, .user-message *, [data-testid="user"] * {
508
+ color: #ffffff !important;
509
+ }
510
+
511
+ /* Bot/Haze messages - slightly lighter background with orange text */
512
+ .message.bot, .bot-message, [data-testid="bot"] {
513
+ background-color: #2a2a2f !important;
514
+ color: #ffb347 !important;
515
+ }
516
+
517
+ .message.bot *, .bot-message *, [data-testid="bot"] * {
518
+ color: #ffb347 !important;
519
+ }
520
+
521
+ /* Ensure markdown in messages is visible */
522
+ .message p, .message span, .message div {
523
+ color: inherit !important;
524
+ }
525
+
526
+ /* Remove borders */
527
+ .contain, .block, .chatbot {
528
+ border: none !important;
529
+ box-shadow: none !important;
530
+ }
531
+
532
+ /* Input field visibility */
533
+ input, textarea {
534
+ background-color: #1a1a1f !important;
535
+ color: #e8e8e8 !important;
536
+ border: 1px solid #333 !important;
537
+ }
538
+
539
+ /* Markdown text visibility */
540
+ .markdown-body, .prose {
541
+ color: #d0d0d0 !important;
542
+ }
543
  """
544
 
545
+ with gr.Blocks(theme=haze_theme, css=custom_css) as demo:
546
+ gr.Markdown(LOGO_TEXT)
547
 
548
  with gr.Row():
549
+ # Main chat interface
550
  with gr.Column(scale=3):
551
  chatbot = gr.Chatbot(
552
  label="Conversation",
 
571
  max_lines=2,
572
  )
573
 
574
+ # Sidebar with architecture info
575
  with gr.Column(scale=1):
576
+ gr.Markdown(ARCHITECTURE_INFO)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
577
 
578
+ # Chat handler
579
  def chat(message, history):
580
  response, metadata = respond(message, history)
581
+ history = history + [
582
+ ChatMessage(role="user", content=message),
583
+ ChatMessage(role="assistant", content=response)
584
+ ]
585
  return "", history, metadata
586
 
587
+ # Connect handlers
588
  msg.submit(chat, [msg, chatbot], [msg, chatbot, metadata_display])
589
  submit.click(chat, [msg, chatbot], [msg, chatbot, metadata_display])
590
 
591
+ # Footer
592
+ gr.Markdown(FOOTER_TEXT)
 
 
 
 
593
 
594
+ return demo, haze_theme, custom_css
595
 
596
 
597
  # ============================================================================
 
608
  print("=" * 60)
609
  print()
610
 
611
+ result = create_interface()
612
 
613
+ if result is None or result[0] is None:
614
  print("[error] Could not create interface")
615
  return
616
 
617
+ demo, theme, css = result
618
+
619
  print("Starting Gradio server...")
620
  print()
621
 
622
  # Launch with HuggingFace Spaces compatible settings
623
+ # In Gradio 6.0+, theme and css are passed to launch()
624
  demo.launch(
625
  server_name="0.0.0.0",
626
  server_port=7860,