Download aide/utils/tree_export.py from dexhunter/aideml: direct link, hf CLI and curl.
- Browser
- Download file 2.84 kB
-
https://huggingface.co/spaces/dexhunter/aideml/resolve/main/aide/utils/tree_export.py
- Command line
-
hf download hf://spaces/dexhunter/aideml/aide/utils/tree_export.py
-
curl -L -o tree_export.py https://huggingface.co/spaces/dexhunter/aideml/resolve/main/aide/utils/tree_export.py
2.84 kB
| """Export journal to HTML visualization of tree + code.""" | |
| import json | |
| import textwrap | |
| from pathlib import Path | |
| import numpy as np | |
| from igraph import Graph | |
| from ..journal import Journal | |
| def get_edges(journal: Journal): | |
| for node in journal: | |
| for c in node.children: | |
| yield (node.step, c.step) | |
| def generate_layout(n_nodes, edges, layout_type="rt"): | |
| """Generate visual layout of graph""" | |
| layout = Graph( | |
| n_nodes, | |
| edges=edges, | |
| directed=True, | |
| ).layout(layout_type) | |
| y_max = max(layout[k][1] for k in range(n_nodes)) | |
| layout_coords = [] | |
| for n in range(n_nodes): | |
| layout_coords.append((layout[n][0], 2 * y_max - layout[n][1])) | |
| return np.array(layout_coords) | |
| def normalize_layout(layout: np.ndarray): | |
| """Normalize layout to [0, 1]""" | |
| layout = (layout - layout.min(axis=0)) / (layout.max(axis=0) - layout.min(axis=0)) | |
| layout[:, 1] = 1 - layout[:, 1] | |
| layout[:, 1] = np.nan_to_num(layout[:, 1], nan=0) | |
| layout[:, 0] = np.nan_to_num(layout[:, 0], nan=0.5) | |
| return layout | |
| def strip_code_markers(code: str) -> str: | |
| """Remove markdown code block markers if present.""" | |
| code = code.strip() | |
| if code.startswith("```"): | |
| # Remove opening backticks and optional language identifier | |
| first_newline = code.find("\n") | |
| if first_newline != -1: | |
| code = code[first_newline:].strip() | |
| if code.endswith("```"): | |
| code = code[:-3].strip() | |
| return code | |
| def cfg_to_tree_struct(cfg, jou: Journal): | |
| edges = list(get_edges(jou)) | |
| layout = normalize_layout(generate_layout(len(jou), edges)) | |
| # metrics = np.array([n.metric.value_npsafe for n in jou]) | |
| # metrics = (metrics - np.nanmin(metrics)) / (np.nanmax(metrics) - np.nanmin(metrics)) | |
| # metrics = np.nan_to_num(metrics, nan=1) | |
| # metrics[:] = 0 | |
| metrics = np.array([0 for n in jou]) | |
| return dict( | |
| edges=edges, | |
| layout=layout.tolist(), | |
| plan=[textwrap.fill(n.plan, width=80) for n in jou.nodes], | |
| code=[strip_code_markers(n.code) for n in jou], | |
| term_out=[n.term_out for n in jou], | |
| analysis=[n.analysis for n in jou], | |
| exp_name=cfg.exp_name, | |
| metrics=metrics.tolist(), | |
| ) | |
| def generate_html(tree_graph_str: str): | |
| template_dir = Path(__file__).parent / "viz_templates" | |
| with open(template_dir / "template.js") as f: | |
| js = f.read() | |
| js = js.replace("<placeholder>", tree_graph_str) | |
| with open(template_dir / "template.html") as f: | |
| html = f.read() | |
| html = html.replace("<!-- placeholder -->", js) | |
| return html | |
| def generate(cfg, jou: Journal, out_path: Path): | |
| tree_graph_str = json.dumps(cfg_to_tree_struct(cfg, jou)) | |
| html = generate_html(tree_graph_str) | |
| with open(out_path, "w") as f: | |
| f.write(html) | |