Lukeetah commited on
Commit
0348043
·
verified ·
1 Parent(s): 4849de0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +277 -267
app.py CHANGED
@@ -1,293 +1,303 @@
1
- # =======================================================================================
2
- # Artisan Nexus v1.0 - "Genesis"
3
- # Tu Estudio Personal de Ingeniería de Prompts
4
  #
5
- # Creado para constructores, artesanos y pioneros del futuro digital.
6
- # Este no es un generador. Es una forja.
7
- # =======================================================================================
 
8
 
9
  import gradio as gr
10
-
11
- # ---------------------------------------------------------------------------------------
12
- # I. CONSTANTES Y CONFIGURACIÓN DEL ESTUDIO
13
- # Define la identidad y la estructura de la aplicación.
14
- # ---------------------------------------------------------------------------------------
15
-
16
- APP_VERSION = "1.0 - Genesis"
17
- APP_TITLE = f"Artisan Nexus ({APP_VERSION})"
18
-
19
- # Define la paleta de colores para una apariencia profesional y única.
20
- THEME_COLOR_PRIMARY = "#4A90E2" # Un azul tecnológico y confiable
21
- THEME_COLOR_SECONDARY = "#50E3C2" # Un verde menta para la innovación
22
- THEME_COLOR_NEUTRAL = "#B8B8B8" # Gris claro para el texto
23
- THEME_FONT = ["'Segoe UI'", "system-ui", "sans-serif"]
24
- THEME_FONT_MONO = ["'SF Mono'", "'Consolas'", "monospace"]
25
-
26
- # Bloques de texto reutilizables para mantener la consistencia del marketing.
27
- MARKDOWN_HEADER = f"""
28
- <div style="text-align: center; margin-bottom: 20px;">
29
- <h1 style="color: {THEME_COLOR_PRIMARY}; font-size: 3em; margin-bottom: 0px;">Artisan Nexus</h1>
30
- <p style="color: {THEME_COLOR_NEUTRAL}; font-size: 1.2em; margin-top: 5px;">Tu Estudio Personal de Ingeniería de Prompts</p>
31
- </div>
32
- """
33
-
34
- MARKDOWN_FOOTER = """
35
- <hr>
36
- <div style="text-align: center; margin-top: 20px;">
37
- <p style="color: #B8B8B8; font-size: 0.9em;">
38
- Creado con ❤️ por un artesano digital.
39
- <br>
40
- ¿Quieres integrar esta filosofía en tu equipo o empresa?
41
- <a href="https://www.linkedin.com/" target="_blank" style="color: #50E3C2; text-decoration: none;">Hablemos.</a>
42
- </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  </div>
44
- """
45
 
46
- # ---------------------------------------------------------------------------------------
47
- # II. EL MOTOR DE LA FORJA (CORE LOGIC)
48
- # Aquí reside la inteligencia del artesano. Cada función es una herramienta especializada.
49
- # ---------------------------------------------------------------------------------------
50
 
51
- class PromptCraftsman:
52
- """El Maestro Artesano que contiene la lógica para forjar los prompts."""
 
53
 
54
- def _generate_output_blocks(self, crafted_prompt: str, insight: str, pro_tip: str) -> tuple:
55
- """
56
- Genera los bloques de salida estandarizados para la UI.
57
- Este método asegura consistencia en toda la aplicación.
58
- """
59
- # Bloque del Prompt Forjado
60
- prompt_block = gr.Textbox(
61
- label=" PROMPT FORJADO (Listo para copiar y pegar en tu IA favorita)",
62
- value=crafted_prompt,
63
- lines=10,
64
- interactive=False,
65
- show_copy_button=True,
66
- visible=True
67
- )
68
- # Bloque de la Visión del Artesano
69
- insight_block = gr.Markdown(
70
- f"""
71
- ### 🔬 Visión del Artesano: ¿Por qué funciona este prompt?
72
- {insight}
73
- """,
74
- visible=True
75
- )
76
- # Bloque del Consejo Profesional
77
- pro_tip_block = gr.Markdown(
78
- f"""
79
- ### 💡 Consejo Profesional:
80
- *"{pro_tip}"*
81
- """,
82
- visible=True
83
- )
84
- return prompt_block, insight_block, pro_tip_block
85
-
86
- def craft_diplomatic_email(self, recipient: str, role: str, goal: str, key_points: str, tone: str) -> tuple:
87
- """Forja un prompt para emails complejos y diplomáticos."""
88
- if not all([recipient, role, goal, key_points, tone]):
89
- return gr.Textbox(visible=False), gr.Markdown(visible=False), gr.Markdown(visible=False)
90
-
91
- crafted_prompt = f"""
92
- Actúa como un experto estratega en comunicación corporativa y redacción de emails. Tu misión es redactar un borrador de email claro, conciso y diplomático.
93
-
94
- **CONTEXTO DEL EMAIL:**
95
- - **Destinatario:** {recipient}
96
- - **Mi Rol:** {role}
97
- - **Objetivo Principal:** {goal}
98
- - **Tono Requerido:** {tone}
99
-
100
- **CONTENIDO OBLIGATORIO:**
101
- El email debe abordar, de manera estructurada y lógica, los siguientes puntos clave:
102
- {key_points}
103
-
104
- **INSTRUCCIONES DE FORMATO:**
105
- 1. **Asunto:** Crea un asunto breve y descriptivo que refleje el propósito del email.
106
- 2. **Apertura:** Comienza con un saludo profesional y una breve introducción que establezca el contexto.
107
- 3. **Cuerpo:** Desarrolla los puntos clave de forma clara y separada. Utiliza párrafos cortos.
108
- 4. **Cierre:** Concluye con un resumen de la acción deseada o el siguiente paso, y un cierre profesional.
109
- 5. **Revisión:** Asegúrate de que el lenguaje sea constructivo y esté alineado con el objetivo y el tono solicitados. Evita la ambigüedad.
110
- """
111
- insight = """
112
- Este prompt es eficaz porque utiliza la técnica **"Rol, Contexto, Instrucción"**.
113
- 1. **Rol (`Actúa como...`):** Pone a la IA en un modo experto específico.
114
- 2. **Contexto (`CONTEXTO DEL EMAIL`):** Le proporciona toda la información de fondo necesaria para evitar respuestas genéricas.
115
- 3. **Instrucción (`CONTENIDO OBLIGATORIO`, `INSTRUCCIONES DE FORMATO`):** Le da una estructura rígida y requisitos claros, forzando una salida de alta calidad y bien organizada.
116
- """
117
- pro_tip = "La IA proporciona el 90% del camino. Siempre lee el borrador en voz alta para ajustarlo a tu voz personal antes de enviarlo. El toque humano final es insustituible."
118
-
119
- return self._generate_output_blocks(crafted_prompt, insight, pro_tip)
120
-
121
- def craft_creative_content(self, topic: str, content_format: str, audience: str, style: str, goals: str) -> tuple:
122
- """Forja un prompt para la creación de contenido original."""
123
- if not all([topic, content_format, audience, style, goals]):
124
- return gr.Textbox(visible=False), gr.Markdown(visible=False), gr.Markdown(visible=False)
125
-
126
- crafted_prompt = f"""
127
- Actúa como un creador de contenido de clase mundial y estratega de marketing digital. Tu tarea es generar un borrador para una pieza de contenido excepcional.
128
-
129
- **BRIEF CREATIVO:**
130
- - **Tema Central:** {topic}
131
- - **Formato del Contenido:** {content_format}
132
- - **Audiencia Objetivo:** {audience}
133
- - **Estilo de Escritura Deseado:** {style}
134
- - **Objetivos de la Pieza (¿Qué quiero que la audiencia piense, sienta o haga?):** {goals}
135
-
136
- **DIRECTRICES DE CREACIÓN:**
137
- 1. **Gancho Inicial:** Comienza con una frase o párrafo de apertura que sea extremadamente cautivador y relevante para la audiencia objetivo.
138
- 2. **Desarrollo Estructurado:** Organiza el contenido de forma lógica. Si es un artículo, usa subtítulos. Si es un guion, usa escenas.
139
- 3. **Voz y Tono:** Mantén el estilo de escritura `{style}` de manera consistente en toda la pieza.
140
- 4. **Llamada a la Acción (CTA):** Integra de forma natural una llamada a la acción que se alinee con los objetivos definidos.
141
- 5. **Originalidad:** Evita clichés y frases comunes. Busca ángulos únicos y perspectivas frescas sobre el tema.
142
- """
143
- insight = """
144
- La clave de este prompt es el **"Brief Creativo"**. Al igual que en una agencia de publicidad, le damos a la IA un brief completo.
145
- - Definir la **Audiencia** y los **Objetivos** obliga a la IA a pensar no solo en el *qué* (el tema), sino en el *para quién* y el *para qué*.
146
- - Esto transforma una simple solicitud de texto en una tarea estratégica, resultando en un contenido mucho más enfocado y efectivo.
147
- """
148
- pro_tip = "Usa la primera respuesta de la IA como una lluvia de ideas. Pídele que te dé '10 ganchos iniciales alternativos' o '3 estructuras diferentes para este contenido'. La primera idea no siempre es la mejor."
149
-
150
- def craft_code_solution(self, language: str, task: str, constraints: str, code_snippet: str) -> tuple:
151
- """Forja un prompt para solucionar problemas de programación."""
152
- if not all([language, task]):
153
- return gr.Textbox(visible=False), gr.Markdown(visible=False), gr.Markdown(visible=False)
154
-
155
- context_code = f"\n**CÓDIGO EXISTENTE (para referencia o depuración):**\n```\n{code_snippet}\n```" if code_snippet else ""
156
- context_constraints = f"\n**RESTRICCIONES O REQUISITOS:**\n{constraints}" if constraints else ""
157
-
158
- crafted_prompt = f"""
159
- Actúa como un ingeniero de software senior experto en el lenguaje de programación **{language}**. Tu especialidad es escribir código limpio, eficiente y bien documentado.
160
-
161
- **TAREA A REALIZAR:**
162
- {task}
163
- {context_constraints}
164
- {context_code}
165
-
166
- **INSTRUCCIONES DE ENTREGA:**
167
- 1. **Solución en Código:** Proporciona el bloque de código completo y funcional en `{language}`.
168
- 2. **Explicación Detallada:** Debajo del código, añade una sección `### EXPLICACIÓN` donde describas paso a paso cómo funciona tu solución, las decisiones clave que tomaste y por qué.
169
- 3. **Buenas Prácticas:** Asegúrate de que el código siga las mejores prácticas del lenguaje, incluyendo nombres de variables claros y comentarios donde sea necesario.
170
- 4. **Eficiencia:** Considera la eficiencia (complejidad temporal y espacial) si es relevante para la tarea.
171
- """
172
- insight = """
173
- Este prompt funciona por su **rigurosa estructura de entrega**.
174
- - No solo pide el código, exige una **Explicación Detallada**. Esto obliga a la IA a "pensar en voz alta", lo que a menudo conduce a soluciones más correctas y robustas.
175
- - Separar la **Tarea** de las **Restricciones** y el **Código Existente** ayuda a la IA a organizar la información de entrada de manera más efectiva.
176
- """
177
- pro_tip = "Nunca copies y pegues código de una IA directamente en producción. Úsalo como un compañero de pair programming. Entiende cada línea que te da, cuestiónala y adáptala a tu proyecto."
178
 
 
 
 
 
179
 
180
- # ---------------------------------------------------------------------------------------
181
- # III. EL ESTUDIO (USER INTERFACE)
182
- # La construcción de la interfaz con Gradio. Es el espacio de trabajo del artesano.
183
- # ---------------------------------------------------------------------------------------
184
 
185
- class UIBuilder:
186
- """Construye la interfaz de usuario completa para Artisan Nexus."""
187
  def __init__(self):
188
- self.craftsman = PromptCraftsman()
189
- self.theme = gr.themes.Soft(
190
- primary_hue=gr.themes.colors.blue,
191
- secondary_hue=gr.themes.colors.cyan,
192
- font=THEME_FONT,
193
- font_mono=THEME_FONT_MONO
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  )
195
 
196
- def build_output_components(self):
197
- """Crea los componentes de salida, inicialmente invisibles."""
198
- with gr.Blocks() as output_area:
199
- with gr.Column(visible=False) as self.output_group:
200
- self.crafted_prompt_output = gr.Textbox(label="✅ PROMPT FORJADO", interactive=False)
201
- self.insight_output = gr.Markdown(visible=False)
202
- self.pro_tip_output = gr.Markdown(visible=False)
203
- return self.crafted_prompt_output, self.insight_output, self.pro_tip_output
204
-
205
- def build_diplomat_workbench(self):
206
- """Construye la interfaz para el Banco de Trabajo del Diplomático."""
207
- with gr.Tab("✉️ El Banco del Diplomático (Emails)"):
208
- with gr.Row():
209
- with gr.Column(scale=1):
210
- gr.Markdown("### 1. Define tu Misión Diplomática")
211
- recipient_input = gr.Textbox(label="¿Quién es el destinatario?", placeholder="Ej: Director de Marketing, Cliente potencial, etc.")
212
- role_input = gr.Textbox(label="¿Cuál es tu rol o relación con él?", placeholder="Ej: Analista de su equipo, Proveedor externo, etc.")
213
- goal_input = gr.Textbox(label="¿Cuál es tu objetivo principal?", placeholder="Ej: Conseguir aprobación para un proyecto, Resolver una queja, etc.")
214
- key_points_input = gr.Textbox(label="Puntos Clave a Incluir (uno por línea)", lines=4, placeholder="Ej:\n- Recordar el deadline del proyecto.\n- Solicitar los datos del informe Q3.\n- Proponer una breve reunión de 15 min.")
215
- tone_input = gr.Dropdown(label="Tono Deseado", choices=["Persuasivo", "Directo y al grano", "Empático y comprensivo", "Extremadamente formal", "Amistoso pero profesional"], value="Persuasivo")
216
- craft_button = gr.Button("Forjar Prompt de Email", variant="primary")
217
- with gr.Column(scale=2):
218
- gr.Markdown("### 2. El Resultado de la Forja")
219
- prompt, insight, tip = self.build_output_components()
220
 
221
- craft_button.click(
222
- fn=self.craftsman.craft_diplomatic_email,
223
- inputs=[recipient_input, role_input, goal_input, key_points_input, tone_input],
224
- outputs=[prompt, insight, tip]
225
- )
 
 
 
 
226
 
227
- def build_creator_workbench(self):
228
- """Construye la interfaz para el Banco de Trabajo del Creador."""
229
- with gr.Tab("🎨 El Estudio del Creador (Contenido)"):
230
  with gr.Row():
 
231
  with gr.Column(scale=1):
232
- gr.Markdown("### 1. Prepara tu Lienzo Creativo")
233
- topic_input = gr.Textbox(label="¿Cuál es el tema central?", placeholder="Ej: El futuro del trabajo remoto")
234
- format_input = gr.Dropdown(label="Formato del Contenido", choices=["Artículo de Blog", "Guion para video de YouTube (5 min)", "Hilo para Twitter/X", "Post de LinkedIn", "Letra de una canción"], value="Artículo de Blog")
235
- audience_input = gr.Textbox(label="¿Para quién es?", placeholder="Ej: Jóvenes profesionales de la tecnología")
236
- style_input = gr.Textbox(label="Estilo de Escritura Deseado", placeholder="Ej: Inspirador y visionario, Técnico y detallado, Divertido e irreverente")
237
- goals_input = gr.Textbox(label="Objetivos (¿Qué debe pensar/sentir/hacer la audiencia?)", placeholder="Ej: Sentirse optimistas sobre el futuro, Compartir el post, etc.")
238
- craft_button = gr.Button("Forjar Prompt Creativo", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  with gr.Column(scale=2):
240
- gr.Markdown("### 2. La Obra Maestra")
241
- prompt, insight, tip = self.build_output_components()
242
-
243
- craft_button.click(
244
- fn=self.craftsman.craft_creative_content,
245
- inputs=[topic_input, format_input, audience_input, style_input, goals_input],
246
- outputs=[prompt, insight, tip]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  )
248
 
249
- def build_coder_workbench(self):
250
- """Construye la interfaz para el Banco de Trabajo del Programador."""
251
- with gr.Tab("🛠️ La Forja del Programador (Código)"):
252
- with gr.Row():
253
- with gr.Column(scale=1):
254
- gr.Markdown("### 1. Define el Plano Técnico")
255
- lang_input = gr.Dropdown(label="Lenguaje de Programación", choices=["Python", "JavaScript", "SQL", "Java", "C++", "HTML/CSS", "Bash"], value="Python")
256
- task_input = gr.Textbox(label="Describe la tarea de programación", placeholder="Ej: Crear una función que lea un CSV y devuelva el promedio de una columna.", lines=3)
257
- constraints_input = gr.Textbox(label="Restricciones o Requisitos (Opcional)", placeholder="Ej: No usar la librería pandas, La función debe manejar archivos grandes, etc.")
258
- snippet_input = gr.Code(label="Pega aquí tu código existente (Opcional)", language="python", lines=5)
259
- craft_button = gr.Button("Forjar Prompt de Código", variant="primary")
260
- with gr.Column(scale=2):
261
- gr.Markdown("### 2. La Solución Compilada")
262
- prompt, insight, tip = self.build_output_components()
263
 
264
- # Actualizar dinámicamente el lenguaje del snippet
265
- lang_input.change(lambda x: gr.Code(language=x.lower()), inputs=lang_input, outputs=snippet_input)
266
-
267
- craft_button.click(
268
- fn=self.craftsman.craft_code_solution,
269
- inputs=[lang_input, task_input, constraints_input, snippet_input],
270
- outputs=[prompt, insight, tip]
271
  )
 
 
 
272
 
273
- def launch(self):
274
- """Construye y lanza la aplicación Gradio completa."""
275
- with gr.Blocks(theme=self.theme, title=APP_TITLE) as app:
276
- gr.Markdown(MARKDOWN_HEADER)
277
- with gr.Tabs():
278
- self.build_diplomat_workbench()
279
- self.build_creator_workbench()
280
- self.build_coder_workbench()
281
- gr.Markdown(MARKDOWN_FOOTER)
282
-
283
- # Lanza la aplicación con la cola habilitada para manejar múltiples usuarios.
284
  app.queue().launch(show_error=True)
285
 
286
- # ---------------------------------------------------------------------------------------
287
- # IV. PUNTO DE ENTRADA DE LA APLICACIÓN
288
- # El "main" que enciende la forja.
289
- # ---------------------------------------------------------------------------------------
290
-
291
  if __name__ == "__main__":
292
- studio = UIBuilder()
293
- studio.launch()
 
1
+ # ==================================================================================================
2
+ # SYNAPSE v0.9 (Codename: "Prometheus")
3
+ # The Dynamic Prompting Environment
4
  #
5
+ # PHILOSOPHY:
6
+ # We don't generate prompts. We architect instructions. We build workflows.
7
+ # This is not a tool, it is a laboratory for command and control of generative AI.
8
+ # ==================================================================================================
9
 
10
  import gradio as gr
11
+ import uuid
12
+ import json
13
+
14
+ # --------------------------------------------------------------------------------------------------
15
+ # I. CORE BLUEPRINTS & CONFIGURATION
16
+ # The DNA of the Synapse Environment. Defines the capabilities of each Node.
17
+ # --------------------------------------------------------------------------------------------------
18
+
19
+ class NodeBlueprint:
20
+ """Defines the structure and capabilities of a functional node in the Synapse chain."""
21
+
22
+ NODE_TEMPLATES = {
23
+ "strategic_comm": {
24
+ "name": "Strategic Communicator",
25
+ "description": "For crafting complex, high-stakes communication (emails, memos, announcements).",
26
+ "icon": "📨",
27
+ "inputs": [
28
+ {"label": "Audience Profile", "placeholder": "E.g., 'C-Suite Executives, skeptical but data-driven'"},
29
+ {"label": "Primary Objective", "placeholder": "E.g., 'Secure funding for Project Phoenix'"},
30
+ {"label": "Key Information Payloads (one per line)", "lines": 4, "placeholder": "- Q2 results exceeded projections by 15%.\n- The project has a 6-month ROI timeline.\n- We have a lead engineer ready to start."},
31
+ {"label": "Desired Tone & Voice", "choices": ["Assertive & Confident", "Empathetic & Collaborative", "Urgent & Action-Oriented", "Formal & Deferential"], "value": "Assertive & Confident"},
32
+ ],
33
+ "refinement_actions": ["make_more_concise", "increase_persuasion", "add_data_focus", "soften_tone"]
34
+ },
35
+ "creative_ideation": {
36
+ "name": "Creative Ideation Engine",
37
+ "description": "For brainstorming and generating novel concepts from a single spark.",
38
+ "icon": "💡",
39
+ "inputs": [
40
+ {"label": "Core Concept or Theme", "placeholder": "E.g., 'The future of decentralized cities'"},
41
+ {"label": "Output Format", "choices": ["5 Blog Post Titles", "3 YouTube Video Concepts", "10 Tweet-sized Ideas", "A one-paragraph story starter"], "value": "5 Blog Post Titles"},
42
+ {"label": "Creative Constraint", "placeholder": "E.g., 'Must be optimistic in tone', 'Avoid using tech jargon'"},
43
+ ],
44
+ "refinement_actions": ["make_more_provocative", "explore_contrarian_angle", "target_a_niche_audience", "simplify_for_beginners"]
45
+ },
46
+ "technical_architect": {
47
+ "name": "Technical Architect",
48
+ "description": "For designing code logic, solving bugs, and explaining complex systems.",
49
+ "icon": "⚙️",
50
+ "inputs": [
51
+ {"label": "Programming Language / Tech Stack", "value": "Python"},
52
+ {"label": "Core Task or Problem", "lines": 3, "placeholder": "E.g., 'Design a Python function to asynchronously fetch data from multiple APIs and aggregate the results.'"},
53
+ {"label": "Key Constraints or Requirements", "placeholder": "E.g., 'Must use the asyncio library, must include error handling for failed requests.'"},
54
+ ],
55
+ "refinement_actions": ["add_step_by_step_explanation", "generate_code_comments", "write_testing_plan", "optimize_for_performance"]
56
+ }
57
+ }
58
+
59
+ # --------------------------------------------------------------------------------------------------
60
+ # II. THE SYNAPSE ENGINE
61
+ # The core logic that powers the creation and refinement of prompt chains.
62
+ # --------------------------------------------------------------------------------------------------
63
+
64
+ class SynapseEngine:
65
+ """The intelligent engine that translates user intent into architected prompt instructions."""
66
+
67
+ def _render_prompt_anatomy(self, prompt_text: str) -> str:
68
+ """Visualizes the prompt's structure with Markdown and HTML for clarity."""
69
+ # This is a simplified visualization. A more complex version could use regex to tag parts.
70
+ return f"""
71
+ <div style="border: 1px solid #444; padding: 15px; border-radius: 8px; background-color: #1a1a1a;">
72
+ <details>
73
+ <summary><strong>🔬 Ver Anatomía del Prompt</strong></summary>
74
+ <pre><code style="color: #e0e0e0; white-space: pre-wrap;">{prompt_text}</code></pre>
75
+ </details>
76
  </div>
77
+ """
78
 
79
+ def craft_node_output(self, node_id: str, *args) -> dict:
80
+ """Crafts a single, structured node for the chain."""
81
+ template = NodeBlueprint.NODE_TEMPLATES.get(node_id)
82
+ if not template: return None
83
 
84
+ # Basic validation
85
+ if not all(str(arg).strip() for arg in args):
86
+ return None
87
 
88
+ prompt = f"## PROMPT DIRECTIVE: ACT AS {template['name'].upper()} ##\n\n"
89
+ prompt += f"**MISSION CONTEXT:**\n"
90
+ for i, input_field in enumerate(template['inputs']):
91
+ prompt += f"- {input_field['label']}: {args[i]}\n"
92
+
93
+ prompt += f"\n**PRIMARY EXECUTION DIRECTIVE:**\nBased on the context, generate the specified output, adhering strictly to the defined format and constraints. The output must be of expert-level quality, demonstrating deep domain knowledge and strategic insight."
94
+
95
+ explanation = f"This node establishes a high-level **Expert Persona** ('{template['name']}') and provides a structured **Mission Context**. This forces the AI to move beyond generic responses and adopt a specific, professional mindset, leading to vastly superior results."
96
+
97
+ return {
98
+ "id": str(uuid.uuid4()),
99
+ "node_type": template['name'],
100
+ "icon": template['icon'],
101
+ "prompt": prompt,
102
+ "explanation": explanation,
103
+ "refinements_applied": []
104
+ }
105
+
106
+ def refine_node_prompt(self, prompt: str, action: str) -> str:
107
+ """Applies a refinement action to an existing prompt string."""
108
+ refinement_map = {
109
+ "make_more_concise": "\n\n**REFINEMENT DIRECTIVE:** Review the entire response and condense it by 25-40% without losing critical information. Prioritize clarity and impact.",
110
+ "increase_persuasion": "\n\n**REFINEMENT DIRECTIVE:** Re-evaluate the prompt's output to maximize its persuasive power. Employ rhetorical devices, strengthen the call-to-action, and appeal directly to the audience's motivations.",
111
+ "add_data_focus": "\n\n**REFINEMENT DIRECTIVE:** Enhance the output by integrating real or hypothetical quantitative data and metrics to support all claims. The tone should be analytical and evidence-based.",
112
+ "soften_tone": "\n\n**REFINEMENT DIRECTIVE:** Adjust the language to be more collaborative, empathetic, and less confrontational. Use inclusive phrasing and acknowledge potential alternative viewpoints.",
113
+ "make_more_provocative": "\n\n**REFINEMENT DIRECTIVE:** Inject a bold, contrarian, or highly provocative element into the output. Challenge a common assumption. The goal is to spark debate and capture attention.",
114
+ "add_step_by_step_explanation": "\n\n**REFINEMENT DIRECTIVE:** Append a detailed, step-by-step explanation to the primary output. Assume the reader is intelligent but a novice in this specific domain. Use analogies.",
115
+ }
116
+ # Add a placeholder for unimplemented actions
117
+ refinement_instruction = refinement_map.get(action, f"\n\n**REFINEMENT DIRECTIVE:** Apply the concept of '{action.replace('_', ' ')}' to the output.")
118
+
119
+ # Avoid duplicating refinement instructions
120
+ if refinement_instruction in prompt:
121
+ return prompt
122
+
123
+ return prompt + refinement_instruction
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
+ # --------------------------------------------------------------------------------------------------
126
+ # III. THE LAB ENVIRONMENT (UI)
127
+ # The Gradio interface. Designed to feel like a professional, dynamic workspace.
128
+ # --------------------------------------------------------------------------------------------------
129
 
130
+ class SynapseUI:
131
+ """Builds and manages the Gradio user interface for the Synapse Environment."""
 
 
132
 
 
 
133
  def __init__(self):
134
+ self.engine = SynapseEngine()
135
+ self.css = """
136
+ :root { --syn-c-primary: #00A9FF; --syn-c-secondary: #89CFF3; --syn-c-background: #0d1117; --syn-c-surface: #161b22; --syn-c-text: #c9d1d9; }
137
+ body, .gradio-container { background-color: var(--syn-c-background); color: var(--syn-c-text); font-family: 'Inter', sans-serif; }
138
+ #chain_display { border: 1px solid #30363d; border-radius: 8px; padding: 1em; min-height: 400px; background-color: var(--syn-c-surface); }
139
+ .node-card { border: 1px solid #30363d; border-radius: 12px; padding: 1em; margin-bottom: 1em; background-color: rgba(0, 169, 255, 0.05); }
140
+ .node-header { display: flex; align-items: center; font-size: 1.5em; font-weight: 600; color: var(--syn-c-secondary); }
141
+ .node-icon { font-size: 1.5em; margin-right: 0.5em; }
142
+ button { border-radius: 8px !important; }
143
+ """
144
+ self.theme = gr.themes.Base(
145
+ primary_hue="blue",
146
+ secondary_hue="cyan",
147
+ font="'Inter', sans-serif"
148
+ ).set(
149
+ body_background_fill="var(--syn-c-background)",
150
+ block_background_fill="var(--syn-c-surface)",
151
+ block_border_width="0px",
152
+ body_text_color="var(--syn-c-text)",
153
+ button_primary_background_fill="var(--syn-c-primary)",
154
+ button_primary_text_color="#FFFFFF",
155
+ button_secondary_background_fill="#30363d",
156
+ button_secondary_text_color="#FFFFFF",
157
  )
158
 
159
+ def _render_chain_display(self, chain_data: list) -> str:
160
+ """Renders the current prompt chain as a rich Markdown string."""
161
+ if not chain_data:
162
+ return "<div style='text-align: center; padding: 5em 0;'><p style='font-size: 1.2em; color: #888;'>Your Prompt Chain is empty.</p><p style='color: #666;'>Select a Node Type from the Workshop to begin.</p></div>"
163
+
164
+ html = ""
165
+ for i, node in enumerate(chain_data):
166
+ refinements_str = ", ".join(r.replace("_", " ").title() for r in node['refinements_applied'])
167
+ refinements_html = f"<p style='color: #89CFF3; font-size: 0.9em;'><strong>Refinements:</strong> {refinements_str}</p>" if refinements_str else ""
168
+
169
+ html += f"""
170
+ <div class='node-card'>
171
+ <div class='node-header'><span class='node-icon'>{node['icon']}</span><span>Node {i+1}: {node['node_type']}</span></div>
172
+ <hr style='border-color: #30363d;'>
173
+ <p><strong>// Rationale //</strong><br>{node['explanation']}</p>
174
+ {refinements_html}
175
+ {self.engine._render_prompt_anatomy(node['prompt'])}
176
+ </div>
177
+ """
178
+ if i < len(chain_data) - 1:
179
+ html += "<div style='text-align: center; font-size: 2em; color: #444; margin: -0.5em 0;'>↓</div>"
180
+
181
+ return html
 
182
 
183
+ def launch(self):
184
+ """Builds and launches the full Gradio application."""
185
+ with gr.Blocks(theme=self.theme, css=self.css, title="SYNAPSE") as app:
186
+ # STATE MANAGEMENT
187
+ chain_state = gr.State([]) # Holds the list of node dicts
188
+ active_node_id = gr.State(None)
189
+
190
+ # HEADER
191
+ gr.HTML("""<div style='text-align: center; padding: 2rem 0;'><h1 style='color: #00A9FF; font-size: 3rem; font-weight: 800; margin: 0;'>S Y N A P S E</h1><p style='color: #89CFF3; font-size: 1.2rem;'>The Dynamic Prompting Environment</p></div>""")
192
 
 
 
 
193
  with gr.Row():
194
+ # LEFT COLUMN: THE WORKSHOP (INPUTS)
195
  with gr.Column(scale=1):
196
+ gr.Markdown("### <strong>1. The Workshop</strong>")
197
+ node_selector = gr.Dropdown(
198
+ label="Select Node Type to Add",
199
+ choices=[(d['name'], k) for k, d in NodeBlueprint.NODE_TEMPLATES.items()],
200
+ value=None
201
+ )
202
+
203
+ # Create input groups for all node types, initially hidden
204
+ input_groups = {}
205
+ for node_id, template in NodeBlueprint.NODE_TEMPLATES.items():
206
+ with gr.Group(visible=False) as input_groups[node_id]:
207
+ gr.Markdown(f"#### {template['icon']} {template['name']}")
208
+ gr.Markdown(f"<p style='font-size:0.9em; color:#888;'>{template['description']}</p>")
209
+ inputs = []
210
+ for field in template['inputs']:
211
+ if 'choices' in field:
212
+ inputs.append(gr.Dropdown(label=field['label'], choices=field['choices'], value=field.get('value')))
213
+ else:
214
+ inputs.append(gr.Textbox(label=field['label'], placeholder=field.get('placeholder', ''), lines=field.get('lines', 1)))
215
+ input_groups[node_id].__setattr__("inputs", inputs)
216
+
217
+ add_node_button = gr.Button("Add Node to Chain", variant="primary", visible=False)
218
+
219
+ # REFINEMENT WORKBENCH (dynamically populated)
220
+ with gr.Group(visible=False) as refinement_group:
221
+ gr.Markdown("### <strong>3. Refinement Workbench</strong>")
222
+ gr.Markdown("<p style='font-size:0.9em; color:#888;'>Mutate the **last node** in the chain.</p>")
223
+ refinement_buttons = []
224
+ all_actions = set(a for t in NodeBlueprint.NODE_TEMPLATES.values() for a in t['refinement_actions'])
225
+ for action in all_actions:
226
+ btn = gr.Button(action.replace("_", " ").title(), visible=False)
227
+ refinement_buttons.append((action, btn))
228
+
229
+ clear_chain_button = gr.Button("Clear Entire Chain", variant="secondary")
230
+
231
+ # RIGHT COLUMN: THE CHAIN DISPLAY
232
  with gr.Column(scale=2):
233
+ gr.Markdown("### <strong>2. The Prompt Chain</strong>")
234
+ chain_display = gr.HTML(self._render_chain_display([]), elem_id="chain_display")
235
+
236
+ # EVENT HANDLING LOGIC
237
+ def on_node_select(node_id):
238
+ active_node_id.value = node_id
239
+ updates = {group: gr.update(visible=k==node_id) for k, group in input_groups.items()}
240
+ updates[add_node_button] = gr.update(visible=bool(node_id))
241
+ return updates
242
+
243
+ def add_node_to_chain(chain_data, node_id, *inputs):
244
+ node_output = self.engine.craft_node_output(node_id, *inputs)
245
+ if node_output:
246
+ chain_data.append(node_output)
247
+
248
+ # Update refinement buttons visibility
249
+ refinement_updates = {}
250
+ last_node_actions = set(NodeBlueprint.NODE_TEMPLATES[node_id]['refinement_actions'])
251
+ for action, btn in refinement_buttons:
252
+ refinement_updates[btn] = gr.update(visible=action in last_node_actions)
253
+
254
+ return {
255
+ chain_state: chain_data,
256
+ chain_display: self._render_chain_display(chain_data),
257
+ refinement_group: gr.update(visible=True),
258
+ **refinement_updates
259
+ }
260
+
261
+ def apply_refinement(chain_data, action):
262
+ if not chain_data: return chain_data, self._render_chain_display(chain_data)
263
+
264
+ last_node = chain_data[-1]
265
+ # Avoid applying the same refinement twice
266
+ if action not in last_node["refinements_applied"]:
267
+ original_prompt = last_node["prompt"]
268
+ refined_prompt = self.engine.refine_node_prompt(original_prompt, action)
269
+ last_node["prompt"] = refined_prompt
270
+ last_node["refinements_applied"].append(action)
271
+
272
+ return chain_data, self._render_chain_display(chain_data)
273
+
274
+ # Connect events to functions
275
+ node_selector.change(on_node_select, inputs=node_selector, outputs=[active_node_id, add_node_button] + list(input_groups.values()))
276
+
277
+ add_node_button.click(
278
+ add_node_to_chain,
279
+ inputs=[chain_state, active_node_id] + list(inp for grp in input_groups.values() for inp in grp.inputs),
280
+ outputs=[chain_state, chain_display, refinement_group] + [b for _, b in refinement_buttons]
281
  )
282
 
283
+ for action, btn in refinement_buttons:
284
+ btn.click(
285
+ apply_refinement,
286
+ inputs=[chain_state, gr.State(action)],
287
+ outputs=[chain_state, chain_display]
288
+ )
 
 
 
 
 
 
 
 
289
 
290
+ clear_chain_button.click(
291
+ lambda: ([], self._render_chain_display([]), gr.update(visible=False)),
292
+ None,
293
+ [chain_state, chain_display, refinement_group]
 
 
 
294
  )
295
+
296
+ # FOOTER
297
+ gr.Markdown("<hr style='border-color:#30363d;'><div style='text-align:center;color:#888;'>SYNAPSE v0.9 // Forging the future of human-AI interaction. <a href='https://www.linkedin.com/' target='_blank' style='color:#00A9FF;'>Let's connect.</a></div>")
298
 
 
 
 
 
 
 
 
 
 
 
 
299
  app.queue().launch(show_error=True)
300
 
 
 
 
 
 
301
  if __name__ == "__main__":
302
+ ui = SynapseUI()
303
+ ui.launch()