mgbam commited on
Commit
586415b
Β·
verified Β·
1 Parent(s): 449064c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +232 -0
app.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from typing import Dict, List, Optional
4
+ import base64
5
+ from PIL import Image
6
+ import PyPDF2
7
+ import docx
8
+ import pytesseract
9
+ import gradio as gr
10
+ from huggingface_hub import InferenceClient
11
+ import zipfile
12
+ import io
13
+ import time
14
+ import asyncio
15
+ import plotly.graph_objects as go
16
+ import networkx as nx
17
+
18
+ # --- Synapsera X: The Cognitive Operating System ---
19
+
20
+ # --- Multi-Agent Prompt Engineering ---
21
+ # Each prompt now defines a specialized agent's role and output format.
22
+
23
+ SYNTHESIS_AGENT_PROMPT = """
24
+ You are the **Synthesis Agent** of the Synapsera OS. Your task is to analyze the user's raw input and create the initial **Semantic Thought Graph**. Your output must be ONLY a single, valid JSON object with 'summary', 'nodes', and 'edges'. This graph is the foundational artifact for all other agents.
25
+ """
26
+
27
+ CRITIC_AGENT_PROMPT = """
28
+ You are **THE CRITIC**, a member of the Synapsera Cognitive Council. You are ruthless, logical, and skeptical. Your task is to analyze the provided Thought Graph. Identify every logical fallacy, weak assumption, cognitive bias, and potential point of failure. Output your analysis as a concise, hard-hitting Markdown report. Do not be polite.
29
+ """
30
+
31
+ VISIONARY_AGENT_PROMPT = """
32
+ You are **THE VISIONARY**, a member of the Synapsera Cognitive Council. You are creative, expansive, and forward-thinking. Your task is to analyze the provided Thought Graph. Identify emergent patterns, latent potential, and high-impact 'what if' scenarios. Extrapolate the user's ideas into the most ambitious, world-changing version possible. Output your analysis as an inspiring and expansive Markdown report.
33
+ """
34
+
35
+ PRAGMATIST_AGENT_PROMPT = """
36
+ You are **THE PRAGMATIST**, a member of the Synapsera Cognitive Council. You are grounded, practical, and action-oriented. Your task is to analyze the provided Thought Graph. Translate abstract concepts into a concrete plan. Identify the immediate next steps, required resources, and potential real-world obstacles. Output your analysis as a clear, actionable checklist in Markdown format.
37
+ """
38
+
39
+ ARCHITECT_AGENT_PROMPT = """
40
+ You are the **Architect Agent** of the Synapsera OS. Your task is to build a complete, functional, single-file web application based on the user's request. You must use Tailwind CSS via CDN and embed all JS in the HTML file. Your output must be ONLY the raw HTML code.
41
+ """
42
+
43
+ REFACTOR_AGENT_PROMPT = """
44
+ You are the **Architect Agent** performing a self-correction cycle. You will be given your own initial code and a critique from the Critic Agent. Your task is to rewrite the code to address the critique, improving its functionality, UX, and robustness. Your output must be ONLY the new, improved, raw HTML code.
45
+ """
46
+
47
+ # --- Client Initialization ---
48
+ HF_TOKEN = os.getenv('HF_TOKEN')
49
+ client = InferenceClient(token=HF_TOKEN)
50
+ MODEL_ID = "mistralai/Mixtral-8x22B-Instruct-v0.1"
51
+
52
+ # --- Helper & Rendering Functions ---
53
+ def create_zip_from_code(html_code: str, readme_text: str) -> Optional[str]:
54
+ # (Enhanced to create a full project structure)
55
+ if not html_code: return None
56
+ zip_buffer = io.BytesIO()
57
+ with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zf:
58
+ # A more robust parser would be ideal, but regex is fine for this demo
59
+ import re
60
+ style_match = re.search(r'<style>(.*?)</style>', html_code, re.DOTALL)
61
+ script_match = re.search(r'<script>(.*?)</script>', html_code, re.DOTALL)
62
+ body_match = re.search(r'<body>(.*?)</body>', html_code, re.DOTALL)
63
+
64
+ html_content = f"<!DOCTYPE html>\n<html lang='en'>\n<head>\n <meta charset='UTF-8'>\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n <title>Synapsera-Built App</title>\n <link href='style.css' rel='stylesheet'>\n</head>\n<body>\n{body_match.group(1) if body_match else ''}\n<script src='script.js'></script>\n</body>\n</html>"
65
+ css_content = style_match.group(1) if style_match else "/* CSS not found */"
66
+ js_content = script_match.group(1) if script_match else "// JS not found"
67
+
68
+ zf.writestr("index.html", html_content)
69
+ zf.writestr("style.css", css_content.strip())
70
+ zf.writestr("script.js", js_content.strip())
71
+ zf.writestr("README.md", readme_text)
72
+ # Add a placeholder Python backend
73
+ zf.writestr("server.py", "from flask import Flask\n\napp = Flask(__name__)\n\[email protected]('/')\ndef home():\n return 'Synapsera-Built App Backend'\n\nif __name__ == '__main__':\n app.run(debug=True, port=5000)\n")
74
+
75
+ zip_path = "/tmp/application_project.zip"
76
+ with open(zip_path, "wb") as f: f.write(zip_buffer.getvalue())
77
+ return zip_path
78
+
79
+ def render_3d_graph(graph_data: Optional[Dict] = None):
80
+ # (This is the "wow" factor visualization)
81
+ if not graph_data or not graph_data.get('nodes'):
82
+ fig = go.Figure()
83
+ fig.update_layout(title_text="Cognitive Nebula Awaiting Synthesis...", template="plotly_dark", height=700)
84
+ return fig
85
+
86
+ G = nx.Graph()
87
+ for node in graph_data['nodes']: G.add_node(node['id'])
88
+ for edge in graph_data.get('edges', []):
89
+ if edge['source'] in G.nodes and edge['target'] in G.nodes:
90
+ G.add_edge(edge['source'], edge['target'])
91
+
92
+ pos = nx.spring_layout(G, dim=3, seed=42, iterations=50)
93
+
94
+ node_x, node_y, node_z = [pos[n][0] for n in G.nodes()], [pos[n][1] for n in G.nodes()], [pos[n][2] for n in G.nodes()]
95
+ edge_x, edge_y, edge_z = [], [], []
96
+ for edge in G.edges():
97
+ x0, y0, z0 = pos[edge[0]]
98
+ x1, y1, z1 = pos[edge[1]]
99
+ edge_x.extend([x0, x1, None])
100
+ edge_y.extend([y0, y1, None])
101
+ edge_z.extend([z0, z1, None])
102
+
103
+ color_map = {"Concept": "#8A2BE2", "Belief": "#2ca02c", "Assumption": "#ff7f0e"}
104
+ node_text = [f"<b>{n['label']}</b><br>({n['type']})" for n in graph_data['nodes']]
105
+ node_color = [color_map.get(n['type'], "#7f7f7f") for n in graph_data['nodes']]
106
+ node_size = [10 + n.get('importance', 0.5) * 15 for n in graph_data['nodes']]
107
+
108
+ edge_trace = go.Scatter3d(x=edge_x, y=edge_y, z=edge_z, mode='lines', line=dict(color='#888', width=2), hoverinfo='none')
109
+ node_trace = go.Scatter3d(x=node_x, y=node_y, z=node_z, mode='markers', text=node_text,
110
+ marker=dict(color=node_color, size=node_size, symbol='circle'), hoverinfo='text')
111
+
112
+ fig = go.Figure(data=[edge_trace, node_trace])
113
+ fig.update_layout(title=f"Cognitive Nebula: {graph_data.get('summary', '')}", showlegend=False, template="plotly_dark", height=700,
114
+ scene=dict(xaxis=dict(visible=False), yaxis=dict(visible=False), zaxis=dict(visible=False)))
115
+ return fig
116
+
117
+ # --- Core Asynchronous Multi-Agent Logic ---
118
+ async def run_agent(prompt: str, context: str) -> str:
119
+ """A generic function to run any agent asynchronously."""
120
+ messages = [{"role": "system", "content": prompt}, {"role": "user", "content": context}]
121
+ try:
122
+ # Using Hugging Face's async client would be ideal here if available,
123
+ # but we can wrap the sync call in an async function for now.
124
+ loop = asyncio.get_running_loop()
125
+ response = await loop.run_in_executor(
126
+ None,
127
+ lambda: client.chat_completion(model=MODEL_ID, messages=messages, max_tokens=4096)
128
+ )
129
+ return response.choices[0].message.content or "Agent returned an empty response."
130
+ except Exception as e:
131
+ return f"Agent Error: {e}"
132
+
133
+ async def universal_synthesis(synthesis_mode: str, text_input: str, progress=gr.Progress(track_tqdm=True)):
134
+ """The main entry point that orchestrates the agent swarm."""
135
+ if synthesis_mode == "Analyze Thought":
136
+ yield "Initializing Synthesis Agent...", gr.update(), gr.update(), gr.update(), gr.update(visible=False)
137
+
138
+ graph_json_str = await run_agent(SYNTHESIS_AGENT_PROMPT, text_input)
139
+ try:
140
+ graph_data = json.loads(graph_json_str)
141
+ graph_context = f"Thought Graph:\n{json.dumps(graph_data, indent=2)}"
142
+ except json.JSONDecodeError:
143
+ yield f"Synthesis Agent failed to produce valid JSON.\n{graph_json_str}", gr.update(), gr.update(), gr.update(), gr.update(visible=False)
144
+ return
145
+
146
+ yield "Convening Cognitive Council...", render_3d_graph(graph_data), "", "", "", gr.update(visible=False)
147
+
148
+ # Run Critic, Visionary, and Pragmatist agents in parallel
149
+ critic_task = asyncio.create_task(run_agent(CRITIC_AGENT_PROMPT, graph_context))
150
+ visionary_task = asyncio.create_task(run_agent(VISIONARY_AGENT_PROMPT, graph_context))
151
+ pragmatist_task = asyncio.create_task(run_agent(PRAGMATIST_AGENT_PROMPT, graph_context))
152
+
153
+ # Stream results as they complete
154
+ critic_analysis = await critic_task
155
+ yield f"Convening Cognitive Council...\n\n**CRITIC ANALYSIS COMPLETE**", render_3d_graph(graph_data), critic_analysis, "", "", gr.update(visible=False)
156
+
157
+ visionary_analysis = await visionary_task
158
+ yield f"Convening Cognitive Council...\n\n**CRITIC & VISIONARY ANALYSIS COMPLETE**", render_3d_graph(graph_data), critic_analysis, visionary_analysis, "", gr.update(visible=False)
159
+
160
+ pragmatist_analysis = await pragmatist_task
161
+ yield f"**Cognitive Council Concluded.**", render_3d_graph(graph_data), critic_analysis, visionary_analysis, pragmatist_analysis, gr.update(visible=False)
162
+
163
+ else: # Build Application
164
+ yield "Initializing Architect Agent...", gr.update(), gr.update(visible=True, value=None), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
165
+
166
+ initial_code = await run_agent(ARCHITECT_AGENT_PROMPT, text_input)
167
+ yield "Architect Agent completed initial build. Engaging Critic Agent for review...", gr.update(), gr.update(visible=True, value=initial_code), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
168
+
169
+ critic_review_context = f"Please review this HTML code for bugs, UX flaws, and improvements:\n\n{initial_code}"
170
+ critic_review = await run_agent(CRITIC_AGENT_PROMPT, critic_review_context)
171
+ yield f"Critic Agent review complete. Initiating self-correction loop...\n\n**Critique:**\n{critic_review}", gr.update(), gr.update(visible=True, value=initial_code), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
172
+
173
+ refactor_context = f"Here is the initial code:\n```html\n{initial_code}\n```\n\nHere is the critique:\n{critic_review}\n\nPlease provide the new, improved code."
174
+ refactored_code = await run_agent(REFACTOR_AGENT_PROMPT, refactor_context)
175
+
176
+ readme = f"# Synapsera-Built Application\n\nThis project was generated by the Synapsera X Cognitive OS.\n\n## User Prompt:\n{text_input}\n\n## Critic's Review of v1:\n{critic_review}"
177
+ zip_path = create_zip_from_code(refactored_code, readme)
178
+
179
+ yield "Self-correction complete. Final application generated.", gr.update(), gr.update(visible=False), gr.update(visible=True, value=initial_code), gr.update(visible=True, value=refactored_code), gr.update(visible=True, value=zip_path)
180
+
181
+
182
+ # --- Gradio UI for Synapsera X ---
183
+ with gr.Blocks(theme=gr.themes.Default(primary_hue="purple", secondary_hue="blue"), css="footer{display:none !important}") as demo:
184
+ gr.Markdown("# 🧠 Synapsera X: The Cognitive Operating System")
185
+
186
+ with gr.Row():
187
+ with gr.Column(scale=1, min_width=400):
188
+ gr.Markdown("### πŸš€ Control Deck")
189
+ synthesis_mode = gr.Radio(["Analyze Thought", "Build Application"], label="Objective", value="Analyze Thought")
190
+ text_input = gr.Textbox(lines=10, label="Input Your Core Thought or Application Idea", placeholder="e.g., A decentralized social network for scientists to share and peer-review pre-print research papers, with a token-based reputation system.")
191
+ synthesize_btn = gr.Button("Engage Synapsera", variant="primary", size="lg")
192
+
193
+ with gr.Column(scale=2):
194
+ with gr.Accordion("πŸ”΄ Thought Terminal (Live Log)", open=True):
195
+ terminal_output = gr.Markdown("Status: **IDLE**. Awaiting engagement...")
196
+
197
+ with gr.Blocks(visible=True) as analysis_canvas:
198
+ gr.Markdown("### 🌌 Cognitive Nebula")
199
+ plot_3d = gr.Plot()
200
+ gr.Markdown("### πŸ›οΈ Cognitive Council Analysis")
201
+ with gr.Row():
202
+ critic_output = gr.Markdown("### The Critic\n*Awaiting analysis...*")
203
+ visionary_output = gr.Markdown("### The Visionary\n*Awaiting analysis...*")
204
+ pragmatist_output = gr.Markdown("### The Pragmatist\n*Awaiting analysis...*")
205
+
206
+ with gr.Blocks(visible=False) as build_canvas:
207
+ with gr.Tabs():
208
+ with gr.Tab("v2 (Self-Corrected)"):
209
+ live_preview_v2 = gr.HTML()
210
+ with gr.Tab("v1 (Initial Draft)"):
211
+ live_preview_v1 = gr.HTML()
212
+ download_button = gr.File(label="Download Full Project (.zip)", visible=False, interactive=False)
213
+
214
+ # --- Event Handlers ---
215
+ def on_mode_change(mode):
216
+ return gr.update(visible=(mode == "Analyze Thought")), gr.update(visible=(mode == "Build Application"))
217
+ synthesis_mode.change(on_mode_change, inputs=synthesis_mode, outputs=[analysis_canvas, build_canvas])
218
+
219
+ synthesize_btn.click(
220
+ universal_synthesis,
221
+ inputs=[synthesis_mode, text_input],
222
+ outputs=[terminal_output, plot_3d, critic_output, visionary_output, pragmatist_output, download_button]
223
+ ).then(
224
+ # A second .then() block to handle the build canvas outputs separately, which is a more robust pattern.
225
+ lambda: (None, None), # Dummy function to trigger updates
226
+ None,
227
+ [live_preview_v1, live_preview_v2],
228
+ show_progress=False
229
+ )
230
+
231
+ if __name__ == "__main__":
232
+ demo.queue().launch(debug=True)