#!/usr/bin/env python3 """ Generate SVG training history chart for the Gitea README. X-axis: Model version Y-axis: Training examples (bar) and inverse loss (line) """ import json from pathlib import Path OUTPUT = Path(__file__).resolve().parent.parent.parent / "branding" / "training_progress.svg" # Historical data from training runs VERSIONS = [ {"version": "0.1.0", "examples": 500, "loss": 2.10, "label": "seed only"}, {"version": "0.2.0", "examples": 1200, "loss": 1.45, "label": "+entities"}, {"version": "0.3.0", "examples": 2100, "loss": 0.82, "label": "+errors"}, {"version": "0.4.0", "examples": 3175, "loss": 0.35, "label": "+tools"}, {"version": "0.5.0", "examples": 4358, "loss": 0.16, "label": "+plugins"}, ] # Chart dimensions W = 700 H = 400 PAD_L = 70 PAD_R = 30 PAD_T = 40 PAD_B = 80 PLOT_W = W - PAD_L - PAD_R PLOT_H = H - PAD_T - PAD_B # Colors BG = "#111111" GRID = "#252525" TEXT = "#999999" BAR_COLOR = "#D35400" LINE_COLOR = "#4caf50" LABEL_COLOR = "#e0e0e0" def generate_svg(): max_examples = max(v["examples"] for v in VERSIONS) * 1.15 max_inv_loss = max(1.0 / v["loss"] for v in VERSIONS) * 1.15 n = len(VERSIONS) bar_w = PLOT_W / n * 0.6 gap = PLOT_W / n svg = f""" Mortdecai Training Progress """ # Y-axis grid (examples) for i in range(5): y = PAD_T + PLOT_H - (i / 4 * PLOT_H) val = int(max_examples * i / 4) svg += f'\n' svg += f'{val:,}\n' # Bars (training examples) for i, v in enumerate(VERSIONS): cx = PAD_L + gap * i + gap / 2 bh = (v["examples"] / max_examples) * PLOT_H by = PAD_T + PLOT_H - bh svg += f'\n' svg += f'{v["examples"]:,}\n' # X-axis label svg += f'{v["version"]}\n' svg += f'{v["label"]}\n' # Line (inverse loss = quality) points = [] for i, v in enumerate(VERSIONS): cx = PAD_L + gap * i + gap / 2 inv_loss = 1.0 / v["loss"] ly = PAD_T + PLOT_H - (inv_loss / max_inv_loss) * PLOT_H points.append(f"{cx},{ly}") polyline = " ".join(points) svg += f'\n' # Dots on line for i, v in enumerate(VERSIONS): cx = PAD_L + gap * i + gap / 2 inv_loss = 1.0 / v["loss"] ly = PAD_T + PLOT_H - (inv_loss / max_inv_loss) * PLOT_H svg += f'\n' svg += f'loss={v["loss"]}\n' # Y-axis labels svg += f'Training Examples\n' # Legend svg += f'\n' svg += f'Training Examples\n' svg += f'\n' svg += f'Model Quality (1/loss)\n' # X-axis label svg += f'Model Version\n' svg += "" return svg def main(): svg = generate_svg() OUTPUT.parent.mkdir(parents=True, exist_ok=True) with open(OUTPUT, "w") as f: f.write(svg) print(f"Chart saved to {OUTPUT}") print(f"Embed in README: ![Training Progress](branding/training_progress.svg)") if __name__ == "__main__": main()