Small HTTP server that converts a hand-drawn diagram image into standalone LaTeX/TikZ using an LLM, then compiles it with pdflatex and renders a PNG preview via ImageMagick.
  • Python 57.1%
  • HTML 24.2%
  • CSS 16.5%
  • Dockerfile 2.2%
Find a file
2025-12-27 02:17:07 +01:00
examples initial prototype 2025-12-25 11:52:09 +01:00
public feat: enhance security features and improve user interface in LaTeX diagram tool 2025-12-26 22:07:58 +01:00
templates feat: add fork functionality to create a copy of a run 2025-12-27 02:17:07 +01:00
.gitignore initial prototype 2025-12-25 11:52:09 +01:00
.python-version initial prototype 2025-12-25 11:52:09 +01:00
docker-compose.yaml feat: enhance security features and improve user interface in LaTeX diagram tool 2025-12-26 22:07:58 +01:00
Dockerfile feat: enhance security features and improve user interface in LaTeX diagram tool 2025-12-26 22:07:58 +01:00
main.py feat: add fork functionality to create a copy of a run 2025-12-27 02:17:07 +01:00
pyproject.toml refactor: rename project from latex-diagram-to-tikz to diagram-to-tikz 2025-12-26 22:10:02 +01:00
README.md fix: update image references from 'preview.png' to 'diagram.png' in README and HTML template 2025-12-26 23:50:48 +01:00
uv.lock refactor: rename project from latex-diagram-to-tikz to diagram-to-tikz 2025-12-26 22:10:02 +01:00

diagram-to-tikz

Small HTTP server that converts a hand-drawn diagram image into standalone LaTeX/TikZ using an LLM, then compiles it with pdflatex and renders a PNG preview via ImageMagick (magick).

Prerequisites

  • System tools:

    • pdflatex (TeX Live)

    • magick (ImageMagick)

    • pdf2svg

Install (uv)

From this folder:

uv sync

Configure LLM

This project uses LiteLLM with Google Gemini models.

Set credentials (common case):

export GOOGLE_API_KEY="..."

Defaults (comma-separated fallback order):

  • LLM_MODELS=gemini/gemini-3-pro-preview,gemini/gemini-3-flash-preview,gemini/gemini-flash-latest
  • EDIT_MODELS=gemini/gemini-3-flash-preview,gemini/gemini-flash-latest

Override if you want:

export LLM_MODELS="gemini/gemini-3-flash-preview"
export EDIT_MODELS="gemini/gemini-3-flash-preview"

Run

Option A: run via Python entrypoint

uv run python main.py
uv run uvicorn main:app --reload

Open:

Docker

Single-stage python:3.12-slim + uv with cached dependency layer. BuildKit is required for cache mounts.

Build locally:

docker build -t diagram-to-tikz .

Run with Docker

docker run -it --rm -p 8000:8000 \
    -e GOOGLE_API_KEY="your-google-api-key" \
    -e LLM_MODELS="gemini/gemini-3-pro-preview,gemini/gemini-3-flash-preview,gemini/gemini-flash-latest" \
    -e EDIT_MODELS="gemini/gemini-3-flash-preview,gemini/gemini-flash-latest" \
    -e BASE_PATH="/" \
    -v $(pwd)/runs:/app/runs \
    diagram-to-tikz \
    uv run uvicorn main:app --host 0.0.0.0 --port 8000

Run with Docker Compose

Run with Compose (persists runs/ to the host):

services:
    app:
        build: .
        ports:
            - "8000:8000"
        environment:
            GOOGLE_API_KEY: "your-google-api-key"
            LLM_MODELS: "gemini/gemini-3-pro-preview,gemini/gemini-3-flash-preview,gemini/gemini-flash-latest"
            EDIT_MODELS: "gemini/gemini-3-flash-preview,gemini/gemini-flash-latest"
            BASE_PATH: "/"
            LOG_LEVEL: "INFO"
            CONVERT_DAILY_LIMIT: "5"
            EDIT_DAILY_LIMIT: "10"
            PDFLATEX_TIMEOUT_SECONDS: "10"
            HOST: "0.0.0.0"
            PORT: "8000"
            RELOAD: "0"
        volumes:
            - ./runs:/app/runs
        command: uv run uvicorn main:app --host 0.0.0.0 --port 8000

Then start it:

docker compose up --build

Outputs

Each request creates a folder under runs/<run_id>/ containing:

  • original.* (your upload)
  • diagram.tex
  • diagram.pdf (if LaTeX compilation succeeded)
  • diagram.png (if ImageMagick rendering succeeded)
  • run.log.txt (all logs: LLM + pdflatex + magick)