Graphify / app.py
ZahirJS's picture
Update app.py
028a336 verified
raw
history blame
7.16 kB
import gradio as gr
import json
from graphviz import Digraph
import os
from tempfile import NamedTemporaryFile
def generate_concept_map(json_input: str) -> str:
"""
Generate concept map from JSON and return as image file
Args:
json_input (str): JSON describing the concept map structure.
REQUIRED FORMAT EXAMPLE:
{
"central_node": "AI",
"nodes": [
{
"id": "ml",
"label": "Machine Learning",
"relationship": "subcategory",
"subnodes": [
{
"id": "dl",
"label": "Deep Learning",
"relationship": "type",
"subnodes": [
{
"id": "cnn",
"label": "CNN",
"relationship": "architecture"
}
]
}
]
}
]
}
Returns:
str: Path to generated PNG image file
"""
try:
if not json_input.strip():
return "Error: Empty input"
data = json.loads(json_input)
if 'central_node' not in data or 'nodes' not in data:
raise ValueError("Missing required fields: central_node or nodes")
# Create graph
dot = Digraph(
name='ConceptMap',
format='png',
graph_attr={
'rankdir': 'TB',
'splines': 'ortho',
'bgcolor': 'transparent'
}
)
# Central node (ellipse)
dot.node(
'central',
data['central_node'],
shape='ellipse',
style='filled',
fillcolor='#2196F3',
fontcolor='white',
fontsize='14'
)
# Process nodes (rectangles)
for node in data['nodes']:
node_id = node.get('id')
label = node.get('label')
relationship = node.get('relationship')
# Validate node
if not all([node_id, label, relationship]):
raise ValueError(f"Invalid node: {node}")
# Create main node (rectangle)
dot.node(
node_id,
label,
shape='box',
style='filled',
fillcolor='#4CAF50',
fontcolor='white',
fontsize='12'
)
# Connect to central node
dot.edge(
'central',
node_id,
label=relationship,
color='#9C27B0',
fontsize='10'
)
# Process subnodes (rectangles with lighter fill)
for subnode in node.get('subnodes', []):
sub_id = subnode.get('id')
sub_label = subnode.get('label')
sub_rel = subnode.get('relationship')
if not all([sub_id, sub_label, sub_rel]):
raise ValueError(f"Invalid subnode: {subnode}")
dot.node(
sub_id,
sub_label,
shape='box',
style='filled',
fillcolor='#FFA726',
fontcolor='white',
fontsize='10'
)
dot.edge(
node_id,
sub_id,
label=sub_rel,
color='#E91E63',
fontsize='8'
)
# Save to temporary file
with NamedTemporaryFile(delete=False, suffix='.png') as tmp:
dot.render(tmp.name, format='png', cleanup=True)
return tmp.name + '.png'
except json.JSONDecodeError:
return "Error: Invalid JSON format"
except Exception as e:
return f"Error: {str(e)}"
if __name__ == "__main__":
# Complex sample JSON
sample_json = """
{
"central_node": "Artificial Intelligence (AI)",
"nodes": [
{
"id": "ml",
"label": "Machine Learning",
"relationship": "Core Component",
"subnodes": [
{
"id": "sl",
"label": "Supervised Learning",
"relationship": "Learning Type",
"subnodes": [
{
"id": "reg",
"label": "Regression",
"relationship": "Technique",
"subnodes": [
{"id": "lr", "label": "Linear Regression", "relationship": "Algorithm"}
]
},
{
"id": "clf",
"label": "Classification",
"relationship": "Technique",
"subnodes": [
{"id": "svm", "label": "SVM", "relationship": "Algorithm"},
{"id": "rf", "label": "Random Forest", "relationship": "Algorithm"}
]
}
]
},
{
"id": "ul",
"label": "Unsupervised Learning",
"relationship": "Learning Type",
"subnodes": [
{
"id": "clus",
"label": "Clustering",
"relationship": "Technique",
"subnodes": [
{"id": "kmeans", "label": "K-Means", "relationship": "Algorithm"}
]
}
]
}
]
},
{
"id": "nlp",
"label": "NLP",
"relationship": "Application Domain",
"subnodes": [
{
"id": "sa",
"label": "Sentiment Analysis",
"relationship": "Task",
"subnodes": [
{"id": "tb", "label": "Transformer-Based", "relationship": "Approach"}
]
}
]
}
]
}
"""
demo = gr.Interface(
fn=generate_concept_map,
inputs=gr.Textbox(
value=sample_json,
placeholder="Paste JSON following the documented format",
label="Structured JSON Input",
lines=25
),
outputs=gr.Image(
label="Generated Concept Map",
type="filepath",
show_download_button=True
),
title="Advanced Concept Map Generator",
description="Create multi-level concept maps from properly formatted JSON"
)
demo.launch(
mcp_server=True,
share=False,
server_port=7860,
server_name="0.0.0.0"
)