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() |