|
import graphviz |
|
import json |
|
from tempfile import NamedTemporaryFile |
|
import os |
|
from graph_generator_utils import add_nodes_and_edges |
|
|
|
def generate_radial_diagram(json_input: str, output_format: str) -> str: |
|
""" |
|
Generates a radial (center-expanded) diagram from JSON input. |
|
|
|
Args: |
|
json_input (str): A JSON string describing the radial diagram structure. |
|
It must follow the Expected JSON Format Example below. |
|
|
|
Expected JSON Format Example: |
|
{ |
|
"central_node": "AI Core Concepts & Domains", |
|
"nodes": [ |
|
{ |
|
"id": "foundational_ml", |
|
"label": "Foundational ML", |
|
"relationship": "builds on", |
|
"subnodes": [ |
|
{"id": "supervised_l", "label": "Supervised Learning", "relationship": "e.g."}, |
|
{"id": "unsupervised_l", "label": "Unsupervised Learning", "relationship": "e.g."} |
|
] |
|
}, |
|
{ |
|
"id": "dl_architectures", |
|
"label": "Deep Learning Arch.", |
|
"relationship": "evolved from", |
|
"subnodes": [ |
|
{"id": "cnns_rad", "label": "CNNs", "relationship": "e.g."}, |
|
{"id": "rnns_rad", "label": "RNNs", "relationship": "e.g."} |
|
] |
|
}, |
|
{ |
|
"id": "major_applications", |
|
"label": "Major AI Applications", |
|
"relationship": "applied in", |
|
"subnodes": [ |
|
{"id": "nlp_rad", "label": "Natural Language Processing", "relationship": "e.g."}, |
|
{"id": "cv_rad", "label": "Computer Vision", "relationship": "e.g."} |
|
] |
|
}, |
|
{ |
|
"id": "ethical_concerns", |
|
"label": "Ethical AI Concerns", |
|
"relationship": "addresses", |
|
"subnodes": [ |
|
{"id": "fairness_rad", "label": "Fairness & Bias", "relationship": "e.g."}, |
|
{"id": "explainability", "label": "Explainability (XAI)", "relationship": "e.g."} |
|
] |
|
}, |
|
{ |
|
"id": "future_trends", |
|
"label": "Future AI Trends", |
|
"relationship": "looking at", |
|
"subnodes": [ |
|
{"id": "agi_future", "label": "AGI Development", "relationship": "e.g."}, |
|
{"id": "quantum_ai", "label": "Quantum AI", "relationship": "e.g."} |
|
] |
|
} |
|
] |
|
} |
|
|
|
Returns: |
|
str: The filepath to the 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") |
|
|
|
|
|
|
|
korean_font = 'NanumGothic-Regular' |
|
|
|
dot = graphviz.Digraph( |
|
name='RadialDiagram', |
|
format='png', |
|
engine='neato', |
|
graph_attr={ |
|
'overlap': 'false', |
|
'splines': 'true', |
|
'bgcolor': 'white', |
|
'pad': '0.5', |
|
'layout': 'neato', |
|
'fontname': korean_font, |
|
'charset': 'UTF-8' |
|
}, |
|
node_attr={ |
|
'fixedsize': 'false', |
|
'fontname': korean_font |
|
}, |
|
edge_attr={ |
|
'fontname': korean_font |
|
} |
|
) |
|
|
|
base_color = '#19191a' |
|
|
|
dot.node( |
|
'central', |
|
data['central_node'], |
|
shape='box', |
|
style='filled,rounded', |
|
fillcolor=base_color, |
|
fontcolor='white', |
|
fontsize='16', |
|
fontname=korean_font |
|
) |
|
|
|
add_nodes_and_edges(dot, 'central', data.get('nodes', []), current_depth=1, base_color=base_color) |
|
|
|
with NamedTemporaryFile(delete=False, suffix=f'.{output_format}') as tmp: |
|
dot.render(tmp.name, format=output_format, cleanup=True) |
|
return f"{tmp.name}.{output_format}" |
|
|
|
except json.JSONDecodeError: |
|
return "Error: Invalid JSON format" |
|
except Exception as e: |
|
return f"Error: {str(e)}" |