| 
							 | 
						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)}" |