Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,815 +1,177 @@
|
|
1 |
import gradio as gr
|
2 |
-
import
|
3 |
-
import
|
4 |
-
import
|
5 |
-
import
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
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 |
-
|
225 |
-
|
226 |
-
#
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
#
|
234 |
-
|
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
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
"Provocateur": "#f9e6ff",
|
329 |
-
"Cultural": "#e6ffed",
|
330 |
-
"Judge": "#f0f0f0",
|
331 |
-
"User": "#f0f0f0"
|
332 |
}
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
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 |
-
|
387 |
-
|
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 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
436 |
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
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 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
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 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
|
|
|
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()
|