Skip to main content

vectrify

PyPI Python License

LLMs still struggle to generate perfect vector images from a reference raster in one shot. vectrify turns raster images into editable vector code by treating vectorization as a search problem: an LLM proposes candidate SVG/Graphviz/Typst code, a vision scorer ranks how close each candidate looks to the source, and an optimization loop iteratively refines the best candidates.

The output is human-readable code you can keep editing by hand.

Features

  • Output formats: SVG (default), Graphviz DOT, Typst. HTML and TikZ planned.
  • LLM providers: OpenAI, Anthropic, Google Gemini, auto-detected from env vars.
  • Search strategies: NSGA-II for diversity-preserving multi-objective optimization, or beam search for a cheaper single-best run.
  • Scoring: local vision-model embeddings (perceptual), with pixel-diff and LLM-as-judge as alternatives.
  • Resumable runs: pick up where you left off, or fork from the top-N nodes of a previous run.
  • Live dashboard: pool stats, scoring, and convergence criteria.

Install

pipx or uv tool keeps vectrify in its own environment and on your PATH:

pipx install vectrify                    # or: uv tool install vectrify
pipx install "vectrify[vision]"          # recommended for best quality
pipx install "vectrify[all]"             # everything

Plain pip install works too, into whatever environment is active; when using --user, check that ~/.local/bin is on your PATH.

The base install covers SVG output and the pixel-difference scorer. The extras add the rest:

Extra What it adds
vision torch + transformers for the perceptual (CLIP/SigLIP) scorer
graphviz the graphviz Python bindings (system Graphviz still required)
typst the typst Python compiler
all vision + graphviz + typst

Cairo is required for SVG output (apt install libcairo2 or brew install cairo), and the graphviz format additionally needs the Graphviz binaries (apt install graphviz or brew install graphviz). A GPU is optional; the vision scorer falls back to CPU or MPS.

Finally, set an API key for one provider:

export OPENAI_API_KEY=...
export ANTHROPIC_API_KEY=...
export GEMINI_API_KEY=...

The provider is auto-detected from whichever key is set; override it with --provider {openai,anthropic,gemini} if you have several keys.

Quickstart

vectrify input.png -o output.svg

The defaults run up to 4 NSGA-II epochs and stop early once the search stops finding improvements (see Convergence and cost). Worst case, it runs for an hour and gives up.

A few useful variations:

# Bigger budget, longer runs
vectrify photo.jpg -o sketch.svg --epoch-patience 60 --max-wall-seconds 1800

# Steer the search with a goal
vectrify logo.png --goal "Use thick strokes only and avoid gradients"

# Output Graphviz DOT instead of SVG
vectrify diagram.png -o out.dot --format graphviz

# Resume from a previous run, keeping only the 20 best nodes
vectrify input.png --resume --resume-top 20

Run vectrify --help for the full flag reference, organized into LLM provider, scoring, search strategy, epoch control, resume, output artifacts, and runtime sections.

How it works

vectrify runs an evolutionary loop over a pool of candidate vector representations. The pool is seeded with a few LLM-generated candidates. On each iteration a parent is sampled, and:

  • with probability 1 − llm-rate, mutated locally (color tweaks, path nudges, crossover);
  • otherwise, sent to the LLM for a refined edit.

The new candidate is scored against the source image (perceptual via vision-transformer embeddings, pixel-space, or LLM-as-judge), then either replaces a worse pool member or is dropped.

Search strategies

NSGA-II, the default, keeps a diverse Pareto front and does better when you can afford several epochs. Beam search converges faster on a single answer. NSGA-only flags are epoch-diversity, epoch-variance and epoch-seeds; beam-only flags are beams and cull-keep. The CLI rejects mixed usage.

NSGA-II objectives

The search minimizes three objectives at once:

Objective Measure
visual error scorer distance to the source image
visual complexity JPEG-compressed size of the render
structural complexity code size (whitespace-stripped source length)

Visual error is the primary objective; the complexity measures only break ties among the best-scoring candidates, biasing toward small, clean output once the image is already close. Raising tournament-size pushes harder toward visual quality at the cost of pool diversity.

Convergence and cost

Each epoch ends when one of these fires; the next re-seeds from the current Pareto front. The run stops at max-epochs, max-wall-seconds, or the max-llm-calls cap.

Flag Default Triggers when…
max-epochs 4 hard cap on epoch count
epoch-patience 20 this many LLM calls in a row produce no improvement
epoch-steps 50 this many LLM calls have run in the current epoch
epoch-variance 0 (NSGA-only) score std-dev in the pool drops below value
epoch-diversity 0 (NSGA-only) mean pairwise diversity drops below value
max-wall-seconds 3600 wall-clock budget; ends the run, not just the epoch
max-llm-calls 0 hard cap on total LLM calls; 0 disables

Patience and step counters only tick on LLM calls, not on the cheap local mutations that make up most tasks, and a new best resets patience. The two NSGA stop criteria are off by default; good thresholds depend on your scorer and image.

The defaults cap LLM calls near max_epochs × epoch_steps, so around 220, and most runs stop well before that. A full run costs on the order of a dollar on flagship models; set max-llm-calls for a hard ceiling.

Output layout

Given --output sketch.svg, vectrify writes:

sketch.svg                       # the best final candidate (written at the end)
sketch/
└── runs/
    └── 2026-04-26_14-30-21/     # one directory per run, timestamped
        ├── lineage.csv          # accepted node history (all three objectives, parent, ops)
        └── nodes/
            ├── 0.0421_0001.svg  # one file per accepted node, prefixed by score
            ├── 0.0421_0001.png  # rendered preview (--save-raster)
            └── ...

Disable artifacts you don't need with no-write-lineage or no-save-raster. Enable save-heatmap to also dump perceptual diff maps next to each node.

Download files

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

Source Distribution

vectrify-0.1.2.tar.gz (309.4 kB view details)

Uploaded Source

Built Distribution

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

vectrify-0.1.2-py3-none-any.whl (87.2 kB view details)

Uploaded Python 3

File details

Details for the file vectrify-0.1.2.tar.gz.

File metadata

  • Download URL: vectrify-0.1.2.tar.gz
  • Upload date:
  • Size: 309.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for vectrify-0.1.2.tar.gz
Algorithm Hash digest
SHA256 49bf6b4a812d8822d48ca5786402b70370d40f725643b8d690d036d97a799d16
MD5 552f0c55dde7bc2aebe667476fac7b6a
BLAKE2b-256 3c4c7e51911f0692b48c9e69c4907074ca2a37b90279cd28c9c49fddf930372a

See more details on using hashes here.

File details

Details for the file vectrify-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: vectrify-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 87.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for vectrify-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4a55a860b9c8f3e6f6be844750d1a3d4a6466bd77a11e2ac6e834a12f9c3265e
MD5 362f69ca5b4baad3875e6eab4aa2e28d
BLAKE2b-256 5d33ce0120cc8ebe32c9ddd73c08391ac0907599b46d5179f332b42dc95e9152

See more details on using hashes here.

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