Skip to main content

Schema-first visualization specifications for LLMs

Project description

Vizdantic

ChatGPT Image Jan 27, 2026, 05_16_35 PM

Python Status License

Stop LLMs from hallucinating plotting APIs. Let them describe what to visualize instead.

Vizdantic separates the data layer (what LLMs produce) from the view layer (what your code renders).


The Problem

You want an LLM to create charts from data. You have two bad options:

  1. Let the LLM write plotting code → It hallucinates APIs, mixes incompatible parameters, breaks on library updates
  2. Hardcode every chart type → Rigid, doesn't scale, defeats the purpose of using an LLM

The actual problem: LLMs are great at understanding intent but terrible at remembering exact function signatures.


The Solution

Vizdantic gives LLMs a stable contract: describe what to visualize, not how to plot it.

# LLM outputs this (validated against schema):
{
  "kind": "cartesian",
  "chart": "bar",
  "x": "month",
  "y": "revenue"
}

# Your code renders it however you want:
fig = render(spec, df)
fig = apply_company_theme(fig)
fig.show()

You get:

  • Validated LLM output (no hallucinated APIs)
  • Full control over rendering (swap Plotly for Matplotlib anytime)
  • Type-safe specs (a "flow" chart can't claim chart="bar")

Is This For You?

Yes, if you:

  • Build LLM apps that generate charts
  • Want LLMs to pick chart types, not write plotting code
  • Need to enforce brand guidelines on LLM-generated visualizations
  • Want a stable interface between LLM output and rendering logic

No, if you:

  • Just need a plotting library (use Plotly/Matplotlib directly)
  • Don't use LLMs for visualization
  • Want the LLM to control colors/fonts/styling

Quick Start

pip install vizdantic
from vizdantic import validate
from vizdantic.plugins.plotly import render
import pandas as pd

# 1. LLM produces this JSON
llm_output = {
    "kind": "cartesian",
    "chart": "bar",
    "x": "month",
    "y": "revenue"
}

# 2. Validate it
spec = validate(llm_output)  # Raises ValidationError if invalid

# 3. Render it
df = pd.DataFrame({"month": ["Jan", "Feb", "Mar"], "revenue": [100, 150, 120]})
fig = render(spec, df)
fig.show()

That's it. The LLM never touches plotting code.


Codex Skill (Optional)

This repo includes a Codex skill for running Vizdantic visualizations locally.

vizdantic install-codex-skill

Or with uv:

uv run vizdantic install-codex-skill

Restart Codex after installing. The skill will appear as vizdantic-runner.


What Charts Are Supported?

Vizdantic supports 14 chart type categories covering ~90% of common use cases:

Category Chart Types Example Use Case
Cartesian bar, line, area, scatter Time series, comparisons
Distribution histogram, box, violin, strip Statistical analysis
Parts pie Proportions, market share
Geo choropleth, scatter_geo, mapbox Geographic data
Hierarchy treemap, sunburst, icicle Organizational charts
Flow sankey Process flows, migrations
Polar scatter_polar, line_polar, bar_polar Directional data, wind roses
Ternary scatter_ternary, line_ternary 3-component compositions
3D scatter_3d, line_3d Spatial data
Financial funnel, funnel_area Sales funnels, conversions
Parallel parallel_coordinates, parallel_categories Multi-dimensional data
Timeline timeline Gantt charts, schedules
Matrix heatmap, imshow Correlation matrices
Points scatter Basic scatter plots

Each category has strongly-typed chart options. The LLM can't create invalid combinations.


How to Use With LLMs

Vizdantic works with any LLM. Two common patterns:

Option 1: Prompt-Based (Universal)

Embed the schema in your prompt:

from vizdantic import schema

prompt = f"""
You are a data visualization assistant.
Return JSON matching this schema:

{schema()}

User data columns: {df.columns.tolist()}
User request: "Show me revenue by month as a bar chart"
"""

The LLM returns JSON. You validate and render it.

Option 2: Tool/Function Calling (Structured)

For LLMs that support tools (OpenAI, Anthropic, etc.):

tool = {
    "name": "create_chart",
    "description": "Create a data visualization",
    "input_schema": schema()
}

The LLM is now constrained to valid output only.


Styling: You're In Control

Vizdantic doesn't touch colors, fonts, or themes. That's intentional.

def company_theme(fig):
    fig.update_layout(
        template="plotly_dark",
        colorway=["#ff0000", "#000000"],
        font=dict(family="Inter")
    )
    return fig

fig = render(spec, df)
fig = company_theme(fig)  # Apply your branding
fig.show()

The LLM picks the chart type. You control everything else.

This is why Vizdantic works in production: it never fights your design system.


Plugins

Currently supported:

  • Plotly (vizdantic.plugins.plotly)

Planned:

  • Matplotlib
  • Altair
  • Vega-Lite

Each plugin exposes one function: render(spec, data) → figure

Want a custom plugin? Implement that function. The spec is just a Pydantic model.


Status

  • Version: 0.2.2
  • Stability: Experimental (breaking changes possible until 1.0)
  • Python: 3.10+
  • License: MIT

Feedback welcome. This is a real project solving a real problem, not a demo.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vizdantic-0.2.2.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vizdantic-0.2.2-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file vizdantic-0.2.2.tar.gz.

File metadata

  • Download URL: vizdantic-0.2.2.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for vizdantic-0.2.2.tar.gz
Algorithm Hash digest
SHA256 9aa3078bcb31887812a37680f5d4340943b8746e13d412e84d2429ca31a34699
MD5 c0d66e808162c50b4adc2d0e87793e40
BLAKE2b-256 7cb992e2ddfa41ee1a83eeac01b3c0854aefb73e36b05c8acbac3c3e7ee35ea1

See more details on using hashes here.

Provenance

The following attestation bundles were made for vizdantic-0.2.2.tar.gz:

Publisher: release.yaml on ivogarais/vizdantic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vizdantic-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: vizdantic-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for vizdantic-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8b521e5795a8f35b0bfd9e53475d6f338934939a10398e8e330c28a5b461c178
MD5 c172c0d61ac742ea3a905b1158115d5c
BLAKE2b-256 fa4f5ede890af9a0011613123cf4bd38535d883ce9c7b399baf5e93ccc555d9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for vizdantic-0.2.2-py3-none-any.whl:

Publisher: release.yaml on ivogarais/vizdantic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page