ZahirJS commited on
Commit
1dbebbe
·
verified ·
1 Parent(s): 0e09093

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -154
app.py CHANGED
@@ -1,174 +1,119 @@
1
  import gradio as gr
2
- import json
3
- from graphviz import Digraph
4
- import os
5
- from tempfile import NamedTemporaryFile
6
- from sample_data import COMPLEX_SAMPLE_JSON # El JSON de ejemplo se mantiene sin cambios
7
 
8
- def generate_concept_map(json_input: str) -> str:
 
 
 
 
 
 
9
  """
10
- Generate concept map from JSON and return as image file
11
-
12
- Args:
13
- json_input (str): JSON describing the concept map structure.
14
-
15
- REQUIRED FORMAT EXAMPLE:
16
- {
17
- "central_node": "AI",
18
- "nodes": [
19
- {
20
- "id": "ml",
21
- "label": "Machine Learning",
22
- "relationship": "subcategory",
23
- "subnodes": [
24
- {
25
- "id": "dl",
26
- "label": "Deep Learning",
27
- "relationship": "type",
28
- "subnodes": [
29
- {
30
- "id": "cnn",
31
- "label": "CNN",
32
- "relationship": "architecture"
33
- }
34
- ]
35
- }
36
- ]
37
- }
38
- ]
39
- }
40
-
41
- Returns:
42
- str: Path to generated PNG image file
43
  """
44
- try:
45
- if not json_input.strip():
46
- return "Error: Empty input"
47
-
48
- data = json.loads(json_input)
49
-
50
- if 'central_node' not in data or 'nodes' not in data:
51
- raise ValueError("Missing required fields: central_node or nodes")
52
-
53
- dot = Digraph(
54
- name='ConceptMap',
55
- format='png',
56
- graph_attr={
57
- 'rankdir': 'TB', # Top-to-Bottom
58
- 'splines': 'ortho', # Straight lines
59
- 'bgcolor': 'white', # Fondo blanco
60
- 'pad': '0.5' # ¡Este es el margen! 0.5 pulgadas
61
- }
62
- )
63
-
64
- # Base color for the central node
65
- base_color = '#19191a' # Casi negro
66
-
67
- # Central node (now a rounded box)
68
- dot.node(
69
- 'central',
70
- data['central_node'],
71
- shape='box', # Ahora es un rectángulo
72
- style='filled,rounded', # Redondeado
73
- fillcolor=base_color, # Color base
74
- fontcolor='white',
75
- fontsize='16' # Un poco más grande para el título
76
- )
77
-
78
- # Helper function to recursively add nodes and edges
79
- def add_nodes_and_edges(parent_id, nodes_list, current_depth=0):
80
- # Calculate color for current depth, making it lighter
81
- lightening_factor = 0.12 # How much lighter each level gets
82
-
83
- # Convert base_color hex to RGB
84
- base_r = int(base_color[1:3], 16)
85
- base_g = int(base_color[3:5], 16)
86
- base_b = int(base_color[5:7], 16)
87
-
88
- # Calculate current node color
89
- current_r = base_r + int((255 - base_r) * current_depth * lightening_factor)
90
- current_g = base_g + int((255 - base_g) * current_depth * lightening_factor)
91
- current_b = base_b + int((255 - base_b) * current_depth * lightening_factor)
92
-
93
- # Clamp values to 255
94
- current_r = min(255, current_r)
95
- current_g = min(255, current_g)
96
- current_b = min(255, current_b)
97
-
98
- node_fill_color = f'#{current_r:02x}{current_g:02x}{current_b:02x}'
99
-
100
- # Font color: white for dark nodes, black for very light nodes
101
- font_color = 'white' if current_depth * lightening_factor < 0.6 else 'black'
102
-
103
- # Edge colors can remain constant or change. Let's make them slightly visible.
104
- edge_color = '#4a4a4a' # Un gris oscuro para las líneas
105
- font_size = max(9, 14 - (current_depth * 2)) # Adjust font size based on depth
106
- edge_font_size = max(7, 10 - (current_depth * 1))
107
-
108
- for node in nodes_list:
109
- node_id = node.get('id')
110
- label = node.get('label')
111
- relationship = node.get('relationship')
112
-
113
- if not all([node_id, label, relationship]):
114
- raise ValueError(f"Invalid node: {node}")
115
-
116
- dot.node(
117
- node_id,
118
- label,
119
- shape='box', # Rectángulo
120
- style='filled,rounded', # Redondeado
121
- fillcolor=node_fill_color,
122
- fontcolor=font_color,
123
- fontsize=str(font_size)
124
- )
125
-
126
- dot.edge(
127
- parent_id,
128
- node_id,
129
- label=relationship,
130
- color=edge_color,
131
- fontcolor=edge_color, # Color de la fuente de la arista también gris
132
- fontsize=str(edge_font_size)
133
- )
134
-
135
- if 'subnodes' in node:
136
- add_nodes_and_edges(node_id, node['subnodes'], current_depth + 1)
137
-
138
- # Start processing from the top-level nodes connected to the central node
139
- add_nodes_and_edges('central', data.get('nodes', []), current_depth=1) # Initial depth is 1 for nodes under central
140
-
141
- # Save to temporary file
142
- with NamedTemporaryFile(delete=False, suffix='.png') as tmp:
143
- dot.render(tmp.name, format='png', cleanup=True)
144
- return tmp.name + '.png'
145
-
146
- except json.JSONDecodeError:
147
- return "Error: Invalid JSON format"
148
- except Exception as e:
149
- return f"Error: {str(e)}"
150
-
151
- if __name__ == "__main__":
152
- demo = gr.Interface(
153
- fn=generate_concept_map,
154
  inputs=gr.Textbox(
155
- value=COMPLEX_SAMPLE_JSON,
156
  placeholder="Paste JSON following the documented format",
157
  label="Structured JSON Input",
158
  lines=25
159
  ),
160
  outputs=gr.Image(
161
- label="Generated Concept Map",
162
  type="filepath",
163
  show_download_button=True
164
  ),
165
- title="AI Concept Map (Custom Style)",
166
- description="Generates an AI concept map with custom rounded boxes, color gradient, and white background."
167
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
  demo.launch(
170
  mcp_server=True,
171
  share=False,
172
  server_port=7860,
173
  server_name="0.0.0.0"
174
- )
 
 
1
  import gradio as gr
 
 
 
 
 
2
 
3
+ # Import generator functions and sample JSONs
4
+ from concept_map_generator import generate_concept_map
5
+ from synoptic_chart_generator import generate_synoptic_chart
6
+ from radial_diagram_generator import generate_radial_diagram
7
+ from sample_data import CONCEPT_MAP_JSON, SYNOPTIC_CHART_JSON, RADIAL_DIAGRAM_JSON
8
+
9
+ def create_interface(generator_fn, sample_json, title, description):
10
  """
11
+ Helper function to create a Gradio Interface for a specific generator.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  """
13
+ return gr.Interface(
14
+ fn=generator_fn,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  inputs=gr.Textbox(
16
+ value=sample_json,
17
  placeholder="Paste JSON following the documented format",
18
  label="Structured JSON Input",
19
  lines=25
20
  ),
21
  outputs=gr.Image(
22
+ label="Generated Graph",
23
  type="filepath",
24
  show_download_button=True
25
  ),
26
+ title=title,
27
+ description=description
28
  )
29
+
30
+ if __name__ == "__main__":
31
+ with gr.Blocks(
32
+ title="Advanced Graph Generator",
33
+ css="""
34
+ .gradio-container {
35
+ font-family: 'Inter', sans-serif !important;
36
+ }
37
+ .gr-tab-item {
38
+ padding: 10px 20px;
39
+ font-size: 1.1em;
40
+ font-weight: bold;
41
+ }
42
+ .gr-button {
43
+ border-radius: 8px;
44
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
45
+ background-color: #4CAF50; /* Green color for buttons */
46
+ color: white;
47
+ padding: 10px 20px;
48
+ font-size: 1.1em;
49
+ }
50
+ .gr-button:hover {
51
+ background-color: #45a049;
52
+ }
53
+ .gr-textbox {
54
+ border-radius: 8px;
55
+ padding: 10px;
56
+ }
57
+ .gradio-container.dark { /* Tailwind dark mode for overall container if needed */
58
+ --tw-bg-opacity: 1;
59
+ background-color: rgb(24 24 27 / var(--tw-bg-opacity)); /* bg-zinc-900 */
60
+ color: #d4d4d8; /* text-zinc-300 */
61
+ }
62
+ .gradio-container.dark .gr-textbox {
63
+ background-color: rgb(39 39 42 / var(--tw-bg-opacity)); /* bg-zinc-800 */
64
+ color: #d4d4d8;
65
+ border-color: #52525b; /* border-zinc-600 */
66
+ }
67
+ .gradio-container.dark .gr-tab-item {
68
+ color: #d4d4d8;
69
+ }
70
+ .gradio-container.dark .gr-tab-item.selected {
71
+ background-color: rgb(39 39 42 / var(--tw-bg-opacity));
72
+ color: #fff;
73
+ }
74
+ """
75
+ ) as demo:
76
+ gr.Markdown(
77
+ """
78
+ # Advanced Graph Generation Suite
79
+ Choose a graph type and provide your JSON data to generate a visual representation.
80
+ All graphs maintain a consistent, elegant style with rounded boxes,
81
+ a dark-to-light color gradient, and a clean white background.
82
+ """
83
+ )
84
+
85
+ with gr.Tabs():
86
+ with gr.TabItem("Concept Map"):
87
+ concept_map_interface = create_interface(
88
+ generate_concept_map,
89
+ CONCEPT_MAP_JSON,
90
+ "Concept Map Generator (Vertical Hierarchy)",
91
+ "Creates a hierarchical concept map, ideal for breaking down complex topics."
92
+ )
93
+ concept_map_interface.render() # Render the interface within the tab
94
+
95
+ with gr.TabItem("Synoptic Chart"):
96
+ synoptic_chart_interface = create_interface(
97
+ generate_synoptic_chart,
98
+ SYNOPTIC_CHART_JSON,
99
+ "Synoptic Chart Generator (Horizontal Hierarchy)",
100
+ "Generates a horizontal synoptic chart, perfect for outlining processes or structures."
101
+ )
102
+ synoptic_chart_interface.render() # Render the interface within the tab
103
+
104
+ with gr.TabItem("Radial Diagram"):
105
+ radial_diagram_interface = create_interface(
106
+ generate_radial_diagram,
107
+ RADIAL_DIAGRAM_JSON,
108
+ "Radial Diagram Generator (Central Expansion)",
109
+ "Creates a diagram expanding from a central idea, visualizing interconnected concepts."
110
+ )
111
+ radial_diagram_interface.render() # Render the interface within the tab
112
 
113
  demo.launch(
114
  mcp_server=True,
115
  share=False,
116
  server_port=7860,
117
  server_name="0.0.0.0"
118
+ )
119
+