Skip to content

Local text→plot generation: anyplot.plot() with a pluggable, local-first LLM backend #8123

@MarkusNeusinger

Description

@MarkusNeusinger

Idea

After cloning the repo, let a user generate a finished plot from plain text — without the
GitHub Actions pipeline. The package is already named anyplot, so the call reads naturally:

import anyplot
anyplot.plot("monthly revenue 2024 as a bar chart, highlight December")
anyplot.plot("scatter of these points", data=df, library="plotly")

The only real work is exposing a top-level plot() from anyplot/__init__.py; the alias is the
caller's choice:

import anyplot as ap;  ap.plot("…")    # numpy-style, safe
import anyplot as any; any.plot("…")   # the literal "any.plot()" reading — valid & runs…

The any alias works (any is not a keyword, just a builtin name that can be shadowed at
module scope), but it shadows the builtin any() in that scope, so it's a mild footgun (some
linters flag it via flake8-builtins; this repo's ruff config — E,F,W,I,C,B — would not). We ship
plot() and let users pick.

It would reuse the same rules and review loop the CI pipeline already uses, just run locally.

Rough flow

  1. Take the text (the only required argument).
  2. Parse it into a spec-like requirement (plot type, data hints, features) — like a lightweight,
    on-the-fly spec.
  3. Either reuse an existing plots/{spec-id} implementation as a base when something close
    exists, or generate fresh when it doesn't.
  4. Optional inputs: data= (a DataFrame / CSV / inline values) and library= (one of the
    supported libs; default could auto-pick).
  5. Render both themes and run the local quality/review check (same criteria as the pipeline),
    repairing if needed.
  6. Return the implementation code + the rendered image(s).

Local-first / pluggable LLM backend

The headline requirement: a fresh clone should work with zero API keys. Default to a local
model via Ollama
; cloud providers (Claude, etc.) optional and selectable. This needs a small
provider abstraction the generation code routes through — today the LLM is effectively Claude-only
(see below), so this is the main new piece.

Possible surfaces (to be decided)

  • Python callable: anyplot.plot("…", data=…, library=…) — closest to the original idea
  • CLI: anyplot generate "…" --library matplotlib --data data.csv
  • MCP tool: a generate_plot tool on the existing MCP server
  • HTTP endpoint: POST /generate on the FastAPI backend

Existing pieces to build on

The generation logic is already prompt-driven and platform-agnostic — the pipeline is mostly
automation around these:

  • Rules/prompts: prompts/plot-generator.md, prompts/default-style-guide.md,
    prompts/library/{library}.md, prompts/quality-criteria.md,
    prompts/workflow-prompts/{impl-generate-claude,ai-quality-review}.md
  • Local-friendly tooling: agentic/commands/regen.md + agentic/workflows/modules/regen/
    (picker / render / metadata) — already runs generation locally, but only against existing
    specs, not free text
  • LLM/CLI abstraction seam: agentic/workflows/modules/agent.py (already supports
    claude/copilot/gemini CLIs via env vars) and core/config.py:resolve_model(cli, tier)
    no Ollama backend and no provider interface yet
  • On-disk layout to mirror: plots/{spec-id}/implementations/{language}/{library}.{ext} +
    metadata/{language}/{library}.yaml

Open questions

  • How to parse free text into a spec-like requirement (and reuse spec tagging like
    prompts/spec-tags-generator.md)?
  • How to decide "reuse an existing impl as a base" vs "generate fresh" (similarity search over the
    catalog vs always-fresh)?
  • Output shape: write a temp plots/-style dir, or return code + image in memory?
  • Which library to pick by default when the user doesn't specify one?
  • Add ollama / litellm as an optional dependency; define the provider interface
    (BaseLLMClientOllamaClient, AnthropicClient, …).

Captured as an idea for later — not yet scoped for implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestinfrastructureWorkflow, backend, or frontend issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions