AI-powered tool that generates publication-quality SVG charts matching PIMCO's InDesign style. Upload Excel/CSV data, write a plain-English brief, then iterate with natural language edits until the chart is exactly right. - Claude Opus 4.6 interprets briefs into structured ChartSpec JSON - Deterministic SVG renderer via drawsvg (no visual hallucinations) - Roboto/Roboto Condensed fonts base64-embedded in SVG - FastAPI + HTMX web frontend with live preview - Conversational refinement: "make lines thicker", "change title", etc. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
"""Pydantic models for the chart specification - the contract between AI and renderer."""
|
|
|
|
from __future__ import annotations
|
|
from typing import Literal
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class AxisSpec(BaseModel):
|
|
label: str | None = None
|
|
suffix: str | None = None
|
|
date_format: str | None = None
|
|
min_val: float | None = None
|
|
max_val: float | None = None
|
|
tick_interval: float | None = None
|
|
|
|
|
|
class ShadedFillSpec(BaseModel):
|
|
reference_series: str = Field(description="Label of the reference series to shade against")
|
|
above_color: Literal["blue", "pink"] = "blue"
|
|
below_color: Literal["blue", "pink"] = "pink"
|
|
|
|
|
|
class SeriesSpec(BaseModel):
|
|
label: str
|
|
data_column: str = Field(description="Column name from uploaded data")
|
|
chart_type: Literal["line", "bar", "stacked_bar", "area", "pie"] = "line"
|
|
color_index: int | None = None
|
|
line_style: Literal["solid", "dashed", "dotted"] = "solid"
|
|
line_weight: float | None = None
|
|
shaded_fill: ShadedFillSpec | None = None
|
|
|
|
|
|
class AnnotationSpec(BaseModel):
|
|
type: Literal["ellipse", "callout", "label"]
|
|
x_start: str | None = None
|
|
x_end: str | None = None
|
|
y_start: float | None = None
|
|
y_end: float | None = None
|
|
text: str | None = None
|
|
|
|
|
|
class PanelSpec(BaseModel):
|
|
title: str
|
|
subtitle: str | None = None
|
|
x_axis: AxisSpec
|
|
y_axis: AxisSpec
|
|
series: list[SeriesSpec]
|
|
annotations: list[AnnotationSpec] = Field(default_factory=list)
|
|
|
|
|
|
class ChartSpec(BaseModel):
|
|
layout: Literal["single", "dual_panel"] = "single"
|
|
panels: list[PanelSpec]
|