Skip to content

ADW-19/llmpic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

13 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

License GitHub Python Version PyPI

llmpic logo

LLMPIC

Natural Language โ†’ Production Charts. One line.

ไธญๆ–‡ ย |ย  API Reference ย |ย  User Guide


from llmpic import llmPIC

lp = llmPIC(api_key="sk-...", base_url="https://api.openai.com/v1")

lp.plot("Monthly sales trend, 12 months").show()   # Jupyter inline
lp.plot("CPU usage over 30 days").save()            # โ†’ ~/llmpic_charts/
lp.bar("Sales by region").data(df).style({"color_scheme":"warm"}).save("bar.png")

Table of Contents


๐Ÿ’ก Why llmpic?

Traditional Python charting means wrestling with matplotlib's verbose API โ€” plt.subplots(), ax.set_xticklabels(), fig.tight_layout(), hundreds of functions to memorize, 15โ€“40 lines for a single chart. Data scientists spend more time googling matplotlib syntax than analyzing data.

llmpic brings Python visualization into the LLM era. Describe what you want in plain English, Chinese, Japanese, or Korean โ€” get a production-quality matplotlib chart instantly.

Traditional matplotlib llmpic
Lines of code 15โ€“40 lines 1โ€“3 lines
API knowledge 100+ functions 0 (natural language)
Chart types Manual selection 11 types + auto-detect
Iteration Rewrite entire block result.edit("make bars red")
Jupyter plt.show() only result.show() inline
Multi-format Separate savefig calls Single save() โ€” PNG/SVG/PDF
Error recovery Manual debugging Auto-fix with LLM (up to 2 rounds)
Concurrency Manual threading AsyncllmPIC.batch() parallel generation
Security None Dual-layer: 32 regex + optional LLM review

๐Ÿ‘€ See the difference for yourself

Task: A grouped bar chart comparing 4 regions ร— 4 quarters, with value labels, custom colors, dashed grid, title, axis labels, and a legend.

Traditional matplotlib โ€” 30+ lines, 100+ API calls to memorize llmpic โ€” 1 line, plain English
import matplotlib.pyplot as plt
import numpy as np

regions  = ["North", "South", "East", "West"]
quarters = ["Q1", "Q2", "Q3", "Q4"]
data = np.array([
    [120, 145, 160, 180],
    [ 95, 110, 130, 155],
    [140, 165, 180, 200],
    [ 80,  95, 110, 125],
])

x = np.arange(len(regions))
w = 0.2
colors = ["#4C72B0", "#55A868",
          "#C44E52", "#8172B2"]

fig, ax = plt.subplots(figsize=(10, 6), dpi=150)
for i, q in enumerate(quarters):
    bars = ax.bar(x + i * w, data[:, i], w,
                  label=q, color=colors[i])
    for bar in bars:
        h = bar.get_height()
        ax.text(bar.get_x() + bar.get_width() / 2,
                h + 1, f"{h:.0f}",
                ha="center", va="bottom", fontsize=9)

ax.set_title("Quarterly Sales by Region (2025)",
             fontsize=14, pad=12)
ax.set_xlabel("Region")
ax.set_ylabel("Sales (K USD)")
ax.set_xticks(x + w * 1.5)
ax.set_xticklabels(regions)
ax.legend(title="Quarter", loc="upper left")
ax.grid(axis="y", linestyle="--", alpha=0.4)
fig.tight_layout()
plt.savefig("sales.png", dpi=150)
plt.close()
from llmpic import llmPIC

lp = llmPIC(api_key="sk-...",
            base_url="https://api.openai.com/v1")

# Step 1: render โ€” LLM writes matplotlib code,
# safety check + sandbox execute it for you.
result = lp.bar(
    "Quarterly sales by region 2025: "
    "North=[120,145,160,180], "
    "South=[95,110,130,155], "
    "East=[140,165,180,200], "
    "West=[80,95,110,125]. "
    "Add value labels, dashed grid, legend."
).render()

result.save("sales.png")

# Want to tweak it later? Use natural language:
v2 = result.edit("make Q4 bars red, "
                 "title 'Annual Report'")
v2.save("sales_v2.png")

# Need the underlying matplotlib code? It's right there:
print(result.code)

That's it. A chart that conveys the same insight โ€” generated, not hand-coded.

No set_xticklabels. No bar.get_x() + bar.get_width()/2. No Stack Overflow tabs open.

๐Ÿ’ฅ 30+ lines of API drudgery โ†’ a few lines of plain English. llmpic still hands you the generated matplotlib code via result.code if you want to fine-tune it manually. The exact rendered output depends on the LLM's code generation โ€” if you need pixel-perfect control, result.edit("...") lets you iterate without rewriting from scratch.


โœจ Features

  • ๐Ÿ—ฃ๏ธ Natural Language Input โ€” English, Chinese, Japanese, Korean
  • ๐Ÿ“Š 11 Chart Types โ€” Line, Scatter, Bar, Pie, Histogram, Heatmap, Boxplot, Area, Radar, Subplots, Auto-detect
  • ๐Ÿ”— Fluent Builder API โ€” chain .data() โ†’ .style() โ†’ .format() โ†’ .save() / .render()
  • ๐Ÿ““ Jupyter Inline โ€” result.show() renders directly below notebook cells
  • โšก Async Batch โ€” AsyncllmPIC.batch() generates multiple charts concurrently (total time โ‰ˆ slowest one)
  • ๐Ÿ”ง Auto-Fix โ€” Failed code executions are auto-corrected by the LLM (up to 2 rounds)
  • โœ๏ธ Iterative Editing โ€” result.edit("make bars red, increase title size") refines charts with natural language
  • ๐Ÿ“ฆ Multi-Format โ€” PNG (raster), SVG (vector), PDF (print) from a single save()
  • ๐ŸŒ Multi-Language Labels โ€” Auto-detects query language and matches chart titles/labels
  • ๐Ÿ›ก๏ธ Dual Safety โ€” 32 precompiled regex patterns (~0ms) + optional LLM semantic review
  • ๐Ÿ’ป Cross-Platform โ€” Windows / Linux / macOS, automatic CJK font configuration
  • ๐Ÿ”„ Exponential Retry โ€” LLM calls retry with backoff (1s, 2s, 4s) on transient failures
  • ๐Ÿ“Š Structured Output โ€” Uses JSON mode for reliable code extraction from LLM responses

๐Ÿ“ฆ Installation

pip install llmpic          # All-in-one: matplotlib, numpy, openai, pandas, seaborn, scikit-learn, scipy

Requirements:

  • Python โ‰ฅ 3.10
  • An OpenAI-compatible API endpoint (OpenAI, Azure, DeepSeek, GLM, Ollama, vLLM, etc.)
  • For CJK charts: appropriate fonts (auto-detected on first run)

Verify Installation

from llmpic import llmPIC, AsyncllmPIC, ChartResult, PlotBuilder, AsyncPlotBuilder
import llmpic
print(llmpic.__version__)  # โ†’ "0.2.0"

๐Ÿš€ Quick Start

1. Initialize the SDK

from llmpic import llmPIC

# OpenAI
lp = llmPIC(
    api_key="sk-your-openai-key",
    base_url="https://api.openai.com/v1",
    model="gpt-4o",
)

# DeepSeek
lp = llmPIC(
    api_key="sk-your-deepseek-key",
    base_url="https://api.deepseek.com/v1",
    model="deepseek-chat",
)

# Any OpenAI-compatible endpoint (Azure, GLM, Ollama, vLLM, etc.)
lp = llmPIC(
    api_key="your-key",
    base_url="https://your-endpoint/v1",
    model="your-model",
)

2. Your First Chart

# Basic โ€” describe it, get a chart
lp.plot("12-month sales trend").save("sales.png")

# Jupyter inline display
lp.plot("CPU usage over 30 days").render().show()

# Default save path (falls through to home directory)
lp.plot("Temperature trend").save()  # โ†’ ~/llmpic_charts/chart_20250101_120000.png

3. With Real Data

import pandas as pd

df = pd.read_csv("sales.csv")
lp.bar("Sales by region").data(df).style({
    "color_scheme": "warm",
    "figsize": [12, 7],
    "title_fontsize": 16,
}).save("regional_sales.png")

4. Common Patterns (30-second cookbook)

# Line chart with SVG output
lp.plot("CPU trend").format('svg').save("cpu.svg")

# Scatter with DataFrame
lp.scatter("Age vs income correlation").data(df).save("scatter.png")

# Pie with inline data
lp.pie("Market share: A=40%, B=25%, C=20%, D=15%").save("pie.png")

# Heatmap correlation matrix
lp.heatmap("Feature correlation").data(corr_df).save("heatmap.png")

# Multi-chart dashboard
lp.subplots("2x2: trend line, region bar, customer scatter, growth histogram").save("dash.png")

# Let the LLM pick the best chart type
lp.custom("Analyze user retention trends").data(df).save("auto.png")

# Access generated code
result = lp.plot("Test").render()
print(result.code)           # The matplotlib code the LLM wrote
print(result.token_usage)    # {'input': 320, 'output': 180}

# Edit an existing chart
result = lp.plot("Sales: Jan=100, Feb=120").render()
result.edit("Change to bar chart, use red color").edit(
    "Title 'Q1 Revenue', add grid").save("final.png")

๐Ÿ“Š Chart Types

Method Chart Type Best For LLM Hint
.plot() Line Trends, time series, continuous data ax.plot()
.scatter() Scatter Correlation, cluster visualization ax.scatter()
.bar() Bar / Barh Categorical comparison, rankings ax.bar() / ax.barh()
.pie() Pie Proportions, market share ax.pie(autopct='%1.1f%%')
.hist() Histogram Distributions, frequency analysis ax.hist()
.heatmap() Heatmap Correlation matrices, 2D density ax.imshow() / sns.heatmap()
.boxplot() Boxplot Statistical distribution comparison ax.boxplot() / sns.boxplot()
.area() Area Stacked trends, composition over time ax.fill_between() / ax.stackplot()
.radar() Radar Multi-dim comparison, capability assessment Polar axes
.subplots() Dashboard Multi-chart composite views plt.subplots(nrows, ncols)
.custom() Auto LLM picks the best type automatically Context-aware selection

๐Ÿ”— Core Workflow

  sdk.plot("query")            โ† describe the chart in natural language
    โ†’ PlotBuilder
      .data(df)                โ† attach real data (optional)
      .style({...})            โ† customize appearance (optional)
      .format('png')           โ† choose output format (optional)
      .render()                โ† trigger: LLM โ†’ safety โ†’ sandbox โ†’ ChartResult
      .save("path.png")        โ† trigger + save to file

The Builder Pattern

# All chart methods return a PlotBuilder. Builders are lazy โ€” nothing runs
# until .render(), .save(), or accessing .image_bytes / .code.

builder = lp.plot("Monthly sales")  # Returns PlotBuilder โ€” NOTHING generated yet
builder = builder.data(df)           # Attach data
builder = builder.style({"figsize": [12, 6]})  # Set style
builder = builder.format('svg')      # Set format

result = builder.render()  # โ† NOW everything runs: LLM โ†’ safety โ†’ sandbox
result.save("chart.svg")

ChartResult โ€” Your Swiss Army Knife

result = lp.plot("CPU trend").render()

# Basic info
result.success           # bool
result.code              # The matplotlib code (str)
result.token_usage       # {'input': 320, 'output': 180}
result.size_kb           # 45.2

# Save to file
result.save()            # โ†’ ~/llmpic_charts/chart_{timestamp}.png
result.save("out.png")   # PNG
result.save("out.svg")   # SVG
result.save("out.pdf")   # PDF

# Display in Jupyter
result.show()

# Base64 for web embedding
result.base64()          # data:image/png;base64,...
result.base64_svg()      # data:image/svg+xml;base64,...

# Access alternative formats (lazy โ€” re-renders on first access)
result.svg_bytes         # SVG as bytes
result.pdf_bytes         # PDF as bytes
result.svg               # SVG as string

# Edit with natural language
v2 = result.edit("Change to bar chart, use warm colors")
v3 = v2.edit("Increase title size to 18")

โšก Async & Batch

Use AsyncllmPIC for concurrent chart generation โ€” total time โ‰ˆ slowest single chart.

from llmpic import AsyncllmPIC
import asyncio

async def main():
    lp = AsyncllmPIC(
        api_key="sk-...",
        base_url="https://api.openai.com/v1",
        model="gpt-4o",
    )

    # Batch: 5 charts generated concurrently
    results = await lp.batch([
        ("plot",     "12-month sales trend"),
        ("bar",      "Regional sales comparison"),
        ("pie",      "Market share distribution"),
        ("scatter",  "Customer age vs spend"),
        ("heatmap",  "Feature correlation matrix"),
    ])

    for i, r in enumerate(results):
        if r.success:
            r.save(f"batch_{i}.png")
            print(f"[{i}] OK โ€” {r.size_kb:.1f}KB, "
                  f"tokens: in={r.token_usage['input']} out={r.token_usage['output']}")
        else:
            print(f"[{i}] FAIL: {r.error_message}")

asyncio.run(main())

Manual Concurrent Rendering

async def main():
    lp = AsyncllmPIC(...)

    # Fine-grained control with builders
    builders = [
        lp.plot("CPU trend").format('png'),
        lp.bar("Sales").data(df).style({"color_scheme": "warm"}).format('svg'),
        lp.pie("Market share").format('pdf'),
    ]
    results = await asyncio.gather(*[b.render() for b in builders])
    # All three run concurrently

asyncio.run(main())

โœ๏ธ Iterative Editing

Don't rewrite prompts for small tweaks โ€” use edit() to refine charts incrementally.

# Start
result = lp.plot("Monthly sales: Jan=100, Feb=120, Mar=90, Apr=150").render()

# Iterate โ€” each .edit() returns a NEW ChartResult (never mutates originals)
result = result.edit("Change to bar chart")
result = result.edit("Make bars red, use warm color scheme")
result = result.edit("Add grid lines, increase title font size to 18")
result = result.edit("Title 'Q1 2025 Sales Report', add y-axis label 'Revenue (K USD)'")

result.save("final.png")
result.show()

How it works: Each edit() sends the current code + your edit request to the LLM, which returns modified code. The new code passes through the same safety check โ†’ sandbox execution pipeline. Original ChartResult is never mutated.


๐Ÿ“ฆ Output Formats

Format Extension Type Best For
PNG .png Raster General use, embedding, quick preview
SVG .svg Vector Web embedding, printing, scaling
PDF .pdf Vector/Print Reports, publications, sharing
# Method 1: Chain .format() before render
lp.plot("Trend").format('svg').save("chart.svg")
lp.plot("Trend").format('pdf').save("chart.pdf")

# Method 2: Extension auto-detection on save
result = lp.plot("Trend").render()     # Default: PNG
result.save("output.svg")              # โ†’ SVG (detected from extension)
result.save("output.pdf")              # โ†’ PDF

# Method 3: Access alternative format properties (lazy re-render)
result = lp.plot("Trend").render()     # PNG in image_bytes
svg_data = result.svg_bytes             # Re-renders as SVG (lazy, cached)
pdf_data = result.pdf_bytes             # Re-renders as PDF (lazy, cached)

๐ŸŽจ Style Customization

Preset Color Schemes (6 built-in)

lp.plot("Trend").style({"color_scheme": "blues"}).save("b.png")
lp.plot("Trend").style({"color_scheme": "warm"}).save("w.png")
lp.plot("Trend").style({"color_scheme": "cool"}).save("c.png")
lp.plot("Trend").style({"color_scheme": "pastel"}).save("p.png")
lp.plot("Trend").style({"color_scheme": "dark"}).save("d.png")
lp.plot("Trend").style({"color_scheme": "grayscale"}).save("g.png")

All Style Keys

Key Type Default Description
figsize [int, int] [10, 6] Figure size in inches (width, height)
dpi int 150 Output resolution (dots per inch)
color_scheme str "blues" One of: blues warm cool pastel dark grayscale
title_fontsize int 14 Chart title font size
label_fontsize int 12 Axis label font size
tick_fontsize int 10 Tick mark label font size
grid bool True Show background grid
grid_alpha float 0.3 Grid line transparency (0โ€“1)
tight_layout bool True Auto-adjust layout to avoid clipping
facecolor str "white" Figure background color (any CSS color)

Style Examples

# Journal-quality figure
lp.plot("Experiment results").style({
    "figsize": [8, 5],
    "dpi": 300,
    "color_scheme": "dark",
    "title_fontsize": 16,
    "label_fontsize": 14,
}).save("journal.png")

# Presentation-ready
lp.bar("Q4 revenue").data(df).style({
    "figsize": [14, 8],
    "color_scheme": "warm",
    "title_fontsize": 22,
    "label_fontsize": 16,
    "tick_fontsize": 14,
    "grid": False,
    "facecolor": "#FAFAFA",
    "dpi": 200,
}).save("presentation.png")

# Style can also be passed as JSON string
lp.plot("Trend").style('{"color_scheme":"cool","figsize":[12,8]}').save("trend.png")

๐Ÿ›ก๏ธ Security

llmpic executes LLM-generated code in a sandboxed environment with dual-layer protection:

Layer 1: Regex Pattern Matching (~0ms overhead)

32 precompiled regex patterns block known dangerous patterns:

  • System commands: os.system(), os.popen(), subprocess
  • File I/O: open() (generated code shouldn't access files)
  • Dynamic execution: exec(), eval(), compile(), __import__()
  • Network access: socket, urllib, requests, httpx
  • Dangerous modules: shutil, ctypes, pickle
  • Reflection escapes: __subclasses__, __bases__, __mro__

Layer 2: Sandbox Execution

  • Restricted namespace: Only safe builtins + matplotlib, numpy, pandas, seaborn
  • Figure.savefig intercepted: Code cannot write files directly
  • plt.show() / plt.savefig() / plt.close() blocked: All intercepted as no-ops
  • Timeout fuse: ThreadPoolExecutor + timeout kills runaway code
  • Serialization lock: Module-level mutex prevents matplotlib state races

Safety Level Configuration

# Fast mode (recommended for production) โ€” regex only
lp = llmPIC(..., safety_level="fast")

# Full mode โ€” regex + LLM semantic review (adds ~1-2s per chart)
lp = llmPIC(..., safety_level="full")

Recommendation: The sandbox already blocks all real execution paths. fast mode is sufficient for production use.


๐ŸŒ Provider Compatibility

llmpic works with any OpenAI-compatible API endpoint that supports chat/completions with JSON structured output:

Provider base_url model (example)
OpenAI https://api.openai.com/v1 gpt-5.5, gpt-5.5-mini
DeepSeek https://api.deepseek.com/v1 deepseek-v4-pro
Azure OpenAI https://{resource}.openai.azure.com/openai/deployments/{deployment} Your deployment name
GLM (Zhipu) https://open.bigmodel.cn/api/paas/v5 glm-5
Ollama (local) http://localhost:11434/v1 llama3, qwen3.5
vLLM (local) http://localhost:8000/v1 Your served model
Groq https://api.groq.com/openai/v1 llama-3.3-70b

Note: For best chart quality, use a model with strong code generation capabilities (GPT-5.5, DeepSeek-V4, GLM-5, etc.). Local models may produce less reliable code โ€” consider increasing max_retries and max_fix_attempts.


๐Ÿ”ง Environment Variables

Store credentials in environment variables or .env files for cleaner code:

# .env file or shell
export LLMPIC_API_KEY="sk-your-key"
export LLMPIC_BASE_URL="https://api.openai.com/v1"
export LLMPIC_MODEL="gpt-4o"
import os
from llmpic import llmPIC

lp = llmPIC(
    api_key=os.getenv("LLMPIC_API_KEY"),
    base_url=os.getenv("LLMPIC_BASE_URL"),
    model=os.getenv("LLMPIC_MODEL", "gpt-4o"),
)

๐Ÿ— Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      llmPIC / AsyncllmPIC                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
โ”‚  โ”‚  .plot() โ”‚   โ”‚  .bar()  โ”‚   โ”‚  .pie()  โ”‚   โ”‚  .custom()โ”‚ โ”‚
โ”‚  โ”‚.scatter()โ”‚   โ”‚ .hist()  โ”‚   โ”‚.heatmap()โ”‚   โ”‚   ... 11  โ”‚ โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
โ”‚       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ”‚
โ”‚                          โ”‚                                   โ”‚
โ”‚                    PlotBuilder / AsyncPlotBuilder             โ”‚
โ”‚                    .data() .style() .format()                 โ”‚
โ”‚                          โ”‚                                   โ”‚
โ”‚                    .render() / .save()                        โ”‚
โ”‚                          โ”‚                                   โ”‚
โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”‚
โ”‚              โ”‚  1. LLM Code Gen      โ”‚  OpenAI API           โ”‚
โ”‚              โ”‚     (with retry ร—3)   โ”‚                      โ”‚
โ”‚              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ”‚
โ”‚                          โ”‚                                   โ”‚
โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”‚
โ”‚              โ”‚  2. Safety Check      โ”‚  CodeSafetyChecker    โ”‚
โ”‚              โ”‚     32 regex + LLM    โ”‚                      โ”‚
โ”‚              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ”‚
โ”‚                          โ”‚                                   โ”‚
โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”‚
โ”‚              โ”‚  3. Sandbox Execute   โ”‚  SandboxExecutor      โ”‚
โ”‚              โ”‚     (with auto-fix)   โ”‚  ThreadPool + timeout โ”‚
โ”‚              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ”‚
โ”‚                          โ”‚                                   โ”‚
โ”‚                    ChartResult                               โ”‚
โ”‚         .save() .show() .edit() .base64() .svg .pdf          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Pipeline per chart:

  1. LLM Code Generation โ€” Natural language โ†’ matplotlib Python code (JSON structured output, 3 retries with backoff)
  2. Safety Check โ€” 32 regex patterns + optional LLM semantic review
  3. Sandbox Execution โ€” ThreadPoolExecutor with timeout, Figure monkey-patching, restricted namespace
  4. Auto-Fix โ€” On execution failure, send code+error back to LLM for correction (up to 2 rounds)
  5. Result โ€” ChartResult with bytes, code, token usage, lazy format conversion

๐Ÿ“– Documentation

Document Language Description
API Reference EN Complete class, method, and parameter reference
API ๅ‚่€ƒ ไธญๆ–‡ ๆ‰€ๆœ‰็ฑปใ€ๆ–นๆณ•ใ€ๅ‚ๆ•ฐ็š„่ฏฆ็ป†่ฏดๆ˜Ž
User Guide EN Advanced usage, best practices, troubleshooting
ไฝฟ็”จๆŒ‡ๅ— ไธญๆ–‡ ่ฟ›้˜ถ็”จๆณ•ใ€ๆœ€ไฝณๅฎž่ทตใ€ๆ•…้šœๆŽ’ๆŸฅ
Jupyter Demos EN/ไธญๆ–‡ Ready-to-run demo notebooks
ไธญๆ–‡้ฆ–้กต ไธญๆ–‡ ๅฎŒๆ•ดไธญๆ–‡ README

๐Ÿ“ฎ Official Contact


๐Ÿ™ Acknowledgements

llmpic is built on the shoulders of these excellent open-source libraries:

  • SciPy โ€” scientific computing
  • scikit-learn โ€” machine learning utilities
  • pandas โ€” data analysis & DataFrame
  • NumPy โ€” numerical computing
  • Matplotlib โ€” chart rendering engine
  • seaborn โ€” statistical data visualization

Heartfelt thanks to all maintainers and contributors of these projects.


๐Ÿ“„ License

MIT ยฉ 2026 ADW-19

About

Natural Language Chart Generation Python SDK

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors