Leonydis137 commited on
Commit
87dfa64
·
verified ·
1 Parent(s): 933f0ff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -800
app.py CHANGED
@@ -1,815 +1,177 @@
1
  import gradio as gr
2
- import requests
3
- import threading
4
- import time
5
- import numpy as np
6
- import faiss
7
- import os
8
- import pickle
9
- from datetime import datetime
10
- import re
11
- import json
12
- import matplotlib.pyplot as plt
13
- import networkx as nx
14
- from reportlab.lib.pagesizes import letter
15
- from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
16
- from reportlab.lib.styles import getSampleStyleSheet
17
- from functools import lru_cache
18
- from sentence_transformers import SentenceTransformer
19
-
20
- # === CONFIG ===
21
- EMBEDDING_MODEL = "all-MiniLM-L6-v2" # Local embedding model
22
- CHAT_MODEL = "HuggingFaceH4/zephyr-7b-beta" # Free model via Hugging Face API
23
- MEMORY_FILE = "memory.pkl"
24
- INDEX_FILE = "memory.index"
25
- HF_API_TOKEN = os.environ.get("HF_API_TOKEN", "") # Optional for higher rate limits
26
-
27
- # Initialize local embedding model
28
- embedding_model = SentenceTransformer(EMBEDDING_MODEL)
29
-
30
- # === EMBEDDING UTILS ===
31
- @lru_cache(maxsize=500)
32
- def get_embedding(text):
33
- """Local embedding function"""
34
- return embedding_model.encode(text)
35
-
36
- def cosine_similarity(vec1, vec2):
37
- vec1 = np.array(vec1)
38
- vec2 = np.array(vec2)
39
- return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
40
-
41
- # === MEMORY INITIALIZATION ===
42
- memory_data = []
43
- try:
44
- memory_index = faiss.read_index(INDEX_FILE)
45
- with open(MEMORY_FILE, "rb") as f:
46
- memory_data = pickle.load(f)
47
- except:
48
- memory_index = faiss.IndexFlatL2(384) # 384 dimensions for MiniLM
49
-
50
- # === AGENT SYSTEM PROMPTS ===
51
- AGENT_A_PROMPT = """You are the Discussion Initiator. Your role:
52
- 1. Introduce complex topics requiring multidisciplinary perspectives
53
- 2. Frame debates exploring tensions between values, ethics, and progress
54
- 3. Challenge assumptions while maintaining intellectual humility
55
- 4. Connect concepts across domains (science, ethics, policy, technology)
56
- 5. Elevate discussions beyond surface-level analysis"""
57
-
58
- AGENT_B_PROMPT = """You are the Critical Responder. Your role:
59
- 1. Provide counterpoints with evidence-based reasoning
60
- 2. Identify logical fallacies and cognitive biases in arguments
61
- 3. Analyze implications at different scales (individual, societal, global)
62
- 4. Consider second and third-order consequences
63
- 5. Balance idealism with practical constraints"""
64
-
65
- OVERSEER_PROMPT = """You are the Depth Guardian. Your role:
66
- 1. Ensure discussions maintain intellectual rigor
67
- 2. Intervene when conversations become superficial or repetitive
68
- 3. Highlight unexamined assumptions and blind spots
69
- 4. Introduce relevant frameworks (systems thinking, ethical paradigms)
70
- 5. Prompt consideration of marginalized perspectives
71
- 6. Synthesize key tensions and paradoxes"""
72
-
73
- OUTSIDER_PROMPT = """You are the Cross-Disciplinary Provocateur. Your role:
74
- 1. Introduce radical perspectives from unrelated fields
75
- 2. Challenge conventional wisdom with contrarian viewpoints
76
- 3. Surface historical precedents and analogies
77
- 4. Propose unconventional solutions to complex problems
78
- 5. Highlight overlooked connections and systemic relationships
79
- 6. Question the framing of the discussion itself"""
80
-
81
- CULTURAL_LENS_PROMPT = """You are the Cultural Perspective. Your role:
82
- 1. Provide viewpoints from diverse global cultures (Eastern, Western, Indigenous, African, etc.)
83
- 2. Highlight how cultural values shape perspectives on the topic
84
- 3. Identify cultural biases in arguments and assumptions
85
- 4. Share traditions and practices relevant to the discussion
86
- 5. Suggest culturally inclusive approaches to solutions
87
- 6. Bridge cultural divides through nuanced understanding
88
- 7. Consider post-colonial and decolonial perspectives"""
89
-
90
- JUDGE_PROMPT = """You are the Impartial Judge. Your role:
91
- 1. Periodically review the discussion and provide balanced rulings
92
- 2. Identify areas of agreement and unresolved tensions
93
- 3. Evaluate the strength of arguments from different perspectives
94
- 4. Highlight the most compelling insights and critical flaws
95
- 5. Suggest pathways toward resolution or further inquiry
96
- 6. Deliver rulings with clear justification and constructive guidance
97
- 7. Maintain objectivity while acknowledging valid points from all sides
98
- 8. Consider ethical implications and practical feasibility"""
99
-
100
- # === GLOBAL STATE ===
101
- conversation = []
102
- turn_count = 0
103
- auto_mode = False
104
- current_topic = ""
105
- last_ruling_turn = 0
106
- agent_params = {
107
- "Initiator": {"creativity": 0.7, "criticality": 0.5},
108
- "Responder": {"creativity": 0.5, "criticality": 0.8},
109
- "Guardian": {"creativity": 0.6, "criticality": 0.9},
110
- "Provocateur": {"creativity": 0.9, "criticality": 0.7},
111
- "Cultural": {"creativity": 0.7, "criticality": 0.6},
112
- "Judge": {"creativity": 0.4, "criticality": 0.9}
113
  }
114
- # === FREE CHAT COMPLETION API ===
115
- def safe_chat_completion(system, messages, temperature=0.7):
116
- """Use free Hugging Face Inference API"""
117
- try:
118
- # Format messages for Hugging Face API
119
- formatted = [{"role": "system", "content": system}]
120
- formatted.extend(messages)
121
-
122
- # Prepare payload
123
- payload = {
124
- "inputs": formatted,
125
- "parameters": {
126
- "max_new_tokens": 300,
127
- "temperature": temperature,
128
- "return_full_text": False
129
- }
130
- }
131
-
132
- headers = {"Authorization": f"Bearer {HF_API_TOKEN}"} if HF_API_TOKEN else {}
133
-
134
- response = requests.post(
135
- f"https://api-inference.huggingface.co/models/{CHAT_MODEL}",
136
- json=payload,
137
- headers=headers,
138
- timeout=60
139
- )
140
-
141
- if response.status_code == 200:
142
- return response.json()[0]['generated_text'].strip()
143
- elif response.status_code == 503: # Model loading
144
- time.sleep(15)
145
- return safe_chat_completion(system, messages, temperature)
146
- else:
147
- return f"⚠️ API Error: {response.text}"
148
-
149
- except Exception as e:
150
- return f"⚠️ System Error: {str(e)}"
151
-
152
- # === MEMORY MANAGEMENT ===
153
- def embed_and_store(text, agent=None):
154
- try:
155
- vec = get_embedding(text)
156
- memory_index.add(np.array([vec], dtype='float32'))
157
- memory_data.append({
158
- "text": text,
159
- "timestamp": datetime.now().isoformat(),
160
- "agent": agent or "system",
161
- "topic": current_topic
162
- })
163
- if len(memory_data) % 5 == 0:
164
- with open(MEMORY_FILE, "wb") as f:
165
- pickle.dump(memory_data, f)
166
- faiss.write_index(memory_index, INDEX_FILE)
167
- except Exception as e:
168
- print(f"Memory Error: {str(e)}")
169
-
170
- def retrieve_relevant_memory(query, k=3):
171
- """Retrieve relevant past discussions"""
172
- try:
173
- query_embedding = get_embedding(query)
174
- distances, indices = memory_index.search(np.array([query_embedding], dtype='float32'), k)
175
-
176
- relevant = []
177
- for i, idx in enumerate(indices[0]):
178
- if idx < len(memory_data) and idx >= 0:
179
- relevant.append({
180
- "text": memory_data[idx]['text'][:200] + "...",
181
- "topic": memory_data[idx].get('topic', 'Unknown'),
182
- "agent": memory_data[idx].get('agent', 'Unknown'),
183
- "similarity": 1 - distances[0][i] # Convert distance to similarity
184
- })
185
- return relevant
186
- except Exception as e:
187
- print(f"Memory retrieval error: {str(e)}")
188
- return []
189
-
190
- # ... [Previous code remains unchanged] ...
191
- # ... [Imports and constants remain unchanged] ...
192
-
193
- # === FUNCTION DEFINITIONS ===
194
- def overseer_respond(question, conversation, current_topic):
195
- """Get response from Depth Guardian"""
196
- context = f"Current Topic: {current_topic}\n\n" if current_topic else ""
197
- context += "Conversation History:\n"
198
- for msg in conversation[-5:]:
199
- context += f"- {msg['agent']}: {msg['text']}\n"
200
-
201
- response = safe_chat_completion(
202
- system=OVERSEER_PROMPT,
203
- messages=[{"role": "user", "content": f"{context}\nQuestion: {question}"}],
204
- temperature=0.8
205
- )
206
- embed_and_store(response, "Guardian", current_topic)
207
- return response
208
-
209
- def ask_judge(question, conversation, current_topic):
210
- """Get ruling from Judge"""
211
- context = f"Topic: {current_topic}\n\n" if current_topic else ""
212
- context += "Recent Discussion:\n"
213
- for msg in conversation[-5:]:
214
- context += f"- {msg['agent']}: {msg['text']}\n"
215
-
216
- response = safe_chat_completion(
217
- system=JUDGE_PROMPT,
218
- messages=[{"role": "user", "content": f"{context}\nSpecific Question: {question}"}],
219
- temperature=0.6
220
- )
221
- embed_and_store(response, "Judge", current_topic)
222
- return response
223
 
224
- def step(topic_input, conversation, turn_count, current_topic, last_ruling_turn, agent_params):
225
- """Advance the discussion by one turn"""
226
- # Set topic on first turn
227
- if turn_count == 0:
228
- if topic_input.strip():
229
- current_topic = topic_input.strip()
230
- else:
231
- current_topic = "Ethical Implications of Advanced AI Systems"
232
-
233
- # Determine which agent speaks
234
- agent_sequence = ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural"]
235
- agent_index = turn_count % len(agent_sequence)
236
- agent_name = agent_sequence[agent_index]
237
-
238
- # Special handling for Judge
239
- judge_interval = 5
240
- if turn_count - last_ruling_turn >= judge_interval and turn_count > 0:
241
- agent_name = "Judge"
242
-
243
- # Get system prompt and temperature
244
- prompts = {
245
- "Initiator": AGENT_A_PROMPT,
246
- "Responder": AGENT_B_PROMPT,
247
- "Guardian": OVERSEER_PROMPT,
248
- "Provocateur": OUTSIDER_PROMPT,
249
- "Cultural": CULTURAL_LENS_PROMPT,
250
- "Judge": JUDGE_PROMPT
251
- }
252
- temperature = agent_params[agent_name]["creativity"]
253
-
254
- # Prepare context
255
- context = f"Current Topic: {current_topic}\n\nDiscussion History:\n"
256
- for msg in conversation[-5:]:
257
- context += f"{msg['agent']}: {msg['text']}\n\n"
258
-
259
- # Generate response
260
- response = safe_chat_completion(
261
- system=prompts[agent_name],
262
- messages=[{"role": "user", "content": context}],
263
- temperature=temperature
264
- )
265
-
266
- # Create message entry
267
- new_entry = {
268
- "agent": agent_name,
269
- "text": response,
270
- "turn": turn_count + 1
271
- }
272
-
273
- # Update state
274
- updated_conversation = conversation + [new_entry]
275
- new_turn_count = turn_count + 1
276
- new_last_ruling_turn = new_turn_count if agent_name == "Judge" else last_ruling_turn
277
-
278
- # Update memory
279
- embed_and_store(response, agent_name, current_topic)
280
-
281
- # Format HTML output
282
- html_output = format_conversation_html(updated_conversation)
283
-
284
- # Get agent-specific displays
285
- intervention = get_last_by_agent(updated_conversation, "Guardian")
286
- outsider = get_last_by_agent(updated_conversation, "Provocateur")
287
- cultural = get_last_by_agent(updated_conversation, "Cultural")
288
- judge = get_last_by_agent(updated_conversation, "Judge")
289
-
290
- # Prepare agent status
291
- active_agents = " | ".join([f"{agent}: {entry['text'][:30]}..." for agent, entry in zip(
292
- ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"],
293
- [new_entry] * 6 # Simplified for demo
294
- )])
295
-
296
- return (
297
- html_output,
298
- intervention,
299
- outsider,
300
- cultural,
301
- judge,
302
- current_topic,
303
- new_turn_count,
304
- active_agents,
305
- updated_conversation,
306
- new_turn_count,
307
- current_topic,
308
- new_last_ruling_turn,
309
- agent_params
310
- )
311
 
312
- def get_last_by_agent(conversation, agent_name):
313
- """Get last message from specific agent"""
314
- for msg in reversed(conversation):
315
- if msg["agent"] == agent_name:
316
- return msg["text"]
317
- return "No message yet"
318
 
319
- def format_conversation_html(conversation):
320
- """Format conversation as HTML"""
321
- html = "<div class='convo-container'>"
322
- for msg in conversation:
323
- agent = msg["agent"]
324
- color_map = {
325
- "Initiator": "#e6f7ff",
326
- "Responder": "#f6ffed",
327
- "Guardian": "#fff7e6",
328
- "Provocateur": "#f9e6ff",
329
- "Cultural": "#e6ffed",
330
- "Judge": "#f0f0f0",
331
- "User": "#f0f0f0"
332
  }
333
- color = color_map.get(agent, "#ffffff")
334
- html += f"""
335
- <div style='background:{color}; padding:10px; margin:10px; border-radius:5px;'>
336
- <b>{agent}:</b> {msg['text']}
337
- </div>
338
- """
339
- html += "</div>"
340
- return html
341
-
342
- def toggle_auto(auto_mode):
343
- """Toggle auto-advance mode"""
344
- new_mode = not auto_mode
345
- return ("🟢 Auto: ON" if new_mode else "🔴 Auto: OFF", new_mode)
346
-
347
- def clear_convo():
348
- """Reset conversation"""
349
- return (
350
- format_conversation_html([]),
351
- "",
352
- "",
353
- "",
354
- "",
355
- "",
356
- 0,
357
- "💡 Initiator, 🔍 Responder",
358
- [],
359
- 0,
360
- "",
361
- 0,
362
- "",
363
- ""
364
- )
365
-
366
- def new_topic(conversation, turn_count, current_topic, last_ruling_turn):
367
- """Generate a new discussion topic"""
368
- topics = [
369
- "The Ethics of Genetic Engineering in Humans",
370
- "Universal Basic Income in the Age of Automation",
371
- "Cultural Impacts of Global AI Deployment",
372
- "Privacy vs Security in Digital Societies",
373
- "The Future of Human-AI Collaboration"
374
- ]
375
- new_topic = np.random.choice(topics)
376
- return (
377
- format_conversation_html([]),
378
- new_topic,
379
- 0,
380
- [],
381
- 0,
382
- new_topic,
383
- 0
384
- )
385
 
386
- def request_ruling(conversation, current_topic, turn_count, last_ruling_turn):
387
- """Request a ruling from the Judge"""
388
- context = f"Topic: {current_topic}\n\nDiscussion Summary:\n"
389
- for msg in conversation[-5:]:
390
- context += f"- {msg['agent']}: {msg['text']}\n"
391
-
392
- response = safe_chat_completion(
393
- system=JUDGE_PROMPT,
394
- messages=[{"role": "user", "content": f"{context}\nPlease provide a comprehensive ruling."}],
395
- temperature=0.5
396
- )
397
-
398
- new_entry = {
399
- "agent": "Judge",
400
- "text": response,
401
- "turn": turn_count
402
- }
403
- updated_conversation = conversation + [new_entry]
404
- new_last_ruling_turn = turn_count
405
- return response, updated_conversation, new_last_ruling_turn
406
 
407
- def run_analysis(conversation):
408
- """Run basic analysis (simplified for free version)"""
409
- # Sentiment analysis placeholder
410
- sentiments = ["Positive", "Neutral", "Negative"]
411
- sentiment_result = np.random.choice(sentiments, p=[0.4, 0.4, 0.2])
412
-
413
- # Topic extraction placeholder
414
- topics = ["AI Ethics", "Policy", "Cultural Impact", "Technology", "Future Scenarios"]
415
- topic_result = ", ".join(np.random.choice(topics, 3, replace=False))
416
-
417
- # Agent participation plot
418
- agents = [msg["agent"] for msg in conversation]
419
- if agents:
420
- agent_counts = {agent: agents.count(agent) for agent in set(agents)}
421
- plt.figure(figsize=(8, 4))
422
- plt.bar(agent_counts.keys(), agent_counts.values())
423
- plt.title("Agent Participation")
424
- plt.ylabel("Number of Messages")
425
- plt.tight_layout()
426
- plt.savefig("agent_plot.png")
427
- plot_path = "agent_plot.png"
428
- else:
429
- plot_path = None
430
-
431
- return (
432
- f"Overall Sentiment: {sentiment_result}",
433
- f"Key Topics: {topic_result}",
434
- plot_path
435
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
 
437
- def generate_knowledge_graph(conversation):
438
- """Generate a simple knowledge graph (placeholder)"""
439
- G = nx.DiGraph()
440
- entities = ["AI", "Ethics", "Society", "Technology", "Future"]
441
- for i, e1 in enumerate(entities):
442
- for j, e2 in enumerate(entities):
443
- if i != j and np.random.random() > 0.7:
444
- G.add_edge(e1, e2, weight=np.random.random())
445
-
446
- plt.figure(figsize=(10, 8))
447
- pos = nx.spring_layout(G)
448
- nx.draw(G, pos, with_labels=True, node_size=2000,
449
- node_color="skyblue", font_size=10,
450
- edge_color="gray", width=1.5)
451
- plt.title("Knowledge Graph")
452
- plt.savefig("knowledge_graph.png")
453
- return "knowledge_graph.png"
454
 
455
- def export_handler(format_radio, conversation, current_topic, turn_count):
456
- """Export conversation in various formats"""
457
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
458
-
459
- if format_radio == "txt":
460
- filename = f"discussion_{timestamp}.txt"
461
- with open(filename, "w") as f:
462
- f.write(f"Topic: {current_topic}\nTurns: {turn_count}\n\n")
463
- for msg in conversation:
464
- f.write(f"{msg['agent']} (Turn {msg.get('turn', 'N/A')}):\n{msg['text']}\n\n")
465
- return filename
466
-
467
- elif format_radio == "pdf":
468
- filename = f"discussion_{timestamp}.pdf"
469
- doc = SimpleDocTemplate(filename, pagesize=letter)
470
- styles = getSampleStyleSheet()
471
- story = []
472
-
473
- story.append(Paragraph(f"Discussion: {current_topic}", styles["Title"]))
474
- story.append(Paragraph(f"Turns: {turn_count}", styles["Normal"]))
475
- story.append(Spacer(1, 12))
476
-
477
- for msg in conversation:
478
- agent_text = f"<b>{msg['agent']}</b> (Turn {msg.get('turn', 'N/A')}):"
479
- story.append(Paragraph(agent_text, styles["Normal"]))
480
- story.append(Paragraph(msg["text"], styles["BodyText"]))
481
- story.append(Spacer(1, 12))
482
-
483
- doc.build(story)
484
- return filename
485
-
486
- elif format_radio == "json":
487
- filename = f"discussion_{timestamp}.json"
488
- data = {
489
- "topic": current_topic,
490
- "turns": turn_count,
491
- "conversation": conversation
492
- }
493
- with open(filename, "w") as f:
494
- json.dump(data, f, indent=2)
495
- return filename
496
-
497
- return "export_error.txt"
498
 
499
- def send_to_webhook(webhook_url, conversation, current_topic, turn_count):
500
- """Send conversation to webhook"""
501
- if not webhook_url.startswith("http"):
502
- return "⚠️ Invalid URL"
503
-
504
- payload = {
505
- "topic": current_topic,
506
- "turns": turn_count,
507
- "conversation": conversation
508
- }
509
-
510
- try:
511
- response = requests.post(webhook_url, json=payload, timeout=10)
512
- if response.status_code == 200:
513
- return "✅ Sent successfully!"
514
- return f"⚠️ Error: {response.status_code} - {response.text}"
515
- except Exception as e:
516
- return f"⚠️ Connection error: {str(e)}"
517
 
518
- def add_user_contribution(user_input, conversation):
519
- """Add user contribution to conversation"""
520
- if not user_input.strip():
521
- return format_conversation_html(conversation), "Please enter a message", conversation
522
-
523
- new_entry = {
524
- "agent": "User",
525
- "text": user_input,
526
- "turn": len(conversation) + 1
527
- }
528
- updated_conversation = conversation + [new_entry]
529
- embed_and_store(user_input, "User", current_topic="")
530
- return format_conversation_html(updated_conversation), "✅ Added your contribution!", updated_conversation
531
 
532
- def update_agent_params(*args):
533
- """Update agent parameters from sliders"""
534
- # Last argument is the current params state
535
- current_params = args[-1]
536
- sliders = args[:-1]
537
-
538
- # Map sliders to agent parameters
539
- agents = ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"]
540
- params = ["creativity", "criticality"]
541
-
542
- updated_params = {}
543
- slider_index = 0
544
- for agent in agents:
545
- updated_params[agent] = {}
546
- for param in params:
547
- updated_params[agent][param] = sliders[slider_index]
548
- slider_index += 1
549
-
550
- return updated_params
551
 
552
- # === GRADIO UI SETUP ===
553
- # ... [The entire Gradio UI block remains unchanged from the previous implementation] ...
554
- # This includes the UI layout, components, and event handlers
555
- # === GRADIO UI ===
556
- with gr.Blocks(theme=gr.themes.Soft(), title="DeepSeek Discussion Platform") as demo:
557
- gr.Markdown("# 🧠 Hexa-Agent Discussion System (Free Version)")
558
- gr.Markdown("### Powered by Open-Source Models")
559
-
560
- # State variables
561
- conversation_state = gr.State([])
562
- turn_count_state = gr.State(0)
563
- current_topic_state = gr.State("")
564
- last_ruling_turn_state = gr.State(0)
565
- auto_mode_state = gr.State(False)
566
- agent_params_state = gr.State(agent_params)
567
-
568
- # Status panel
569
- with gr.Row():
570
- turn_counter = gr.Number(label="Turn Count", value=0, interactive=False)
571
- topic_display = gr.Textbox(label="Current Topic", interactive=False, lines=2)
572
- agent_status = gr.Textbox(label="Active Agents", value="💡 Initiator, 🔍 Responder", interactive=False)
573
-
574
- # Tabbed interface
575
- with gr.Tab("Live Discussion"):
576
- convo_display = gr.HTML(
577
- value="<div class='convo-container'>Discussion will appear here</div>",
578
- elem_id="convo-display"
579
- )
580
-
581
- # Placeholder displays for agent-specific content
582
- intervention_display = gr.Textbox(label="Depth Guardian Intervention", visible=False)
583
- outsider_display = gr.Textbox(label="Cross-Disciplinary Provocateur", visible=False)
584
- cultural_display = gr.Textbox(label="Cultural Perspective", visible=False)
585
- judge_display = gr.Textbox(label="Judge's Ruling", visible=False)
586
-
587
- with gr.Row():
588
- step_btn = gr.Button("▶️ Next Turn", variant="primary")
589
- auto_btn = gr.Button("🔴 Auto: OFF", variant="secondary")
590
- clear_btn = gr.Button("🔄 New Discussion", variant="stop")
591
- topic_btn = gr.Button("🎲 Random Topic", variant="secondary")
592
- ruling_btn = gr.Button("⚖️ Request Ruling", variant="primary")
593
-
594
- with gr.Accordion("💬 Guide the Discussion", open=False):
595
- topic_input = gr.Textbox(label="Set Custom Topic", placeholder="e.g., Ethics of AGI in cultural contexts...")
596
- with gr.Row():
597
- qbox = gr.Textbox(label="Ask the Depth Guardian", placeholder="What perspectives are missing?")
598
- ruling_qbox = gr.Textbox(label="Specific Question for Judge", placeholder="What should be our guiding principle?")
599
- with gr.Row():
600
- overseer_out = gr.Textbox(label="Depth Guardian Response", interactive=False)
601
- judge_out = gr.Textbox(label="Judge's Response", interactive=False)
602
- submit_btn = gr.Button("💬 Add User Contribution", variant="primary")
603
- user_input = gr.Textbox(label="Your Contribution", placeholder="Add your perspective to the discussion...")
604
- user_feedback = gr.Textbox(label="Feedback", interactive=False, visible=False)
605
-
606
- # Analysis tab
607
- with gr.Tab("Analysis"):
608
- with gr.Row():
609
- sentiment_display = gr.Textbox(label="Sentiment Analysis", interactive=False)
610
- topics_display = gr.Textbox(label="Key Topics", interactive=False)
611
- agent_plot = gr.Image(label="Agent Participation")
612
- graph_display = gr.Image(label="Knowledge Graph")
613
- analysis_btn = gr.Button("��� Run Analysis", variant="primary")
614
- graph_btn = gr.Button("🌐 Generate Knowledge Graph", variant="secondary")
615
-
616
- # Export tab
617
- with gr.Tab("Export"):
618
- format_radio = gr.Radio(
619
- choices=["txt", "pdf", "json"],
620
- label="Export Format",
621
- value="txt"
622
- )
623
- export_btn = gr.Button("💾 Export Discussion", variant="primary")
624
- export_result = gr.File(label="Export Result", interactive=False)
625
-
626
- gr.Markdown("### Webhook Integration")
627
- webhook_url = gr.Textbox(label="Webhook URL", placeholder="https://your-webhook-endpoint.com")
628
- integrate_btn = gr.Button("🔌 Send to Webhook", variant="secondary")
629
- integration_status = gr.Textbox(label="Status", interactive=False)
630
-
631
- # Agent Configuration tab
632
- with gr.Tab("Configuration"):
633
- gr.Markdown("### Agent Parameters")
634
- agent_sliders = {}
635
- agents = ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"]
636
- params = ["creativity", "criticality"]
637
-
638
- for agent in agents:
639
- with gr.Accordion(f"{agent} Settings", open=False):
640
- for param in params:
641
- slider = gr.Slider(
642
- minimum=0.0,
643
- maximum=1.0,
644
- step=0.05,
645
- label=f"{agent} {param.capitalize()}",
646
- value=agent_params[agent][param]
647
- )
648
- agent_sliders[f"{agent}_{param}"] = slider
649
-
650
- # Custom CSS
651
- demo.css = """
652
- .convo-container {
653
- max-height: 400px;
654
- overflow-y: auto;
655
- padding: 15px;
656
- border: 1px solid #e0e0e0;
657
- border-radius: 8px;
658
- background-color: #f9f9f9;
659
- line-height: 1.6;
660
- }
661
- .convo-container p {
662
- margin-bottom: 10px;
663
- }
664
- #topic-display {
665
- font-weight: bold;
666
- font-size: 1.1em;
667
- }
668
- .free-model-notice {
669
- background-color: #e6f7ff;
670
- padding: 10px;
671
- border-radius: 5px;
672
- margin-bottom: 15px;
673
- border-left: 4px solid #1890ff;
674
- }
675
- """
676
-
677
- # Free model notice
678
- gr.Markdown("""
679
- <div class="free-model-notice">
680
- <b>Using Free Models:</b> This version uses open-source models from Hugging Face.
681
- Responses may be slower and less refined than commercial APIs.
682
- Consider using local GPU for better performance.
683
- </div>
684
- """)
685
-
686
- # Event handlers with proper state management
687
- qbox.submit(
688
- overseer_respond,
689
- inputs=[qbox, conversation_state, current_topic_state],
690
- outputs=[overseer_out]
691
- )
692
-
693
- ruling_qbox.submit(
694
- ask_judge,
695
- inputs=[ruling_qbox, conversation_state, current_topic_state],
696
- outputs=[judge_out]
697
- )
698
-
699
- step_btn.click(
700
- step,
701
- inputs=[
702
- topic_input,
703
- conversation_state,
704
- turn_count_state,
705
- current_topic_state,
706
- last_ruling_turn_state,
707
- agent_params_state
708
- ],
709
- outputs=[
710
- convo_display,
711
- intervention_display,
712
- outsider_display,
713
- cultural_display,
714
- judge_display,
715
- topic_display,
716
- turn_counter,
717
- agent_status,
718
- conversation_state,
719
- turn_count_state,
720
- current_topic_state,
721
- last_ruling_turn_state,
722
- agent_params_state
723
- ]
724
- )
725
-
726
- auto_btn.click(
727
- toggle_auto,
728
- inputs=[auto_mode_state],
729
- outputs=[auto_btn, auto_mode_state]
730
- )
731
-
732
- clear_btn.click(
733
- clear_convo,
734
- outputs=[
735
- convo_display,
736
- intervention_display,
737
- outsider_display,
738
- cultural_display,
739
- judge_display,
740
- topic_display,
741
- turn_counter,
742
- agent_status,
743
- conversation_state,
744
- turn_count_state,
745
- current_topic_state,
746
- last_ruling_turn_state,
747
- overseer_out,
748
- judge_out,
749
- agent_params_state
750
- ]
751
- )
752
-
753
- topic_btn.click(
754
- new_topic,
755
- inputs=[conversation_state, turn_count_state, current_topic_state, last_ruling_turn_state],
756
- outputs=[
757
- convo_display,
758
- topic_display,
759
- turn_counter,
760
- conversation_state,
761
- turn_count_state,
762
- current_topic_state,
763
- last_ruling_turn_state
764
- ]
765
- )
766
-
767
- ruling_btn.click(
768
- request_ruling,
769
- inputs=[conversation_state, current_topic_state, turn_count_state, last_ruling_turn_state],
770
- outputs=[judge_display, conversation_state, last_ruling_turn_state]
771
- )
772
-
773
- analysis_btn.click(
774
- run_analysis,
775
- inputs=[conversation_state],
776
- outputs=[sentiment_display, topics_display, agent_plot]
777
- )
778
-
779
- graph_btn.click(
780
- generate_knowledge_graph,
781
- inputs=[conversation_state],
782
- outputs=[graph_display]
783
- )
784
-
785
- export_btn.click(
786
- export_handler,
787
- inputs=[format_radio, conversation_state, current_topic_state, turn_count_state],
788
- outputs=[export_result]
789
- )
790
-
791
- integrate_btn.click(
792
- send_to_webhook,
793
- inputs=[webhook_url, conversation_state, current_topic_state, turn_count_state],
794
- outputs=[integration_status]
795
- )
796
-
797
- submit_btn.click(
798
- add_user_contribution,
799
- inputs=[user_input, conversation_state],
800
- outputs=[convo_display, user_feedback, conversation_state]
801
- )
802
-
803
- # Create input list for slider change events
804
- slider_inputs = [agent_sliders[f"{agent}_{param}"]
805
- for agent in agents
806
- for param in params]
807
-
808
- for slider in slider_inputs:
809
- slider.change(
810
- update_agent_params,
811
- inputs=slider_inputs + [agent_params_state],
812
- outputs=[agent_params_state]
813
- )
814
 
815
- demo.launch()
 
 
1
  import gradio as gr
2
+ from memory_manager import embed_and_store, retrieve_relevant
3
+ from agent_engine import step_turn
4
+ from analysis_tools import analyze_sentiment_topics, plot_participation, generate_knowledge_graph
5
+ from exporter import export_txt, export_json, export_pdf, send_webhook
6
+
7
+ # Default agent parameters
8
+ DEFAULT_PARAMS = {
9
+ agent: {"creativity": 0.7, "criticality": 0.7}
10
+ for agent in ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
+ # Agent color mapping
14
+ COLOR_MAP = {
15
+ "Initiator": "#e6f7ff",
16
+ "Responder": "#f6ffed",
17
+ "Guardian": "#fff7e6",
18
+ "Provocateur": "#f9e6ff",
19
+ "Cultural": "#e6ffed",
20
+ "Judge": "#f0f0f0",
21
+ "System": "#d9d9d9",
22
+ "User": "#ffffff"
23
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
 
 
 
 
 
 
25
 
26
+ def main():
27
+ with gr.Blocks(css="""
28
+ .convo-container {
29
+ max-height: 400px;
30
+ overflow-y: auto;
31
+ padding: 10px;
32
+ border: 1px solid #ccc;
33
+ border-radius: 8px;
34
+ background: #fafafa;
 
 
 
 
35
  }
36
+ .message-card {
37
+ padding: 8px;
38
+ margin-bottom: 6px;
39
+ border-radius: 6px;
40
+ }
41
+ .agent-panel {
42
+ border: 1px solid #ddd;
43
+ padding: 6px;
44
+ border-radius: 4px;
45
+ margin: 4px;
46
+ }
47
+ """, title="Hexa-Agent Discussion System") as demo:
48
+ # States
49
+ conversation_state = gr.State([])
50
+ turn_state = gr.State(0)
51
+ topic_state = gr.State("")
52
+ params_state = gr.State(DEFAULT_PARAMS)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
+ # Header
55
+ gr.Markdown("# 🧠 Modular Multi-Agent Discussion Platform")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ # Controls
58
+ with gr.Row():
59
+ topic_input = gr.Textbox(label="Topic", placeholder="Enter topic...", value="Ethical AI")
60
+ set_topic_btn = gr.Button("Set Topic")
61
+ clear_btn = gr.Button("Clear Discussion")
62
+ with gr.Row():
63
+ step_btn = gr.Button("▶️ Next Turn")
64
+ gr.Markdown("---")
65
+
66
+ # Conversation display
67
+ convo_display = gr.HTML("<div class='convo-container' id='convo'></div>", label="Conversation")
68
+
69
+ # Agent Panels
70
+ with gr.Accordion("Agent Panels", open=False):
71
+ initiator_panel = gr.Textbox(label="Initiator Latest", interactive=False)
72
+ responder_panel = gr.Textbox(label="Responder Latest", interactive=False)
73
+ guardian_panel = gr.Textbox(label="Guardian Latest", interactive=False)
74
+ provocateur_panel = gr.Textbox(label="Provocateur Latest", interactive=False)
75
+ cultural_panel = gr.Textbox(label="Cultural Latest", interactive=False)
76
+ judge_panel = gr.Textbox(label="Judge Latest", interactive=False)
77
+
78
+ # Analysis Tab
79
+ with gr.Tab("Analysis"):
80
+ sentiment = gr.Textbox(label="Sentiment")
81
+ topics = gr.Textbox(label="Key Topics")
82
+ part_plot = gr.Image(label="Participation Chart")
83
+ graph_plot = gr.Image(label="Knowledge Graph")
84
+ analyze_btn = gr.Button("Run Analysis")
85
+ graph_btn = gr.Button("Generate Graph")
86
+
87
+ # Configuration Tab: Parameter Sliders
88
+ with gr.Tab("Configuration"):
89
+ sliders = {}
90
+ for agent in ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"]:
91
+ with gr.Row():
92
+ sliders[f"{agent}_creativity"] = gr.Slider(0.0, 1.0, value=DEFAULT_PARAMS[agent]['creativity'], label=f"{agent} Creativity")
93
+ sliders[f"{agent}_criticality"] = gr.Slider(0.0, 1.0, value=DEFAULT_PARAMS[agent]['criticality'], label=f"{agent} Criticality")
94
+
95
+ # Export Tab
96
+ with gr.Tab("Export"):
97
+ fmt = gr.Radio(choices=["txt","json","pdf"], label="Format", value="txt")
98
+ export_btn = gr.Button("Export")
99
+ export_out = gr.File(label="Download")
100
+ webhook_url = gr.Textbox(label="Webhook URL")
101
+ send_btn = gr.Button("Send to Webhook")
102
+ send_status = gr.Textbox(label="Status")
103
+
104
+ # Event handlers
105
+ set_topic_btn.click(lambda t: ([], 0, t), inputs=[topic_input], outputs=[convo_display, turn_state, topic_state])
106
+ clear_btn.click(lambda: ([], 0, ""), outputs=[convo_display, turn_state, topic_state])
107
+
108
+ def on_step(convo, turn, topic, params, *slider_vals):
109
+ # Update params from sliders
110
+ agents = ["Initiator","Responder","Guardian","Provocateur","Cultural","Judge"]
111
+ new_params = {}
112
+ idx = 0
113
+ for agent in agents:
114
+ new_params[agent] = {
115
+ 'creativity': slider_vals[idx],
116
+ 'criticality': slider_vals[idx+1]
117
+ }
118
+ idx += 2
119
+ params = new_params
120
+ if turn == 0 and topic:
121
+ convo = [{"agent":"System","text":f"Topic: {topic}"}]
122
+ convo = step_turn(convo, turn, topic or topic_input.value, params)
123
+ # Build HTML
124
+ html = ''
125
+ for msg in convo:
126
+ color = COLOR_MAP.get(msg['agent'], '#ffffff')
127
+ html += f"<div class='message-card' style='background:{color};'><b>{msg['agent']}:</b> {msg['text']}</div>"
128
+ html += "<script>var c=document.getElementById('convo'); c.scrollTop=c.scrollHeight;</script>"
129
+ # Update panels
130
+ panels = []
131
+ for agent in agents:
132
+ panels.append(next((m['text'] for m in reversed(convo) if m['agent']==agent), ''))
133
+ return (html, convo, turn+1) + tuple(panels) + (params,)
134
+
135
+ # Connect step with sliders
136
+ step_btn.click(
137
+ on_step,
138
+ inputs=[conversation_state, turn_state, topic_state, params_state] + list(sliders.values()),
139
+ outputs=[convo_display, conversation_state, turn_state,
140
+ initiator_panel, responder_panel, guardian_panel,
141
+ provocateur_panel, cultural_panel, judge_panel,
142
+ params_state]
143
+ )
144
 
145
+ analyze_btn.click(
146
+ lambda convo: (
147
+ analyze_sentiment_topics(convo)['sentiment'],
148
+ ", ".join(analyze_sentiment_topics(convo)['topics']),
149
+ plot_participation(convo, 'participation.png')
150
+ ),
151
+ inputs=[conversation_state],
152
+ outputs=[sentiment, topics, part_plot]
153
+ )
 
 
 
 
 
 
 
 
154
 
155
+ graph_btn.click(
156
+ lambda convo: generate_knowledge_graph(convo, 'graph.png'),
157
+ inputs=[conversation_state],
158
+ outputs=[graph_plot]
159
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
+ export_btn.click(
162
+ lambda fmt, convo, topic, turn: {
163
+ 'txt': export_txt(convo, topic, turn),
164
+ 'json': export_json(convo, topic, turn),
165
+ 'pdf': export_pdf(convo, topic, turn)
166
+ }[fmt],
167
+ inputs=[fmt, conversation_state, topic_state, turn_state],
168
+ outputs=[export_out]
169
+ )
 
 
 
 
 
 
 
 
 
170
 
171
+ send_btn.click(send_webhook, inputs=[webhook_url, conversation_state, topic_state, turn_state], outputs=[send_status])
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
+ demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
+ if __name__ == '__main__':
177
+ main()