Spaces:
Sleeping
Sleeping
# app.py - DeepSeek Hexa-Agent Discussion Platform | |
import gradio as gr | |
import openai | |
import threading | |
import time | |
import numpy as np | |
import faiss | |
import os | |
import pickle | |
from datetime import datetime | |
import re | |
import json | |
import matplotlib.pyplot as plt | |
import networkx as nx | |
from reportlab.lib.pagesizes import letter | |
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer | |
from reportlab.lib.styles import getSampleStyleSheet | |
from functools import lru_cache | |
import requests | |
# === CONFIG === | |
EMBEDDING_MODEL = "text-embedding-3-small" | |
CHAT_MODEL = "gpt-4o" | |
MEMORY_FILE = "memory.pkl" | |
INDEX_FILE = "memory.index" | |
openai.api_key = os.environ.get("OPENAI_API_KEY") | |
# === EMBEDDING UTILS === | |
def get_embedding(text, model=EMBEDDING_MODEL): | |
"""Cached embedding function for performance""" | |
text = text.replace("\n", " ") | |
try: | |
response = openai.embeddings.create(input=[text], model=model) | |
return response.data[0].embedding | |
except AttributeError: | |
response = openai.Embedding.create(input=[text], model=model) | |
return response['data'][0]['embedding'] | |
def cosine_similarity(vec1, vec2): | |
vec1 = np.array(vec1) | |
vec2 = np.array(vec2) | |
return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2)) | |
# === MEMORY INITIALIZATION === | |
memory_data = [] | |
try: | |
memory_index = faiss.read_index(INDEX_FILE) | |
with open(MEMORY_FILE, "rb") as f: | |
memory_data = pickle.load(f) | |
except: | |
memory_index = faiss.IndexFlatL2(1536) | |
# === AGENT SYSTEM PROMPTS (Configurable) === | |
AGENT_A_PROMPT = """You are the Discussion Initiator. Your role: | |
1. Introduce complex topics requiring multidisciplinary perspectives | |
2. Frame debates exploring tensions between values, ethics, and progress | |
3. Challenge assumptions while maintaining intellectual humility | |
4. Connect concepts across domains (science, ethics, policy, technology) | |
5. Elevate discussions beyond surface-level analysis""" | |
AGENT_B_PROMPT = """You are the Critical Responder. Your role: | |
1. Provide counterpoints with evidence-based reasoning | |
2. Identify logical fallacies and cognitive biases in arguments | |
3. Analyze implications at different scales (individual, societal, global) | |
4. Consider second and third-order consequences | |
5. Balance idealism with practical constraints""" | |
OVERSEER_PROMPT = """You are the Depth Guardian. Your role: | |
1. Ensure discussions maintain intellectual rigor | |
2. Intervene when conversations become superficial or repetitive | |
3. Highlight unexamined assumptions and blind spots | |
4. Introduce relevant frameworks (systems thinking, ethical paradigms) | |
5. Prompt consideration of marginalized perspectives | |
6. Synthesize key tensions and paradoxes""" | |
OUTSIDER_PROMPT = """You are the Cross-Disciplinary Provocateur. Your role: | |
1. Introduce radical perspectives from unrelated fields | |
2. Challenge conventional wisdom with contrarian viewpoints | |
3. Surface historical precedents and analogies | |
4. Propose unconventional solutions to complex problems | |
5. Highlight overlooked connections and systemic relationships | |
6. Question the framing of the discussion itself""" | |
CULTURAL_LENS_PROMPT = """You are the Cultural Perspective. Your role: | |
1. Provide viewpoints from diverse global cultures (Eastern, Western, Indigenous, African, etc.) | |
2. Highlight how cultural values shape perspectives on the topic | |
3. Identify cultural biases in arguments and assumptions | |
4. Share traditions and practices relevant to the discussion | |
5. Suggest culturally inclusive approaches to solutions | |
6. Bridge cultural divides through nuanced understanding | |
7. Consider post-colonial and decolonial perspectives""" | |
JUDGE_PROMPT = """You are the Impartial Judge. Your role: | |
1. Periodically review the discussion and provide balanced rulings | |
2. Identify areas of agreement and unresolved tensions | |
3. Evaluate the strength of arguments from different perspectives | |
4. Highlight the most compelling insights and critical flaws | |
5. Suggest pathways toward resolution or further inquiry | |
6. Deliver rulings with clear justification and constructive guidance | |
7. Maintain objectivity while acknowledging valid points from all sides | |
8. Consider ethical implications and practical feasibility""" | |
# === GLOBAL STATE === | |
conversation = [] | |
turn_count = 0 | |
auto_mode = False | |
current_topic = "" | |
last_ruling_turn = 0 | |
agent_params = { | |
"Initiator": {"creativity": 0.7, "criticality": 0.5}, | |
"Responder": {"creativity": 0.5, "criticality": 0.8}, | |
"Guardian": {"creativity": 0.6, "criticality": 0.9}, | |
"Provocateur": {"creativity": 0.9, "criticality": 0.7}, | |
"Cultural": {"creativity": 0.7, "criticality": 0.6}, | |
"Judge": {"creativity": 0.4, "criticality": 0.9} | |
} | |
# === ERROR-HANDLED API CALLS === | |
def safe_chat_completion(system, messages, model=CHAT_MODEL, temperature=0.7, max_retries=3): | |
"""Robust API call with exponential backoff""" | |
for attempt in range(max_retries): | |
try: | |
full_messages = [{"role": "system", "content": system}] | |
full_messages.extend(messages) | |
try: | |
response = openai.chat.completions.create( | |
model=model, | |
messages=full_messages, | |
temperature=temperature, | |
max_tokens=300 | |
) | |
return response.choices[0].message.content.strip() | |
except AttributeError: | |
response = openai.ChatCompletion.create( | |
model=model, | |
messages=full_messages, | |
temperature=temperature, | |
max_tokens=300 | |
) | |
return response['choices'][0]['message']['content'].strip() | |
except Exception as e: | |
if attempt < max_retries - 1: | |
wait_time = 2 ** attempt | |
print(f"API error: {e}. Retrying in {wait_time} seconds...") | |
time.sleep(wait_time) | |
else: | |
return f"β οΈ API Error: {str(e)}" | |
return "β οΈ Max retries exceeded" | |
# === MEMORY MANAGEMENT === | |
def embed_and_store(text, agent=None): | |
try: | |
vec = get_embedding(text) | |
memory_index.add(np.array([vec], dtype='float32')) | |
memory_data.append({ | |
"text": text, | |
"timestamp": datetime.now().isoformat(), | |
"agent": agent or "system", | |
"topic": current_topic | |
}) | |
if len(memory_data) % 5 == 0: | |
with open(MEMORY_FILE, "wb") as f: | |
pickle.dump(memory_data, f) | |
faiss.write_index(memory_index, INDEX_FILE) | |
except Exception as e: | |
print(f"Memory Error: {str(e)}") | |
def retrieve_relevant_memory(query, k=3): | |
"""Retrieve relevant past discussions""" | |
try: | |
query_embedding = get_embedding(query) | |
distances, indices = memory_index.search(np.array([query_embedding], dtype='float32'), k) | |
relevant = [] | |
for i, idx in enumerate(indices[0]): | |
if idx < len(memory_data) and idx >= 0: | |
relevant.append({ | |
"text": memory_data[idx]['text'][:200] + "...", | |
"topic": memory_data[idx].get('topic', 'Unknown'), | |
"agent": memory_data[idx].get('agent', 'Unknown'), | |
"similarity": 1 - distances[0][i] # Convert distance to similarity | |
}) | |
return relevant | |
except Exception as e: | |
print(f"Memory retrieval error: {str(e)}") | |
return [] | |
# === CONVERSATION UTILITIES === | |
def format_convo(): | |
return "\n".join([f"**{m['agent']}**: {m['text']}" for m in conversation]) | |
def detect_superficiality(): | |
"""Detect shallow arguments using linguistic analysis""" | |
if len(conversation) < 3: | |
return False | |
last_texts = [m['text'] for m in conversation[-3:]] | |
# Linguistic markers of superficiality | |
superficial_indicators = [ | |
r"\b(obviously|clearly|everyone knows)\b", | |
r"\b(simply|just|merely)\b", | |
r"\b(always|never)\b", | |
r"\b(I (think|believe|feel))\b", | |
r"\b(without question|undeniably)\b" | |
] | |
# Argument depth markers | |
depth_markers = [ | |
r"\b(however|conversely|paradoxically)\b", | |
r"\b(evidence suggests|studies indicate)\b", | |
r"\b(complex interplay|multifaceted nature)\b", | |
r"\b(trade-off|tension between)\b", | |
r"\b(historical precedent|comparative analysis)\b" | |
] | |
superficial_count = 0 | |
depth_count = 0 | |
for text in last_texts: | |
for pattern in superficial_indicators: | |
if re.search(pattern, text, re.IGNORECASE): | |
superficial_count += 1 | |
for pattern in depth_markers: | |
if re.search(pattern, text, re.IGNORECASE): | |
depth_count += 1 | |
return superficial_count > depth_count * 2 | |
def batch_cosine_similarity(embeddings): | |
"""Efficient batch similarity calculation""" | |
norms = np.linalg.norm(embeddings, axis=1) | |
dot_matrix = np.dot(embeddings, embeddings.T) | |
norm_matrix = np.outer(norms, norms) | |
return dot_matrix / norm_matrix | |
def detect_repetition(): | |
"""Check if recent messages are conceptually similar""" | |
if len(conversation) < 4: | |
return False | |
recent = [m['text'] for m in conversation[-4:]] | |
embeddings = [get_embedding(text) for text in recent] | |
# Use batch processing for efficiency | |
similarity_matrix = batch_cosine_similarity(np.array(embeddings)) | |
# Check similarity between current and previous messages | |
return any(similarity_matrix[-1][i] > 0.82 for i in range(len(embeddings)-1)) | |
def detect_cultural_relevance(): | |
"""Check if cultural perspectives are needed""" | |
if len(conversation) < 2: | |
return False | |
last_texts = " ".join([m['text'] for m in conversation[-2:]]) | |
cultural_triggers = [ | |
"society", "culture", "values", "tradition", | |
"global", "western", "eastern", "indigenous", | |
"community", "norms", "beliefs", "diversity", | |
"equity", "identity", "heritage", "colonial" | |
] | |
for trigger in cultural_triggers: | |
if trigger in last_texts.lower(): | |
return True | |
return False | |
def detect_judgment_opportunity(): | |
"""Identify when the discussion is ripe for judgment""" | |
if len(conversation) < 8: | |
return False | |
# Check for unresolved tensions | |
last_texts = " ".join([m['text'] for m in conversation[-4:]]) | |
judgment_triggers = [ | |
"tension", "dilemma", "paradox", "conflict", | |
"disagreement", "opposing views", "unresolved", | |
"contradiction", "impasse", "standoff" | |
] | |
for trigger in judgment_triggers: | |
if trigger in last_texts.lower(): | |
return True | |
return False | |
# === AGENT FUNCTIONS === | |
def generate_topic(): | |
"""Generate a complex discussion topic""" | |
topic = safe_chat_completion( | |
"Generate a complex discussion topic requiring multidisciplinary and multicultural analysis", | |
[{"role": "user", "content": "Create a topic addressing tensions between technological progress, ethics, and cultural values"}] | |
) | |
return topic.split(":")[-1].strip() if ":" in topic else topic | |
def outsider_comment(): | |
"""Generate outsider perspective""" | |
context = "\n".join([f"{m['agent']}: {m['text']}" for m in conversation[-4:]]) | |
prompt = f"Conversation Context:\n{context}\n\nProvide your cross-disciplinary perspective:" | |
# Apply agent parameters | |
params = agent_params["Provocateur"] | |
temp = 0.5 + params["creativity"] * 0.5 # Map to 0.5-1.0 range | |
return safe_chat_completion( | |
OUTSIDER_PROMPT, | |
[{"role": "user", "content": prompt}], | |
temperature=temp | |
) | |
def cultural_perspective(): | |
"""Generate cultural diversity perspective""" | |
context = "\n".join([f"{m['agent']}: {m['text']}" for m in conversation[-4:]]) | |
prompt = f"Conversation Context:\n{context}\n\nProvide diverse cultural perspectives on this topic:" | |
# Apply agent parameters | |
params = agent_params["Cultural"] | |
temp = 0.5 + params["creativity"] * 0.5 | |
return safe_chat_completion( | |
CULTURAL_LENS_PROMPT, | |
[{"role": "user", "content": prompt}], | |
temperature=temp | |
) | |
def judge_ruling(): | |
"""Generate final judgment or ruling""" | |
global last_ruling_turn | |
# Create comprehensive context | |
context = "\n\n".join([ | |
f"Discussion Topic: {current_topic}", | |
"Key Arguments:", | |
*[f"- {m['agent']}: {m['text']}" for m in conversation[-8:]] | |
]) | |
prompt = f"""After reviewing this discussion, provide your impartial judgment: | |
{context} | |
Your ruling should: | |
1. Identify areas of agreement and unresolved tensions | |
2. Evaluate the strength of key arguments | |
3. Highlight the most compelling insights | |
4. Suggest pathways toward resolution | |
5. Consider ethical and practical implications | |
6. Provide constructive guidance for next steps""" | |
# Apply agent parameters | |
params = agent_params["Judge"] | |
temp = 0.3 + params["criticality"] * 0.4 # More critical = lower temperature | |
ruling = safe_chat_completion( | |
JUDGE_PROMPT, | |
[{"role": "user", "content": prompt}], | |
temperature=temp | |
) | |
last_ruling_turn = turn_count | |
return ruling | |
# === CORE CONVERSATION FLOW === | |
def step(topic_input=""): | |
global conversation, turn_count, current_topic, last_ruling_turn | |
# Initialize new discussion | |
if not conversation: | |
current_topic = topic_input or generate_topic() | |
# Retrieve relevant memory | |
memory_context = retrieve_relevant_memory(current_topic) | |
context_str = "" | |
if memory_context: | |
context_str = "\n\nRelevant past discussions:\n" + "\n".join( | |
[f"- {item['agent']} on '{item['topic']}': {item['text']}" | |
for item in memory_context] | |
) | |
msg = safe_chat_completion( | |
AGENT_A_PROMPT, | |
[{"role": "user", "content": f"Initiate a deep discussion on: {current_topic}{context_str}"}], | |
temperature=0.5 + agent_params["Initiator"]["creativity"] * 0.5 | |
) | |
conversation.append({"agent": "π‘ Initiator", "text": msg}) | |
embed_and_store(msg, "Initiator") | |
turn_count = 1 | |
last_ruling_turn = 0 | |
return format_convo(), "", "", "", "", current_topic, turn_count, "" | |
# Critical Responder engages | |
last_msg = conversation[-1]['text'] | |
b_msg = safe_chat_completion( | |
AGENT_B_PROMPT, | |
[{"role": "user", "content": f"Topic: {current_topic}\n\nLast statement: {last_msg}"}], | |
temperature=0.4 + agent_params["Responder"]["criticality"] * 0.4 | |
) | |
conversation.append({"agent": "π Responder", "text": b_msg}) | |
embed_and_store(b_msg, "Responder") | |
# Initiator counters | |
a_msg = safe_chat_completion( | |
AGENT_A_PROMPT, | |
[{"role": "user", "content": f"Topic: {current_topic}\n\nCritical response: {b_msg}"}], | |
temperature=0.5 + agent_params["Initiator"]["creativity"] * 0.5 | |
) | |
conversation.append({"agent": "π‘ Initiator", "text": a_msg}) | |
embed_and_store(a_msg, "Initiator") | |
# Overseer intervention | |
intervention = "" | |
if turn_count % 3 == 0 or detect_repetition() or detect_superficiality(): | |
context = "\n".join([m['text'] for m in conversation[-4:]]) | |
prompt = f"Topic: {current_topic}\n\nDiscussion Context:\n{context}\n\nDeepen the analysis:" | |
intervention = safe_chat_completion( | |
OVERSEER_PROMPT, | |
[{"role": "user", "content": prompt}], | |
temperature=0.5 + agent_params["Guardian"]["criticality"] * 0.4 | |
) | |
conversation.append({"agent": "βοΈ Depth Guardian", "text": intervention}) | |
embed_and_store(intervention, "Overseer") | |
# Outsider commentary | |
outsider_msg = "" | |
if turn_count % 4 == 0 or "paradox" in last_msg.lower(): | |
outsider_msg = outsider_comment() | |
conversation.append({"agent": "π Provocateur", "text": outsider_msg}) | |
embed_and_store(outsider_msg, "Outsider") | |
# Cultural perspective | |
cultural_msg = "" | |
if turn_count % 5 == 0 or detect_cultural_relevance(): | |
cultural_msg = cultural_perspective() | |
conversation.append({"agent": "π Cultural Lens", "text": cultural_msg}) | |
embed_and_store(cultural_msg, "Cultural") | |
# Judge ruling | |
judge_msg = "" | |
ruling_interval = 6 # Turns between rulings | |
if (turn_count - last_ruling_turn >= ruling_interval and | |
(turn_count % ruling_interval == 0 or detect_judgment_opportunity())): | |
judge_msg = judge_ruling() | |
conversation.append({"agent": "βοΈ Judge", "text": judge_msg}) | |
embed_and_store(judge_msg, "Judge") | |
turn_count += 1 | |
return format_convo(), intervention, outsider_msg, cultural_msg, judge_msg, current_topic, turn_count, "" | |
# === ANALYSIS & VISUALIZATION === | |
def analyze_conversation(): | |
"""Generate insights about the discussion""" | |
# Count agent contributions | |
agent_counts = {} | |
for msg in conversation: | |
agent = msg['agent'].split()[0] # Remove emoji | |
agent_counts[agent] = agent_counts.get(agent, 0) + 1 | |
# Sentiment analysis | |
sentiment_prompt = f"Analyze overall sentiment of this discussion:\n{format_convo()}" | |
sentiment = safe_chat_completion( | |
"You are a sentiment analysis expert. Provide a brief assessment of the discussion tone.", | |
[{"role": "user", "content": sentiment_prompt}] | |
) | |
# Topic extraction | |
topic_prompt = f"Extract key topics from this discussion:\n{format_convo()}" | |
topics = safe_chat_completion( | |
"You are a topic extraction expert. List the top 5 topics as a JSON array.", | |
[{"role": "user", "content": topic_prompt}] | |
) | |
try: | |
topics = json.loads(topics) | |
except: | |
topics = ["Topic extraction failed"] | |
return { | |
"agents": list(agent_counts.keys()), | |
"counts": [agent_counts.get(a, 0) for a in list(agent_counts.keys())], | |
"topics": topics, | |
"sentiment": sentiment | |
} | |
def generate_knowledge_graph(): | |
"""Create a knowledge graph of discussion concepts""" | |
# Extract entities and relationships | |
extraction_prompt = f""" | |
Analyze this discussion and extract: | |
1. Key concepts (nouns, important terms) | |
2. Relationships between concepts (verb phrases) | |
Discussion: | |
{format_convo()} | |
Return as JSON: {{"concepts": ["list", "of", "concepts"], "relationships": [["concept1", "relationship", "concept2"]]}} | |
""" | |
try: | |
graph_data = safe_chat_completion( | |
"You are a knowledge graph extraction expert.", | |
[{"role": "user", "content": extraction_prompt}] | |
) | |
graph_data = json.loads(graph_data) | |
# Create graph visualization | |
G = nx.DiGraph() | |
G.add_nodes_from(graph_data["concepts"]) | |
for rel in graph_data["relationships"]: | |
if len(rel) == 3: | |
G.add_edge(rel[0], rel[2], label=rel[1]) | |
plt.figure(figsize=(10, 8)) | |
pos = nx.spring_layout(G, seed=42) | |
nx.draw(G, pos, with_labels=True, node_size=2000, node_color="skyblue", font_size=10) | |
edge_labels = nx.get_edge_attributes(G, 'label') | |
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels) | |
plt.title("Discussion Knowledge Graph") | |
plt.savefig("knowledge_graph.png") | |
return "knowledge_graph.png" | |
except Exception as e: | |
print(f"Graph error: {str(e)}") | |
return None | |
# === EXPORT FUNCTIONS === | |
def export_pdf_report(): | |
"""Generate PDF report of discussion""" | |
filename = f"discussion_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf" | |
doc = SimpleDocTemplate(filename, pagesize=letter) | |
styles = getSampleStyleSheet() | |
story = [] | |
# Title | |
story.append(Paragraph(f"Discussion Report: {current_topic}", styles['Title'])) | |
story.append(Spacer(1, 12)) | |
# Summary | |
analysis = analyze_conversation() | |
story.append(Paragraph("Discussion Summary", styles['Heading2'])) | |
story.append(Paragraph(f"<b>Turn Count:</b> {turn_count}", styles['BodyText'])) | |
story.append(Paragraph(f"<b>Sentiment:</b> {analysis['sentiment']}", styles['BodyText'])) | |
story.append(Spacer(1, 12)) | |
# Key Topics | |
story.append(Paragraph("Key Topics", styles['Heading2'])) | |
for topic in analysis['topics']: | |
story.append(Paragraph(f"- {topic}", styles['BodyText'])) | |
story.append(Spacer(1, 12)) | |
# Full Conversation | |
story.append(Paragraph("Full Discussion", styles['Heading2'])) | |
for msg in conversation: | |
story.append(Paragraph(f"<b>{msg['agent']}:</b> {msg['text']}", styles['BodyText'])) | |
story.append(Spacer(1, 6)) | |
doc.build(story) | |
return filename | |
def export_json_data(): | |
"""Export conversation as JSON""" | |
filename = f"discussion_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" | |
with open(filename, 'w') as f: | |
json.dump({ | |
"topic": current_topic, | |
"turns": turn_count, | |
"conversation": conversation, | |
"analysis": analyze_conversation() | |
}, f, indent=2) | |
return filename | |
def export_text_transcript(): | |
"""Export as plain text""" | |
filename = f"transcript_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt" | |
with open(filename, 'w') as f: | |
f.write(f"Discussion Topic: {current_topic}\n\n") | |
f.write("Participants:\n") | |
agents = set(msg['agent'] for msg in conversation) | |
for agent in agents: | |
f.write(f"- {agent}\n") | |
f.write("\nConversation:\n") | |
for msg in conversation: | |
f.write(f"{msg['agent']}: {msg['text']}\n\n") | |
return filename | |
# === INTEGRATION FUNCTIONS === | |
def send_to_webhook(url): | |
"""Send discussion data to external webhook""" | |
try: | |
payload = { | |
"topic": current_topic, | |
"turns": turn_count, | |
"conversation": conversation, | |
"timestamp": datetime.now().isoformat() | |
} | |
response = requests.post(url, json=payload, timeout=10) | |
if response.status_code == 200: | |
return "β Data sent successfully!" | |
else: | |
return f"β οΈ Error {response.status_code}: {response.text}" | |
except Exception as e: | |
return f"β οΈ Connection error: {str(e)}" | |
# ... [Keep all the imports, config, and function definitions above] ... | |
# === GRADIO UI === | |
with gr.Blocks(theme=gr.themes.Soft(), title="DeepSeek Discussion Platform") as demo: | |
gr.Markdown("# π§ DeepSeek Hexa-Agent Discussion System") | |
gr.Markdown("### AI-Powered Complex Discourse Analysis") | |
# Status panel | |
with gr.Row(): | |
turn_counter = gr.Number(label="Turn Count", value=0, interactive=False) | |
topic_display = gr.Textbox(label="Current Topic", interactive=False, lines=2) | |
agent_status = gr.Textbox(label="Active Agents", value="π‘ Initiator, π Responder", interactive=False) | |
# Tabbed interface | |
with gr.Tab("Live Discussion"): | |
convo_display = gr.HTML( | |
value="<div class='convo-container'>Discussion will appear here</div>", | |
elem_id="convo-display" | |
) | |
with gr.Row(): | |
step_btn = gr.Button("βΆοΈ Next Turn", variant="primary") | |
auto_btn = gr.Button("π΄ Auto: OFF", variant="secondary") | |
clear_btn = gr.Button("π New Discussion", variant="stop") | |
topic_btn = gr.Button("π² Random Topic", variant="secondary") | |
ruling_btn = gr.Button("βοΈ Request Ruling", variant="primary") | |
with gr.Accordion("π¬ Guide the Discussion", open=False): | |
topic_input = gr.Textbox(label="Set Custom Topic", placeholder="e.g., Ethics of AGI in cultural contexts...") | |
with gr.Row(): | |
qbox = gr.Textbox(label="Ask the Depth Guardian", placeholder="What perspectives are missing?") | |
ruling_qbox = gr.Textbox(label="Specific Question for Judge", placeholder="What should be our guiding principle?") | |
with gr.Row(): | |
overseer_out = gr.Textbox(label="Depth Guardian Response", interactive=False) | |
judge_out = gr.Textbox(label="Judge's Response", interactive=False) | |
with gr.Tab("Agent Perspectives"): | |
with gr.Row(): | |
with gr.Column(scale=1): | |
gr.Markdown("### βοΈ Depth Guardian") | |
intervention_display = gr.Textbox(label="", interactive=False) | |
with gr.Column(scale=1): | |
gr.Markdown("### π Cross-Disciplinary") | |
outsider_display = gr.Textbox(label="", interactive=False) | |
with gr.Column(scale=1): | |
gr.Markdown("### π Cultural Lens") | |
cultural_display = gr.Textbox(label="", interactive=False) | |
with gr.Row(): | |
with gr.Column(scale=3): | |
gr.Markdown("### βοΈ Final Judgment") | |
judge_display = gr.Textbox(label="", interactive=False, lines=4) | |
with gr.Tab("Analysis Dashboard"): | |
gr.Markdown("### Conversation Insights") | |
with gr.Row(): | |
sentiment_display = gr.Textbox(label="Discussion Sentiment", interactive=False) | |
topics_display = gr.JSON(label="Key Topics") | |
with gr.Row(): | |
agent_plot = gr.Plot(label="Agent Participation") | |
analysis_btn = gr.Button("Generate Insights", variant="primary") | |
with gr.Row(): | |
gr.Markdown("### Knowledge Graph") | |
graph_btn = gr.Button("Generate Knowledge Graph", variant="secondary") | |
graph_display = gr.Image(label="Concept Relationships", interactive=False) | |
with gr.Tab("Collaboration"): | |
gr.Markdown("### Real-Time Collaboration") | |
with gr.Row(): | |
user_input = gr.Textbox(label="Your Contribution", placeholder="Add your perspective...") | |
submit_btn = gr.Button("Add to Discussion") | |
with gr.Row(): | |
voting_btn = gr.Button("π Vote for Current Direction") | |
flag_btn = gr.Button("π© Flag Issue") | |
with gr.Row(): | |
user_feedback = gr.Textbox(label="Community Feedback", interactive=False) | |
with gr.Tab("Export & Integrate"): | |
with gr.Row(): | |
format_radio = gr.Radio( | |
["PDF Report", "JSON Data", "Text Transcript"], | |
label="Export Format", | |
value="PDF Report" | |
) | |
export_btn = gr.Button("Export Discussion", variant="primary") | |
export_result = gr.File(label="Download File") | |
with gr.Row(): | |
gr.Markdown("### API Integration") | |
webhook_url = gr.Textbox(label="Webhook URL", placeholder="https://your-platform.com/webhook") | |
integrate_btn = gr.Button("Connect to External Platform", variant="secondary") | |
integration_status = gr.Textbox(label="Status", interactive=False) | |
with gr.Tab("Agent Configuration"): | |
gr.Markdown("### Customize Agent Behavior") | |
with gr.Row(): | |
agent_sliders = {} | |
for agent in ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"]: | |
with gr.Column(): | |
gr.Markdown(f"#### {agent}") | |
agent_sliders[f"{agent}_creativity"] = gr.Slider( | |
0.0, 1.0, value=0.7, | |
label="Creativity", interactive=True | |
) | |
agent_sliders[f"{agent}_critical"] = gr.Slider( | |
0.0, 1.0, value=0.5, | |
label="Criticality", interactive=True | |
) | |
# Custom CSS | |
demo.css = """ | |
.convo-container { | |
max-height: 400px; | |
overflow-y: auto; | |
padding: 15px; | |
border: 1px solid #e0e0e0; | |
border-radius: 8px; | |
background-color: #f9f9f9; | |
line-height: 1.6; | |
} | |
.convo-container p { | |
margin-bottom: 10px; | |
} | |
#topic-display { | |
font-weight: bold; | |
font-size: 1.1em; | |
} | |
""" | |
# Event handlers | |
def clear_convo(): | |
global conversation, turn_count, current_topic | |
conversation = [] | |
turn_count = 0 | |
current_topic = "" | |
return ( | |
"<div class='convo-container'>New discussion started</div>", | |
"", "", "", "", "", 0, "", | |
{"agents": [], "counts": []}, "", None, "", "" | |
) | |
def new_topic(): | |
clear_result = clear_convo() | |
topic = generate_topic() | |
return clear_result[:6] + (topic,) + clear_result[7:] | |
# === OVERSEER QUERY HANDLER === | |
def overseer_respond(query): | |
try: | |
context = "\n".join([m['text'] for m in conversation[-3:]]) if conversation else "No context" | |
messages = [{"role": "user", "content": f"Discussion Topic: {current_topic}\n\nRecent context:\n{context}\n\nQuery: {query}"}] | |
return safe_chat_completion( | |
OVERSEER_PROMPT, | |
messages, | |
temperature=0.5 + agent_params["Guardian"]["criticality"] * 0.4 | |
) | |
except Exception as e: | |
return f"[Overseer Error: {str(e)}]" | |
# === JUDGE RULING HANDLER === | |
def request_ruling(): | |
try: | |
ruling = judge_ruling() | |
conversation.append({"agent": "βοΈ Judge", "text": ruling}) | |
embed_and_store(ruling, "Judge") | |
return ruling | |
except Exception as e: | |
return f"[Judge Error: {str(e)}]" | |
def ask_judge(query): | |
try: | |
context = "\n".join([m['text'] for m in conversation[-3:]]) if conversation else "No context" | |
messages = [{"role": "user", "content": f"Discussion Topic: {current_topic}\n\nRecent context:\n{context}\n\nSpecific Question: {query}"}] | |
return safe_chat_completion(JUDGE_PROMPT, messages) | |
except Exception as e: | |
return f"[Judge Error: {str(e)}]" | |
def run_analysis(): | |
analysis = analyze_conversation() | |
# Create agent participation plot | |
plt.figure(figsize=(8, 5)) | |
plt.bar(analysis["agents"], analysis["counts"], color='skyblue') | |
plt.title("Agent Participation") | |
plt.ylabel("Number of Contributions") | |
plt.xticks(rotation=45) | |
plt.tight_layout() | |
plt.savefig("agent_participation.png") | |
return ( | |
analysis["sentiment"], | |
analysis["topics"], | |
"agent_participation.png", | |
analysis | |
) | |
def export_handler(format): | |
if format == "PDF Report": | |
return export_pdf_report() | |
elif format == "JSON Data": | |
return export_json_data() | |
else: | |
return export_text_transcript() | |
def add_user_contribution(text): | |
if text.strip(): | |
conversation.append({"agent": "π€ You", "text": text}) | |
return format_convo(), f"β Added: '{text[:30]}...'" | |
return format_convo(), "Please enter text" | |
def toggle_auto(): | |
global auto_mode | |
auto_mode = not auto_mode | |
if auto_mode: | |
threading.Thread(target=auto_loop, daemon=True).start() | |
return "π΄ Auto: OFF" if not auto_mode else "π’ Auto: ON" | |
def auto_loop(): | |
global auto_mode | |
while auto_mode: | |
step() | |
time.sleep(6) | |
def update_agent_params(init_creat, init_crit, resp_creat, resp_crit, | |
guard_creat, guard_crit, prov_creat, prov_crit, | |
cult_creat, cult_crit, judge_creat, judge_crit): | |
global agent_params | |
agent_params = { | |
"Initiator": {"creativity": init_creat, "criticality": init_crit}, | |
"Responder": {"creativity": resp_creat, "criticality": resp_crit}, | |
"Guardian": {"creativity": guard_creat, "criticality": guard_crit}, | |
"Provocateur": {"creativity": prov_creat, "criticality": prov_crit}, | |
"Cultural": {"creativity": cult_creat, "criticality": cult_crit}, | |
"Judge": {"creativity": judge_creat, "criticality": judge_crit} | |
} | |
return "β Agent parameters updated!" | |
# Connect UI components | |
qbox.submit( | |
overseer_respond, | |
inputs=qbox, | |
outputs=overseer_out | |
) | |
ruling_qbox.submit( | |
ask_judge, | |
inputs=ruling_qbox, | |
outputs=judge_out | |
) | |
step_btn.click( | |
step, | |
inputs=[topic_input], | |
outputs=[ | |
convo_display, intervention_display, outsider_display, | |
cultural_display, judge_display, topic_display, turn_counter, agent_status | |
] | |
) | |
auto_btn.click( | |
toggle_auto, | |
outputs=auto_btn | |
) | |
clear_btn.click( | |
clear_convo, | |
outputs=[ | |
convo_display, intervention_display, outsider_display, | |
cultural_display, judge_display, topic_display, turn_counter, | |
agent_status, agent_plot, graph_display, user_feedback | |
] | |
) | |
topic_btn.click( | |
new_topic, | |
outputs=[convo_display, topic_display, turn_counter] | |
) | |
ruling_btn.click( | |
request_ruling, | |
outputs=[judge_display] | |
) | |
analysis_btn.click( | |
run_analysis, | |
outputs=[sentiment_display, topics_display, agent_plot] | |
) | |
graph_btn.click( | |
generate_knowledge_graph, | |
outputs=[graph_display] | |
) | |
export_btn.click( | |
export_handler, | |
inputs=[format_radio], | |
outputs=[export_result] | |
) | |
integrate_btn.click( | |
send_to_webhook, | |
inputs=[webhook_url], | |
outputs=[integration_status] | |
) | |
submit_btn.click( | |
add_user_contribution, | |
inputs=[user_input], | |
outputs=[convo_display, user_feedback] | |
) | |
voting_btn.click( | |
lambda: "β Your vote has been recorded!", | |
outputs=[user_feedback] | |
) | |
flag_btn.click( | |
lambda: "π© Issue flagged for moderator review", | |
outputs=[user_feedback] | |
) | |
# Create input list for slider change events | |
slider_inputs = [agent_sliders[f"{agent}_{param}"] | |
for agent in ["Initiator", "Responder", "Guardian", "Provocateur", "Cultural", "Judge"] | |
for param in ["creativity", "critical"]] | |
for slider in slider_inputs: | |
slider.change( | |
update_agent_params, | |
inputs=slider_inputs, | |
outputs=[gr.Textbox(visible=False)] | |
) | |
demo.launch() |