Spaces:
Sleeping
Sleeping
Rename app.pyv1 to app.py
Browse files- app.pyv1 β app.py +494 -119
app.pyv1 β app.py
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
# app.py -
|
2 |
import gradio as gr
|
3 |
import openai
|
4 |
import threading
|
@@ -9,6 +9,14 @@ import os
|
|
9 |
import pickle
|
10 |
from datetime import datetime
|
11 |
import re
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
# === CONFIG ===
|
14 |
EMBEDDING_MODEL = "text-embedding-3-small"
|
@@ -18,7 +26,9 @@ INDEX_FILE = "memory.index"
|
|
18 |
openai.api_key = os.environ.get("OPENAI_API_KEY")
|
19 |
|
20 |
# === EMBEDDING UTILS ===
|
|
|
21 |
def get_embedding(text, model=EMBEDDING_MODEL):
|
|
|
22 |
text = text.replace("\n", " ")
|
23 |
try:
|
24 |
response = openai.embeddings.create(input=[text], model=model)
|
@@ -41,7 +51,7 @@ try:
|
|
41 |
except:
|
42 |
memory_index = faiss.IndexFlatL2(1536)
|
43 |
|
44 |
-
# === AGENT SYSTEM PROMPTS ===
|
45 |
AGENT_A_PROMPT = """You are the Discussion Initiator. Your role:
|
46 |
1. Introduce complex topics requiring multidisciplinary perspectives
|
47 |
2. Frame debates exploring tensions between values, ethics, and progress
|
@@ -97,31 +107,47 @@ turn_count = 0
|
|
97 |
auto_mode = False
|
98 |
current_topic = ""
|
99 |
last_ruling_turn = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
-
# ===
|
102 |
-
def
|
103 |
-
|
104 |
-
|
105 |
-
full_messages.extend(messages)
|
106 |
-
|
107 |
try:
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
|
126 |
# === MEMORY MANAGEMENT ===
|
127 |
def embed_and_store(text, agent=None):
|
@@ -131,7 +157,8 @@ def embed_and_store(text, agent=None):
|
|
131 |
memory_data.append({
|
132 |
"text": text,
|
133 |
"timestamp": datetime.now().isoformat(),
|
134 |
-
"agent": agent or "system"
|
|
|
135 |
})
|
136 |
if len(memory_data) % 5 == 0:
|
137 |
with open(MEMORY_FILE, "wb") as f:
|
@@ -140,6 +167,26 @@ def embed_and_store(text, agent=None):
|
|
140 |
except Exception as e:
|
141 |
print(f"Memory Error: {str(e)}")
|
142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
# === CONVERSATION UTILITIES ===
|
144 |
def format_convo():
|
145 |
return "\n".join([f"**{m['agent']}**: {m['text']}" for m in conversation])
|
@@ -182,6 +229,13 @@ def detect_superficiality():
|
|
182 |
|
183 |
return superficial_count > depth_count * 2
|
184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
def detect_repetition():
|
186 |
"""Check if recent messages are conceptually similar"""
|
187 |
if len(conversation) < 4:
|
@@ -189,8 +243,12 @@ def detect_repetition():
|
|
189 |
|
190 |
recent = [m['text'] for m in conversation[-4:]]
|
191 |
embeddings = [get_embedding(text) for text in recent]
|
192 |
-
|
193 |
-
|
|
|
|
|
|
|
|
|
194 |
|
195 |
def detect_cultural_relevance():
|
196 |
"""Check if cultural perspectives are needed"""
|
@@ -231,7 +289,7 @@ def detect_judgment_opportunity():
|
|
231 |
# === AGENT FUNCTIONS ===
|
232 |
def generate_topic():
|
233 |
"""Generate a complex discussion topic"""
|
234 |
-
topic =
|
235 |
"Generate a complex discussion topic requiring multidisciplinary and multicultural analysis",
|
236 |
[{"role": "user", "content": "Create a topic addressing tensions between technological progress, ethics, and cultural values"}]
|
237 |
)
|
@@ -241,13 +299,31 @@ def outsider_comment():
|
|
241 |
"""Generate outsider perspective"""
|
242 |
context = "\n".join([f"{m['agent']}: {m['text']}" for m in conversation[-4:]])
|
243 |
prompt = f"Conversation Context:\n{context}\n\nProvide your cross-disciplinary perspective:"
|
244 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
def cultural_perspective():
|
247 |
"""Generate cultural diversity perspective"""
|
248 |
context = "\n".join([f"{m['agent']}: {m['text']}" for m in conversation[-4:]])
|
249 |
prompt = f"Conversation Context:\n{context}\n\nProvide diverse cultural perspectives on this topic:"
|
250 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
|
252 |
def judge_ruling():
|
253 |
"""Generate final judgment or ruling"""
|
@@ -271,7 +347,15 @@ Your ruling should:
|
|
271 |
5. Consider ethical and practical implications
|
272 |
6. Provide constructive guidance for next steps"""
|
273 |
|
274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
last_ruling_turn = turn_count
|
276 |
return ruling
|
277 |
|
@@ -282,29 +366,42 @@ def step(topic_input=""):
|
|
282 |
# Initialize new discussion
|
283 |
if not conversation:
|
284 |
current_topic = topic_input or generate_topic()
|
285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
AGENT_A_PROMPT,
|
287 |
-
[{"role": "user", "content": f"Initiate a deep discussion on: {current_topic}"}]
|
|
|
288 |
)
|
289 |
conversation.append({"agent": "π‘ Initiator", "text": msg})
|
290 |
embed_and_store(msg, "Initiator")
|
291 |
turn_count = 1
|
292 |
last_ruling_turn = 0
|
293 |
-
return format_convo(), "", "", "", "", current_topic
|
294 |
|
295 |
# Critical Responder engages
|
296 |
last_msg = conversation[-1]['text']
|
297 |
-
b_msg =
|
298 |
AGENT_B_PROMPT,
|
299 |
-
[{"role": "user", "content": f"Topic: {current_topic}\n\nLast statement: {last_msg}"}]
|
|
|
300 |
)
|
301 |
conversation.append({"agent": "π Responder", "text": b_msg})
|
302 |
embed_and_store(b_msg, "Responder")
|
303 |
|
304 |
# Initiator counters
|
305 |
-
a_msg =
|
306 |
AGENT_A_PROMPT,
|
307 |
-
[{"role": "user", "content": f"Topic: {current_topic}\n\nCritical response: {b_msg}"}]
|
|
|
308 |
)
|
309 |
conversation.append({"agent": "π‘ Initiator", "text": a_msg})
|
310 |
embed_and_store(a_msg, "Initiator")
|
@@ -314,7 +411,11 @@ def step(topic_input=""):
|
|
314 |
if turn_count % 3 == 0 or detect_repetition() or detect_superficiality():
|
315 |
context = "\n".join([m['text'] for m in conversation[-4:]])
|
316 |
prompt = f"Topic: {current_topic}\n\nDiscussion Context:\n{context}\n\nDeepen the analysis:"
|
317 |
-
intervention =
|
|
|
|
|
|
|
|
|
318 |
conversation.append({"agent": "βοΈ Depth Guardian", "text": intervention})
|
319 |
embed_and_store(intervention, "Overseer")
|
320 |
|
@@ -342,96 +443,281 @@ def step(topic_input=""):
|
|
342 |
embed_and_store(judge_msg, "Judge")
|
343 |
|
344 |
turn_count += 1
|
345 |
-
return format_convo(), intervention, outsider_msg, cultural_msg, judge_msg, current_topic
|
346 |
|
347 |
-
# ===
|
348 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
try:
|
350 |
-
|
351 |
-
|
352 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
except Exception as e:
|
354 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
|
356 |
-
|
357 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
358 |
try:
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
363 |
except Exception as e:
|
364 |
-
return f"
|
365 |
-
|
366 |
-
# === AUTO MODE HANDLER ===
|
367 |
-
def auto_loop():
|
368 |
-
global auto_mode
|
369 |
-
while auto_mode:
|
370 |
-
step()
|
371 |
-
time.sleep(6)
|
372 |
-
|
373 |
-
def toggle_auto():
|
374 |
-
global auto_mode
|
375 |
-
auto_mode = not auto_mode
|
376 |
-
if auto_mode:
|
377 |
-
threading.Thread(target=auto_loop, daemon=True).start()
|
378 |
-
return "π΄ Auto: OFF" if not auto_mode else "π’ Auto: ON"
|
379 |
|
380 |
# === GRADIO UI ===
|
381 |
-
with gr.Blocks(title="
|
382 |
-
gr.Markdown("# π§
|
383 |
-
gr.Markdown("###
|
384 |
|
|
|
385 |
with gr.Row():
|
386 |
-
|
|
|
|
|
387 |
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
)
|
394 |
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
|
402 |
-
with gr.
|
403 |
-
with gr.
|
404 |
-
gr.
|
405 |
-
|
406 |
-
|
407 |
-
gr.
|
408 |
-
|
409 |
-
|
410 |
-
gr.
|
411 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
412 |
|
413 |
-
with gr.
|
414 |
-
|
415 |
-
|
416 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
|
418 |
-
with gr.
|
419 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
with gr.Row():
|
421 |
-
|
422 |
-
|
|
|
|
|
|
|
|
|
|
|
423 |
with gr.Row():
|
424 |
-
|
425 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
426 |
|
427 |
-
# Custom CSS
|
428 |
demo.css = """
|
429 |
-
.convo-
|
430 |
max-height: 400px;
|
431 |
overflow-y: auto;
|
432 |
-
padding:
|
433 |
border: 1px solid #e0e0e0;
|
434 |
-
border-radius:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
435 |
}
|
436 |
"""
|
437 |
|
@@ -441,40 +727,129 @@ with gr.Blocks(title="Advanced Discussion Simulator") as demo:
|
|
441 |
conversation = []
|
442 |
turn_count = 0
|
443 |
current_topic = ""
|
444 |
-
return
|
|
|
|
|
|
|
|
|
445 |
|
446 |
def new_topic():
|
447 |
-
clear_convo()
|
448 |
topic = generate_topic()
|
449 |
-
return
|
450 |
|
451 |
def ask_judge(query):
|
452 |
try:
|
453 |
context = "\n".join([m['text'] for m in conversation[-3:]]) if conversation else "No context"
|
454 |
messages = [{"role": "user", "content": f"Discussion Topic: {current_topic}\n\nRecent context:\n{context}\n\nSpecific Question: {query}"}]
|
455 |
-
return
|
456 |
except Exception as e:
|
457 |
return f"[Judge Error: {str(e)}]"
|
458 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
459 |
step_btn.click(
|
460 |
step,
|
461 |
-
inputs=[
|
462 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
463 |
)
|
464 |
-
qbox.submit(overseer_respond, inputs=qbox, outputs=overseer_out)
|
465 |
-
ruling_qbox.submit(ask_judge, inputs=ruling_qbox, outputs=judge_out)
|
466 |
-
auto_btn.click(toggle_auto, outputs=auto_btn)
|
467 |
clear_btn.click(
|
468 |
clear_convo,
|
469 |
-
outputs=[
|
|
|
|
|
|
|
|
|
470 |
)
|
471 |
topic_btn.click(
|
472 |
new_topic,
|
473 |
-
outputs=[convo_display,
|
474 |
)
|
475 |
ruling_btn.click(
|
476 |
-
|
477 |
outputs=[judge_display]
|
478 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
479 |
|
480 |
demo.launch()
|
|
|
1 |
+
# app.py - DeepSeek Hexa-Agent Discussion Platform
|
2 |
import gradio as gr
|
3 |
import openai
|
4 |
import threading
|
|
|
9 |
import pickle
|
10 |
from datetime import datetime
|
11 |
import re
|
12 |
+
import json
|
13 |
+
import matplotlib.pyplot as plt
|
14 |
+
import networkx as nx
|
15 |
+
from reportlab.lib.pagesizes import letter
|
16 |
+
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
|
17 |
+
from reportlab.lib.styles import getSampleStyleSheet
|
18 |
+
from functools import lru_cache
|
19 |
+
import requests
|
20 |
|
21 |
# === CONFIG ===
|
22 |
EMBEDDING_MODEL = "text-embedding-3-small"
|
|
|
26 |
openai.api_key = os.environ.get("OPENAI_API_KEY")
|
27 |
|
28 |
# === EMBEDDING UTILS ===
|
29 |
+
@lru_cache(maxsize=500)
|
30 |
def get_embedding(text, model=EMBEDDING_MODEL):
|
31 |
+
"""Cached embedding function for performance"""
|
32 |
text = text.replace("\n", " ")
|
33 |
try:
|
34 |
response = openai.embeddings.create(input=[text], model=model)
|
|
|
51 |
except:
|
52 |
memory_index = faiss.IndexFlatL2(1536)
|
53 |
|
54 |
+
# === AGENT SYSTEM PROMPTS (Configurable) ===
|
55 |
AGENT_A_PROMPT = """You are the Discussion Initiator. Your role:
|
56 |
1. Introduce complex topics requiring multidisciplinary perspectives
|
57 |
2. Frame debates exploring tensions between values, ethics, and progress
|
|
|
107 |
auto_mode = False
|
108 |
current_topic = ""
|
109 |
last_ruling_turn = 0
|
110 |
+
agent_params = {
|
111 |
+
"Initiator": {"creativity": 0.7, "criticality": 0.5},
|
112 |
+
"Responder": {"creativity": 0.5, "criticality": 0.8},
|
113 |
+
"Guardian": {"creativity": 0.6, "criticality": 0.9},
|
114 |
+
"Provocateur": {"creativity": 0.9, "criticality": 0.7},
|
115 |
+
"Cultural": {"creativity": 0.7, "criticality": 0.6},
|
116 |
+
"Judge": {"creativity": 0.4, "criticality": 0.9}
|
117 |
+
}
|
118 |
|
119 |
+
# === ERROR-HANDLED API CALLS ===
|
120 |
+
def safe_chat_completion(system, messages, model=CHAT_MODEL, temperature=0.7, max_retries=3):
|
121 |
+
"""Robust API call with exponential backoff"""
|
122 |
+
for attempt in range(max_retries):
|
|
|
|
|
123 |
try:
|
124 |
+
full_messages = [{"role": "system", "content": system}]
|
125 |
+
full_messages.extend(messages)
|
126 |
+
|
127 |
+
try:
|
128 |
+
response = openai.chat.completions.create(
|
129 |
+
model=model,
|
130 |
+
messages=full_messages,
|
131 |
+
temperature=temperature,
|
132 |
+
max_tokens=300
|
133 |
+
)
|
134 |
+
return response.choices[0].message.content.strip()
|
135 |
+
except AttributeError:
|
136 |
+
response = openai.ChatCompletion.create(
|
137 |
+
model=model,
|
138 |
+
messages=full_messages,
|
139 |
+
temperature=temperature,
|
140 |
+
max_tokens=300
|
141 |
+
)
|
142 |
+
return response['choices'][0]['message']['content'].strip()
|
143 |
+
except Exception as e:
|
144 |
+
if attempt < max_retries - 1:
|
145 |
+
wait_time = 2 ** attempt
|
146 |
+
print(f"API error: {e}. Retrying in {wait_time} seconds...")
|
147 |
+
time.sleep(wait_time)
|
148 |
+
else:
|
149 |
+
return f"β οΈ API Error: {str(e)}"
|
150 |
+
return "β οΈ Max retries exceeded"
|
151 |
|
152 |
# === MEMORY MANAGEMENT ===
|
153 |
def embed_and_store(text, agent=None):
|
|
|
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:
|
|
|
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 |
# === CONVERSATION UTILITIES ===
|
191 |
def format_convo():
|
192 |
return "\n".join([f"**{m['agent']}**: {m['text']}" for m in conversation])
|
|
|
229 |
|
230 |
return superficial_count > depth_count * 2
|
231 |
|
232 |
+
def batch_cosine_similarity(embeddings):
|
233 |
+
"""Efficient batch similarity calculation"""
|
234 |
+
norms = np.linalg.norm(embeddings, axis=1)
|
235 |
+
dot_matrix = np.dot(embeddings, embeddings.T)
|
236 |
+
norm_matrix = np.outer(norms, norms)
|
237 |
+
return dot_matrix / norm_matrix
|
238 |
+
|
239 |
def detect_repetition():
|
240 |
"""Check if recent messages are conceptually similar"""
|
241 |
if len(conversation) < 4:
|
|
|
243 |
|
244 |
recent = [m['text'] for m in conversation[-4:]]
|
245 |
embeddings = [get_embedding(text) for text in recent]
|
246 |
+
|
247 |
+
# Use batch processing for efficiency
|
248 |
+
similarity_matrix = batch_cosine_similarity(np.array(embeddings))
|
249 |
+
|
250 |
+
# Check similarity between current and previous messages
|
251 |
+
return any(similarity_matrix[-1][i] > 0.82 for i in range(len(embeddings)-1))
|
252 |
|
253 |
def detect_cultural_relevance():
|
254 |
"""Check if cultural perspectives are needed"""
|
|
|
289 |
# === AGENT FUNCTIONS ===
|
290 |
def generate_topic():
|
291 |
"""Generate a complex discussion topic"""
|
292 |
+
topic = safe_chat_completion(
|
293 |
"Generate a complex discussion topic requiring multidisciplinary and multicultural analysis",
|
294 |
[{"role": "user", "content": "Create a topic addressing tensions between technological progress, ethics, and cultural values"}]
|
295 |
)
|
|
|
299 |
"""Generate outsider perspective"""
|
300 |
context = "\n".join([f"{m['agent']}: {m['text']}" for m in conversation[-4:]])
|
301 |
prompt = f"Conversation Context:\n{context}\n\nProvide your cross-disciplinary perspective:"
|
302 |
+
|
303 |
+
# Apply agent parameters
|
304 |
+
params = agent_params["Provocateur"]
|
305 |
+
temp = 0.5 + params["creativity"] * 0.5 # Map to 0.5-1.0 range
|
306 |
+
|
307 |
+
return safe_chat_completion(
|
308 |
+
OUTSIDER_PROMPT,
|
309 |
+
[{"role": "user", "content": prompt}],
|
310 |
+
temperature=temp
|
311 |
+
)
|
312 |
|
313 |
def cultural_perspective():
|
314 |
"""Generate cultural diversity perspective"""
|
315 |
context = "\n".join([f"{m['agent']}: {m['text']}" for m in conversation[-4:]])
|
316 |
prompt = f"Conversation Context:\n{context}\n\nProvide diverse cultural perspectives on this topic:"
|
317 |
+
|
318 |
+
# Apply agent parameters
|
319 |
+
params = agent_params["Cultural"]
|
320 |
+
temp = 0.5 + params["creativity"] * 0.5
|
321 |
+
|
322 |
+
return safe_chat_completion(
|
323 |
+
CULTURAL_LENS_PROMPT,
|
324 |
+
[{"role": "user", "content": prompt}],
|
325 |
+
temperature=temp
|
326 |
+
)
|
327 |
|
328 |
def judge_ruling():
|
329 |
"""Generate final judgment or ruling"""
|
|
|
347 |
5. Consider ethical and practical implications
|
348 |
6. Provide constructive guidance for next steps"""
|
349 |
|
350 |
+
# Apply agent parameters
|
351 |
+
params = agent_params["Judge"]
|
352 |
+
temp = 0.3 + params["criticality"] * 0.4 # More critical = lower temperature
|
353 |
+
|
354 |
+
ruling = safe_chat_completion(
|
355 |
+
JUDGE_PROMPT,
|
356 |
+
[{"role": "user", "content": prompt}],
|
357 |
+
temperature=temp
|
358 |
+
)
|
359 |
last_ruling_turn = turn_count
|
360 |
return ruling
|
361 |
|
|
|
366 |
# Initialize new discussion
|
367 |
if not conversation:
|
368 |
current_topic = topic_input or generate_topic()
|
369 |
+
|
370 |
+
# Retrieve relevant memory
|
371 |
+
memory_context = retrieve_relevant_memory(current_topic)
|
372 |
+
context_str = ""
|
373 |
+
if memory_context:
|
374 |
+
context_str = "\n\nRelevant past discussions:\n" + "\n".join(
|
375 |
+
[f"- {item['agent']} on '{item['topic']}': {item['text']}"
|
376 |
+
for item in memory_context]
|
377 |
+
)
|
378 |
+
|
379 |
+
msg = safe_chat_completion(
|
380 |
AGENT_A_PROMPT,
|
381 |
+
[{"role": "user", "content": f"Initiate a deep discussion on: {current_topic}{context_str}"}],
|
382 |
+
temperature=0.5 + agent_params["Initiator"]["creativity"] * 0.5
|
383 |
)
|
384 |
conversation.append({"agent": "π‘ Initiator", "text": msg})
|
385 |
embed_and_store(msg, "Initiator")
|
386 |
turn_count = 1
|
387 |
last_ruling_turn = 0
|
388 |
+
return format_convo(), "", "", "", "", current_topic, turn_count, ""
|
389 |
|
390 |
# Critical Responder engages
|
391 |
last_msg = conversation[-1]['text']
|
392 |
+
b_msg = safe_chat_completion(
|
393 |
AGENT_B_PROMPT,
|
394 |
+
[{"role": "user", "content": f"Topic: {current_topic}\n\nLast statement: {last_msg}"}],
|
395 |
+
temperature=0.4 + agent_params["Responder"]["criticality"] * 0.4
|
396 |
)
|
397 |
conversation.append({"agent": "π Responder", "text": b_msg})
|
398 |
embed_and_store(b_msg, "Responder")
|
399 |
|
400 |
# Initiator counters
|
401 |
+
a_msg = safe_chat_completion(
|
402 |
AGENT_A_PROMPT,
|
403 |
+
[{"role": "user", "content": f"Topic: {current_topic}\n\nCritical response: {b_msg}"}],
|
404 |
+
temperature=0.5 + agent_params["Initiator"]["creativity"] * 0.5
|
405 |
)
|
406 |
conversation.append({"agent": "π‘ Initiator", "text": a_msg})
|
407 |
embed_and_store(a_msg, "Initiator")
|
|
|
411 |
if turn_count % 3 == 0 or detect_repetition() or detect_superficiality():
|
412 |
context = "\n".join([m['text'] for m in conversation[-4:]])
|
413 |
prompt = f"Topic: {current_topic}\n\nDiscussion Context:\n{context}\n\nDeepen the analysis:"
|
414 |
+
intervention = safe_chat_completion(
|
415 |
+
OVERSEER_PROMPT,
|
416 |
+
[{"role": "user", "content": prompt}],
|
417 |
+
temperature=0.5 + agent_params["Guardian"]["criticality"] * 0.4
|
418 |
+
)
|
419 |
conversation.append({"agent": "βοΈ Depth Guardian", "text": intervention})
|
420 |
embed_and_store(intervention, "Overseer")
|
421 |
|
|
|
443 |
embed_and_store(judge_msg, "Judge")
|
444 |
|
445 |
turn_count += 1
|
446 |
+
return format_convo(), intervention, outsider_msg, cultural_msg, judge_msg, current_topic, turn_count, ""
|
447 |
|
448 |
+
# === ANALYSIS & VISUALIZATION ===
|
449 |
+
def analyze_conversation():
|
450 |
+
"""Generate insights about the discussion"""
|
451 |
+
# Count agent contributions
|
452 |
+
agent_counts = {}
|
453 |
+
for msg in conversation:
|
454 |
+
agent = msg['agent'].split()[0] # Remove emoji
|
455 |
+
agent_counts[agent] = agent_counts.get(agent, 0) + 1
|
456 |
+
|
457 |
+
# Sentiment analysis
|
458 |
+
sentiment_prompt = f"Analyze overall sentiment of this discussion:\n{format_convo()}"
|
459 |
+
sentiment = safe_chat_completion(
|
460 |
+
"You are a sentiment analysis expert. Provide a brief assessment of the discussion tone.",
|
461 |
+
[{"role": "user", "content": sentiment_prompt}]
|
462 |
+
)
|
463 |
+
|
464 |
+
# Topic extraction
|
465 |
+
topic_prompt = f"Extract key topics from this discussion:\n{format_convo()}"
|
466 |
+
topics = safe_chat_completion(
|
467 |
+
"You are a topic extraction expert. List the top 5 topics as a JSON array.",
|
468 |
+
[{"role": "user", "content": topic_prompt}]
|
469 |
+
)
|
470 |
+
|
471 |
try:
|
472 |
+
topics = json.loads(topics)
|
473 |
+
except:
|
474 |
+
topics = ["Topic extraction failed"]
|
475 |
+
|
476 |
+
return {
|
477 |
+
"agents": list(agent_counts.keys()),
|
478 |
+
"counts": [agent_counts.get(a, 0) for a in list(agent_counts.keys())],
|
479 |
+
"topics": topics,
|
480 |
+
"sentiment": sentiment
|
481 |
+
}
|
482 |
+
|
483 |
+
def generate_knowledge_graph():
|
484 |
+
"""Create a knowledge graph of discussion concepts"""
|
485 |
+
# Extract entities and relationships
|
486 |
+
extraction_prompt = f"""
|
487 |
+
Analyze this discussion and extract:
|
488 |
+
1. Key concepts (nouns, important terms)
|
489 |
+
2. Relationships between concepts (verb phrases)
|
490 |
+
|
491 |
+
Discussion:
|
492 |
+
{format_convo()}
|
493 |
+
|
494 |
+
Return as JSON: {{"concepts": ["list", "of", "concepts"], "relationships": [["concept1", "relationship", "concept2"]]}}
|
495 |
+
"""
|
496 |
+
|
497 |
+
try:
|
498 |
+
graph_data = safe_chat_completion(
|
499 |
+
"You are a knowledge graph extraction expert.",
|
500 |
+
[{"role": "user", "content": extraction_prompt}]
|
501 |
+
)
|
502 |
+
graph_data = json.loads(graph_data)
|
503 |
+
|
504 |
+
# Create graph visualization
|
505 |
+
G = nx.DiGraph()
|
506 |
+
G.add_nodes_from(graph_data["concepts"])
|
507 |
+
|
508 |
+
for rel in graph_data["relationships"]:
|
509 |
+
if len(rel) == 3:
|
510 |
+
G.add_edge(rel[0], rel[2], label=rel[1])
|
511 |
+
|
512 |
+
plt.figure(figsize=(10, 8))
|
513 |
+
pos = nx.spring_layout(G, seed=42)
|
514 |
+
nx.draw(G, pos, with_labels=True, node_size=2000, node_color="skyblue", font_size=10)
|
515 |
+
edge_labels = nx.get_edge_attributes(G, 'label')
|
516 |
+
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
|
517 |
+
plt.title("Discussion Knowledge Graph")
|
518 |
+
plt.savefig("knowledge_graph.png")
|
519 |
+
return "knowledge_graph.png"
|
520 |
except Exception as e:
|
521 |
+
print(f"Graph error: {str(e)}")
|
522 |
+
return None
|
523 |
+
|
524 |
+
# === EXPORT FUNCTIONS ===
|
525 |
+
def export_pdf_report():
|
526 |
+
"""Generate PDF report of discussion"""
|
527 |
+
filename = f"discussion_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf"
|
528 |
+
doc = SimpleDocTemplate(filename, pagesize=letter)
|
529 |
+
styles = getSampleStyleSheet()
|
530 |
+
story = []
|
531 |
+
|
532 |
+
# Title
|
533 |
+
story.append(Paragraph(f"Discussion Report: {current_topic}", styles['Title']))
|
534 |
+
story.append(Spacer(1, 12))
|
535 |
+
|
536 |
+
# Summary
|
537 |
+
analysis = analyze_conversation()
|
538 |
+
story.append(Paragraph("Discussion Summary", styles['Heading2']))
|
539 |
+
story.append(Paragraph(f"<b>Turn Count:</b> {turn_count}", styles['BodyText']))
|
540 |
+
story.append(Paragraph(f"<b>Sentiment:</b> {analysis['sentiment']}", styles['BodyText']))
|
541 |
+
story.append(Spacer(1, 12))
|
542 |
+
|
543 |
+
# Key Topics
|
544 |
+
story.append(Paragraph("Key Topics", styles['Heading2']))
|
545 |
+
for topic in analysis['topics']:
|
546 |
+
story.append(Paragraph(f"- {topic}", styles['BodyText']))
|
547 |
+
story.append(Spacer(1, 12))
|
548 |
+
|
549 |
+
# Full Conversation
|
550 |
+
story.append(Paragraph("Full Discussion", styles['Heading2']))
|
551 |
+
for msg in conversation:
|
552 |
+
story.append(Paragraph(f"<b>{msg['agent']}:</b> {msg['text']}", styles['BodyText']))
|
553 |
+
story.append(Spacer(1, 6))
|
554 |
+
|
555 |
+
doc.build(story)
|
556 |
+
return filename
|
557 |
+
|
558 |
+
def export_json_data():
|
559 |
+
"""Export conversation as JSON"""
|
560 |
+
filename = f"discussion_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
561 |
+
with open(filename, 'w') as f:
|
562 |
+
json.dump({
|
563 |
+
"topic": current_topic,
|
564 |
+
"turns": turn_count,
|
565 |
+
"conversation": conversation,
|
566 |
+
"analysis": analyze_conversation()
|
567 |
+
}, f, indent=2)
|
568 |
+
return filename
|
569 |
|
570 |
+
def export_text_transcript():
|
571 |
+
"""Export as plain text"""
|
572 |
+
filename = f"transcript_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
|
573 |
+
with open(filename, 'w') as f:
|
574 |
+
f.write(f"Discussion Topic: {current_topic}\n\n")
|
575 |
+
f.write("Participants:\n")
|
576 |
+
agents = set(msg['agent'] for msg in conversation)
|
577 |
+
for agent in agents:
|
578 |
+
f.write(f"- {agent}\n")
|
579 |
+
|
580 |
+
f.write("\nConversation:\n")
|
581 |
+
for msg in conversation:
|
582 |
+
f.write(f"{msg['agent']}: {msg['text']}\n\n")
|
583 |
+
return filename
|
584 |
+
|
585 |
+
# === INTEGRATION FUNCTIONS ===
|
586 |
+
def send_to_webhook(url):
|
587 |
+
"""Send discussion data to external webhook"""
|
588 |
try:
|
589 |
+
payload = {
|
590 |
+
"topic": current_topic,
|
591 |
+
"turns": turn_count,
|
592 |
+
"conversation": conversation,
|
593 |
+
"timestamp": datetime.now().isoformat()
|
594 |
+
}
|
595 |
+
response = requests.post(url, json=payload, timeout=10)
|
596 |
+
if response.status_code == 200:
|
597 |
+
return "β
Data sent successfully!"
|
598 |
+
else:
|
599 |
+
return f"β οΈ Error {response.status_code}: {response.text}"
|
600 |
except Exception as e:
|
601 |
+
return f"β οΈ Connection error: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
602 |
|
603 |
# === GRADIO UI ===
|
604 |
+
with gr.Blocks(theme=gr.themes.Soft(), title="DeepSeek Discussion Platform") as demo:
|
605 |
+
gr.Markdown("# π§ DeepSeek Hexa-Agent Discussion System")
|
606 |
+
gr.Markdown("### AI-Powered Complex Discourse Analysis")
|
607 |
|
608 |
+
# Status panel
|
609 |
with gr.Row():
|
610 |
+
turn_counter = gr.Number(label="Turn Count", value=0, interactive=False)
|
611 |
+
topic_display = gr.Textbox(label="Current Topic", interactive=False, lines=2)
|
612 |
+
agent_status = gr.Textbox(label="Active Agents", value="π‘ Initiator, π Responder", interactive=False)
|
613 |
|
614 |
+
# Tabbed interface
|
615 |
+
with gr.Tab("Live Discussion"):
|
616 |
+
convo_display = gr.HTML(
|
617 |
+
value="<div class='convo-container'>Discussion will appear here</div>",
|
618 |
+
elem_id="convo-display"
|
619 |
)
|
620 |
|
621 |
+
with gr.Row():
|
622 |
+
step_btn = gr.Button("βΆοΈ Next Turn", variant="primary")
|
623 |
+
auto_btn = gr.Button("π΄ Auto: OFF", variant="secondary")
|
624 |
+
clear_btn = gr.Button("π New Discussion", variant="stop")
|
625 |
+
topic_btn = gr.Button("π² Random Topic", variant="secondary")
|
626 |
+
ruling_btn = gr.Button("βοΈ Request Ruling", variant="primary")
|
627 |
|
628 |
+
with gr.Tab("Agent Perspectives"):
|
629 |
+
with gr.Row():
|
630 |
+
with gr.Column(scale=1):
|
631 |
+
gr.Markdown("### βοΈ Depth Guardian")
|
632 |
+
intervention_display = gr.Textbox(label="", interactive=False)
|
633 |
+
with gr.Column(scale=1):
|
634 |
+
gr.Markdown("### π Cross-Disciplinary")
|
635 |
+
outsider_display = gr.Textbox(label="", interactive=False)
|
636 |
+
with gr.Column(scale=1):
|
637 |
+
gr.Markdown("### π Cultural Lens")
|
638 |
+
cultural_display = gr.Textbox(label="", interactive=False)
|
639 |
+
|
640 |
+
with gr.Row():
|
641 |
+
with gr.Column(scale=3):
|
642 |
+
gr.Markdown("### βοΈ Final Judgment")
|
643 |
+
judge_display = gr.Textbox(label="", interactive=False, lines=4)
|
644 |
|
645 |
+
with gr.Tab("Analysis Dashboard"):
|
646 |
+
gr.Markdown("### Conversation Insights")
|
647 |
+
with gr.Row():
|
648 |
+
sentiment_display = gr.Textbox(label="Discussion Sentiment", interactive=False)
|
649 |
+
topics_display = gr.JSON(label="Key Topics")
|
650 |
+
|
651 |
+
with gr.Row():
|
652 |
+
agent_plot = gr.Plot(label="Agent Participation")
|
653 |
+
analysis_btn = gr.Button("Generate Insights", variant="primary")
|
654 |
+
|
655 |
+
with gr.Row():
|
656 |
+
gr.Markdown("### Knowledge Graph")
|
657 |
+
graph_btn = gr.Button("Generate Knowledge Graph", variant="secondary")
|
658 |
+
graph_display = gr.Image(label="Concept Relationships", interactive=False)
|
659 |
+
|
660 |
+
with gr.Tab("Collaboration"):
|
661 |
+
gr.Markdown("### Real-Time Collaboration")
|
662 |
+
with gr.Row():
|
663 |
+
user_input = gr.Textbox(label="Your Contribution", placeholder="Add your perspective...")
|
664 |
+
submit_btn = gr.Button("Add to Discussion")
|
665 |
+
|
666 |
+
with gr.Row():
|
667 |
+
voting_btn = gr.Button("π Vote for Current Direction")
|
668 |
+
flag_btn = gr.Button("π© Flag Issue")
|
669 |
+
|
670 |
+
with gr.Row():
|
671 |
+
user_feedback = gr.Textbox(label="Community Feedback", interactive=False)
|
672 |
|
673 |
+
with gr.Tab("Export & Integrate"):
|
674 |
+
with gr.Row():
|
675 |
+
format_radio = gr.Radio(
|
676 |
+
["PDF Report", "JSON Data", "Text Transcript"],
|
677 |
+
label="Export Format",
|
678 |
+
value="PDF Report"
|
679 |
+
)
|
680 |
+
export_btn = gr.Button("Export Discussion", variant="primary")
|
681 |
+
export_result = gr.File(label="Download File")
|
682 |
+
|
683 |
with gr.Row():
|
684 |
+
gr.Markdown("### API Integration")
|
685 |
+
webhook_url = gr.Textbox(label="Webhook URL", placeholder="https://your-platform.com/webhook")
|
686 |
+
integrate_btn = gr.Button("Connect to External Platform", variant="secondary")
|
687 |
+
integration_status = gr.Textbox(label="Status", interactive=False)
|
688 |
+
|
689 |
+
with gr.Tab("Agent Configuration"):
|
690 |
+
gr.Markdown("### Customize Agent Behavior")
|
691 |
with gr.Row():
|
692 |
+
for agent in ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"]:
|
693 |
+
with gr.Column():
|
694 |
+
gr.Markdown(f"#### {agent}")
|
695 |
+
agent_params[f"{agent}_creativity"] = gr.Slider(
|
696 |
+
0.0, 1.0, value=agent_params[agent]["creativity"],
|
697 |
+
label="Creativity", interactive=True
|
698 |
+
)
|
699 |
+
agent_params[f"{agent}_critical"] = gr.Slider(
|
700 |
+
0.0, 1.0, value=agent_params[agent]["criticality"],
|
701 |
+
label="Criticality", interactive=True
|
702 |
+
)
|
703 |
|
704 |
+
# Custom CSS
|
705 |
demo.css = """
|
706 |
+
.convo-container {
|
707 |
max-height: 400px;
|
708 |
overflow-y: auto;
|
709 |
+
padding: 15px;
|
710 |
border: 1px solid #e0e0e0;
|
711 |
+
border-radius: 8px;
|
712 |
+
background-color: #f9f9f9;
|
713 |
+
line-height: 1.6;
|
714 |
+
}
|
715 |
+
.convo-container p {
|
716 |
+
margin-bottom: 10px;
|
717 |
+
}
|
718 |
+
#topic-display {
|
719 |
+
font-weight: bold;
|
720 |
+
font-size: 1.1em;
|
721 |
}
|
722 |
"""
|
723 |
|
|
|
727 |
conversation = []
|
728 |
turn_count = 0
|
729 |
current_topic = ""
|
730 |
+
return (
|
731 |
+
"<div class='convo-container'>New discussion started</div>",
|
732 |
+
"", "", "", "", "", 0, "",
|
733 |
+
{"agents": [], "counts": []}, "", None, ""
|
734 |
+
)
|
735 |
|
736 |
def new_topic():
|
737 |
+
clear_result = clear_convo()
|
738 |
topic = generate_topic()
|
739 |
+
return clear_result[:6] + (topic,) + clear_result[7:]
|
740 |
|
741 |
def ask_judge(query):
|
742 |
try:
|
743 |
context = "\n".join([m['text'] for m in conversation[-3:]]) if conversation else "No context"
|
744 |
messages = [{"role": "user", "content": f"Discussion Topic: {current_topic}\n\nRecent context:\n{context}\n\nSpecific Question: {query}"}]
|
745 |
+
return safe_chat_completion(JUDGE_PROMPT, messages)
|
746 |
except Exception as e:
|
747 |
return f"[Judge Error: {str(e)}]"
|
748 |
|
749 |
+
def run_analysis():
|
750 |
+
analysis = analyze_conversation()
|
751 |
+
|
752 |
+
# Create agent participation plot
|
753 |
+
plt.figure(figsize=(8, 5))
|
754 |
+
plt.bar(analysis["agents"], analysis["counts"], color='skyblue')
|
755 |
+
plt.title("Agent Participation")
|
756 |
+
plt.ylabel("Number of Contributions")
|
757 |
+
plt.xticks(rotation=45)
|
758 |
+
plt.tight_layout()
|
759 |
+
plt.savefig("agent_participation.png")
|
760 |
+
|
761 |
+
return (
|
762 |
+
analysis["sentiment"],
|
763 |
+
analysis["topics"],
|
764 |
+
"agent_participation.png",
|
765 |
+
analysis
|
766 |
+
)
|
767 |
+
|
768 |
+
def export_handler(format):
|
769 |
+
if format == "PDF Report":
|
770 |
+
return export_pdf_report()
|
771 |
+
elif format == "JSON Data":
|
772 |
+
return export_json_data()
|
773 |
+
else:
|
774 |
+
return export_text_transcript()
|
775 |
+
|
776 |
+
def add_user_contribution(text):
|
777 |
+
if text.strip():
|
778 |
+
conversation.append({"agent": "π€ You", "text": text})
|
779 |
+
return format_convo(), f"β
Added: '{text[:30]}...'"
|
780 |
+
return format_convo(), "Please enter text"
|
781 |
+
|
782 |
+
def update_agent_params(*args):
|
783 |
+
# Update global agent_params based on UI sliders
|
784 |
+
params = agent_params.copy()
|
785 |
+
for agent in params.keys():
|
786 |
+
params[agent]["creativity"] = globals()[f"{agent}_creativity"].value
|
787 |
+
params[agent]["criticality"] = globals()[f"{agent}_critical"].value
|
788 |
+
return "Agent parameters updated!"
|
789 |
+
|
790 |
+
# Connect UI components
|
791 |
step_btn.click(
|
792 |
step,
|
793 |
+
inputs=[topic_display],
|
794 |
+
outputs=[
|
795 |
+
convo_display, intervention_display, outsider_display,
|
796 |
+
cultural_display, judge_display, topic_display, turn_counter, agent_status
|
797 |
+
]
|
798 |
+
)
|
799 |
+
qbox.submit(ask_judge, inputs=gr.Textbox(), outputs=gr.Textbox())
|
800 |
+
auto_btn.click(
|
801 |
+
lambda: ("π’ Auto: ON" if not auto_mode else "π΄ Auto: OFF"),
|
802 |
+
outputs=auto_btn
|
803 |
)
|
|
|
|
|
|
|
804 |
clear_btn.click(
|
805 |
clear_convo,
|
806 |
+
outputs=[
|
807 |
+
convo_display, intervention_display, outsider_display,
|
808 |
+
cultural_display, judge_display, topic_display, turn_counter,
|
809 |
+
agent_status, agent_plot, graph_display
|
810 |
+
]
|
811 |
)
|
812 |
topic_btn.click(
|
813 |
new_topic,
|
814 |
+
outputs=[convo_display, topic_display, turn_counter]
|
815 |
)
|
816 |
ruling_btn.click(
|
817 |
+
lambda: judge_ruling(),
|
818 |
outputs=[judge_display]
|
819 |
)
|
820 |
+
analysis_btn.click(
|
821 |
+
run_analysis,
|
822 |
+
outputs=[sentiment_display, topics_display, agent_plot, topics_display]
|
823 |
+
)
|
824 |
+
graph_btn.click(
|
825 |
+
generate_knowledge_graph,
|
826 |
+
outputs=[graph_display]
|
827 |
+
)
|
828 |
+
export_btn.click(
|
829 |
+
export_handler,
|
830 |
+
inputs=[format_radio],
|
831 |
+
outputs=[export_result]
|
832 |
+
)
|
833 |
+
integrate_btn.click(
|
834 |
+
send_to_webhook,
|
835 |
+
inputs=[webhook_url],
|
836 |
+
outputs=[integration_status]
|
837 |
+
)
|
838 |
+
submit_btn.click(
|
839 |
+
add_user_contribution,
|
840 |
+
inputs=[user_input],
|
841 |
+
outputs=[convo_display, user_feedback]
|
842 |
+
)
|
843 |
+
|
844 |
+
# Connect all agent parameter sliders
|
845 |
+
param_components = [globals()[f"{agent}_{param}"]
|
846 |
+
for agent in agent_params.keys()
|
847 |
+
for param in ["creativity", "critical"]]
|
848 |
+
for comp in param_components:
|
849 |
+
comp.change(
|
850 |
+
update_agent_params,
|
851 |
+
inputs=param_components,
|
852 |
+
outputs=[gr.Textbox(visible=False)]
|
853 |
+
)
|
854 |
|
855 |
demo.launch()
|