Skip to content

Repository files navigation

Prompt Sigil + Latent Sigil

A new visual language for talking to LLMs — and for watching them think back.

This repo contains two complementary systems that share one premise: every mark on the figure must correspond to a real, measured property of the input. No randomness. No styling for effect. The magic-circle aesthetic emerges from honest projection.

Prompt Sigil (original + tensor scope + compression)

Markdown prompt → deterministic sigil. The gold trail shows where the AI is "drawing from" during generation. Open the tensor scope to peer inside the model itself.

Prompt Sigil web app

Latent Sigil (new — May 2026)

Text → Qwen2.5-0.5B layer-12 hidden state → magic circle. Draw a point on the circle → steered generation of "same nuance, varied text."

Latent Sigil ring view

Both systems run locally on CPU. No API keys, no telemetry, no GPU required.


Two demo paths

1. Prompt Sigil — magic-circle prompt composer + tensor scope

Renders a markdown prompt as a deterministic sigil. The webapp also runs a small LLM in-browser via transformers.js, projects its output back onto the figure as a thought trajectory, and exposes a tensor scope that visualises every layer's hidden state as a mandala.

Prompt Sigil rotating with all 35 sections of a complex system prompt

1. blank 2. place glyphs 3. bridge 4. conjure
empty canvas click ◉ △ ⊞ ▽ ✦ to place typed sections click two vertices to bridge scaffold + conjure → real sigil

Three modes of human ⇄ AI exchange:

  • Human → AI: place typed glyphs on a circle (persona, reasoning, tools, limits, …) instead of writing prose. The geometry encodes intent; the user types almost nothing.
  • AI → Human (output): as the model generates, its output is projected into the prompt's semantic space and drawn as a trail across the figure. You can see which parts of the prompt the model is drawing from at each moment.
  • AI → Human (interior): open the tensor scope to peer inside the model itself. The hidden state of every token at every layer becomes a petal of a layered mandala, and a logit-lens decoder shows what word the model "thinks" each token is at each depth.

A prompt can also be reduced to a minimal sigil-equivalent form: the compressor keeps the contract-bearing parts (headings, code, imperatives, URLs) verbatim and ranks remaining prose by importance, so two prompts that produce similar sigils now also produce similar markdown.

pip install -r requirements.txt
python webapp/server.py
# → open http://localhost:8765

# CLI (static SVG)
python -m prompt_sigil examples/complex.md
# → out/complex.svg

# CLI (compress; protected content survives any ratio)
python -m prompt_sigil compress examples/complex.md --ratio 0.4 --render-pair
# tokens     1040 -> 493  (47.4%)
# preserved  23 imperatives, 5 code blocks, 2 urls
# also writes before/after sigils for visual diff

The webapp runs entirely on your machine. The optional in-browser LLM (SmolLM2 / Qwen3 / Gemma 3 / Gemma 4) is downloaded once into IndexedDB and runs locally afterward — no API keys, no telemetry. The tensor scope additionally needs torch + transformers (CPU-only is fine) and optionally umap-learn.

2. Latent Sigil — Qwen mid-layer to magic circle, bidirectional

A PyTorch backend (Qwen2.5-0.5B, 24 layers, 896-dim hidden state) extracts the middle layer's residual stream for any prompt, projects it through a fixed PCA-2 basis built from a 210-phrase bilingual reference corpus, and renders the result as a sigil.

The same figure works in reverse: draw a point on the circle, get text that steers in that semantic direction.

Encode (text → figure) Decode (figure → text)
Sentence → forward pass on Qwen2.5-0.5B → mean-pool layer 12 → L2-normalize → project through fixed PCA-2 basis → 2D position + per-token trajectory User clicks a point → K-nearest atlas phrases in 2D → average their full 896-d hidden states → register forward_hook on layer 12 that adds α·v to residual → sample K completions

The atlas is laid out as 17 category arcs around the rim (instruction, nature, polite, tech, …). Each category has a Unicode glyph mnemonic; phrases within a category form a coloured band. The pool of a new encode lands inside the ring, with per-token hidden states drawn as a numbered trail.

# uv-managed environment (recommended)
uv sync

# 1. One-time: build the fixed PCA-2 basis from the reference corpus.
#    Downloads Qwen2.5-0.5B (~500 MB) on first run, then ~45 s to encode
#    the 210-phrase corpus on CPU.
uv run python -m latent_sigil.build_basis

# 2. Run the FastAPI server
uv run uvicorn latent_sigil.server:app --port 8766
# → http://localhost:8766/latent.html

Generation costs ~4 s per 40-token sample on CPU. The encode endpoint returns in ~0.2 s for a sentence.


How to use Prompt Sigil

  1. Click ⌂ blank to start with an empty canvas.
  2. Pick a glyph: persona, reasoning, tools, output, style, limits, memory, examples.
  3. Click on the figure to place a typed vertex (it snaps to the rim).
  4. Click an existing vertex of the same type to cycle its preset.
  5. Use ↔ bridge to connect two vertices semantically.
  6. Click ✦ scaffold — the markdown system prompt is generated for you.
  7. Click conjure to render the real sigil from that prompt.
  8. Open live inference, load a model (SmolLM2-135M is the fastest first download), type a question, click infer.
  9. Watch the gold thought trajectory draw itself across the circle.

You can also free-hand draw on top of an existing sigil:

  • Closed shape around a section → emphasize it in the next query.
  • Line through ≥2 sections → bridge them.
  • Two crossing strokes near a section → suppress it.

The drawn intent is appended to your query before inference.

Tensor scope

Open the ⌗ tensor scope panel and click extract: the server runs one forward pass with output_hidden_states=True (PyTorch + HF transformers, bypassing the ONNX-export limitation that would otherwise drop intermediate layers), projects all (layer × token) hidden states through a single shared PCA / UMAP / t-SNE basis, and renders one of two views.

Mandala view is the magic-circle reading. Concentric rings = layers (outer = embedding, inner = output). Each token sits at a fixed angle around the rim; following its radial spoke shows how its representation travels through depth. Per-layer normalisation keeps the colours vibrant even when one PCA axis dominates the global variance.

Scatter view is a 3D point cloud through PCA space, with each token's trajectory as a polyline.

In either view, every cell carries its own meaning:

  • Hover: tooltip with token, layer, the three PC values, and the top-k logit-lens predictions for that cell (nostalgebraist 2020).
  • Click a token to follow its spoke through every layer; its full D-dim hidden state is drawn as a morphing radial shape that reshapes between layers, synced with a top-k bar chart.
  • Click a layer ring to jump to that layer.
  • Scroll = zoom (cursor-anchored), drag = pan, double-click = reset.

The tensor scope is intentionally decoupled from compression. It is a viewer for human inspection, not a pipeline stage; nothing flows back into prompt processing.


How to use Latent Sigil

  1. Type a sentence into ① 文字 → 魔法陣 and click Encode. A gold disc appears at the pool position; the per-token trajectory threads through it numbered 1..N with a blue→gold gradient.
  2. Click anywhere inside the ring to place a green draw mark. The mark's angle (relative to centre) determines which category direction the steering will pull toward.
  3. Set a prompt under ② 魔法陣 → 文字 (the model continues this text) and click Generate. Three samples appear, all sharing the nuance of the direction you drew but with different surface text.
  4. The view supports mouse-wheel zoom, drag-pan, and double-click to reset. ⤺ atlas snaps back to atlas-only zoom; ⤡ fit all frames everything including any encoded trajectory.
  5. ◯ ring / ✦ scatter toggles between the magic-circle ring layout and the raw PCA-2 scatter (same data, different view).

The steering sweet spot is α = 5–10. Below 3 the nuance is invisible; above 20 the model collapses into noise tokens.


Functional beauty (the rule we never break)

Every visual element is a 1:1 mapping to a measured property of the input. Examples:

Prompt Sigil:

  • Section vertex angle = atan2 of the section's PCA-2 embedding.
  • Slot width = equal (sections are parallel things, not weighted by tokens).
  • Tick band density = token count.
  • Inner polygon edges = pairwise cosine similarity between sections.
  • Sentence cloud = each sentence as a 2D point in the same PCA basis.
  • Thought dots (gold) = generated text projected through the same basis.

Tensor scope:

  • Ring index = layer (outer → embedding, inner → output).
  • Angular position = token order.
  • Cell colour = PCA / UMAP / t-SNE projection of the cell's hidden state.
  • Morphing radial shape = the selected token's full D-dim hidden state.

Latent Sigil:

  • Gold pool disc = full prompt's layer-12 hidden state, projected.
  • Numbered token dots (blue→gold) = each token's hidden state at layer 12, with the colour gradient encoding sequence position.
  • Atlas glyph position on the rim = sort order of category centroid angles.
  • Atlas phrase position within a slot = its individual angle in the slot.
  • Green draw mark = user's chosen steering direction.

Same input always produces the same sigil. There is no randomness, no "styling for effect."


Repository layout

prompt_sigil/        Pure-Python lib: markdown → measured tree → 2D projection
  parse.py           Hand-rolled markdown parser (Japanese imperatives included)
  analyze.py         TF-IDF + PCA-2 (CLI), embedding-based PCA-2 (webapp)
  render.py          SVG output for the CLI path
  compress.py        Importance-scored extractive compression

latent_sigil/        Qwen2.5-0.5B mid-layer pipeline + FastAPI server
  __init__.py        Constants: MODEL_ID, LAYER=12, D_MODEL=896
  model.py           Lazy model load, encode_text(), generate_with_steering()
  corpus.py          210 bilingual reference phrases across 17 categories
  build_basis.py     One-shot: encode corpus, fit PCA-2, save atlas + basis
  server.py          FastAPI: /api/atlas, /api/encode, /api/decode
  cache/             basis.npz + atlas.json (gitignored, built locally)

webapp/              Two frontends, one stdlib server
  server.py          Stdlib HTTP server: /api/{layout, project, parse,
                     positions, compress, pca, hidden_states} on port 8765.
                     HF transformers loaded only by /api/hidden_states —
                     keeps the base demo torch-free.
  static/index.html  Prompt Sigil UI + tensor scope (single-file, no build)
  static/latent.html Latent Sigil UI (single-file, talks to FastAPI on 8766)

examples/            Sample prompts for prompt-sigil
docs/                Screenshots, GIF, わかる.md (middle-school explainer)
pyproject.toml       uv-managed Python project (torch, transformers, fastapi)
requirements.txt     pip-friendly equivalent for the prompt-sigil server

Why two HTTP servers?

The original Prompt Sigil server stays in stdlib (http.server) — its job is to serve static files and run a small TF-IDF + PCA pipeline. The Latent Sigil server needs to host Qwen2.5-0.5B in process, which benefits from async (FastAPI/uvicorn) and a structured JSON API. They run on different ports (8765 and 8766) so you can run either, or both, without conflict.


Requirements

  • Python 3.10+ for the Prompt Sigil base demo
  • Python 3.12+ for Latent Sigil (modern type hints)
  • CPU-only PyTorch is sufficient — no GPU needed
  • ~700 MB disk for the Qwen2.5-0.5B model cache (Latent Sigil)
  • ~22 MB disk for the in-browser embedder (Prompt Sigil) — cached in IndexedDB by transformers.js

The pyproject.toml pins the PyTorch CPU wheel index so uv sync does the right thing on Windows/macOS/Linux without manual flags.


Status

Working today (May 2026):

  • Deterministic markdown-prompt → magic-circle rendering (Prompt Sigil)
  • 8-glyph composer for click-only prompt building
  • In-browser inference with thought-trajectory projection
  • CSS-driven rotation that survives WASM main-thread blockage
  • Free-hand stroke interpretation (emphasize / suppress / bridge)
  • One-click prompt scaffolding from typed-glyph composition
  • Extractive prompt compression that preserves sigil semantics
  • Tensor scope: per-layer per-token mandala with PCA/UMAP/t-SNE, zoom-pan, hover tooltips, click-to-follow, logit lens
  • Selected-token morph: raw D-dim hidden state as a closed radial shape that reshapes between layers, synced with top-k bar chart
  • Qwen2.5-0.5B encode + decode endpoints with K-NN-in-2D steering (Latent Sigil)
  • Ring atlas with 17 categorical arcs, glyph mnemonics, color bands
  • Double-scale rendering (atlas at one scale, encoded marks at another so both stay visible regardless of prompt length)

Tuning knobs:

  • latent_sigil/__init__.py:LAYER — currently 12 (the geometric middle of Qwen2.5-0.5B's 24 layers). Earlier layers are more lexical, later layers more task-specific.
  • Default alpha=7 in /api/decode — the steering vector magnitude. See "How to use Latent Sigil" above for the sweet-spot range.

Roadmap (help wanted)

Pick one, open a PR.

  1. AI proposes a sigil. User states a goal in one sentence; an LLM proposes a typed-glyph layout the user can accept or edit.

  2. Larger steering vocabulary. The current 210-phrase corpus covers 17 categories. Doubling that and adding more linguistic registers (academic / vernacular / poetic / technical) would sharpen the ring.

  3. Live thought trajectory during generation. Currently the trail is drawn after generation completes because WASM blocks the main thread. Moving inference into a Web Worker would unblock this for Prompt Sigil.

  4. Higher-rank basis for Latent Sigil. PCA-2 captures ~37% of the variance in the normalized hidden states. PCA-3/4 with one extra visual channel (size, opacity) could show more structure without collapsing the figure.

  5. Vertex drag. Allow composed vertices to be dragged along the rim so the user can curate the angular layout.

  6. Save and share. Encode sigil state into a URL hash so a circle can be sent as a link, loaded, and remixed.

  7. Hover preview of atlas phrases. Currently atlas dots have <title> tooltips. An overlay panel that shows the phrase as the user hovers would be more discoverable.

  8. Hidden-state-driven compression. Use the tensor scope's activation norms to bias the compression's token_importance map. Wiring is already in webapp/static/index.html.


Prior art

The unique niche of this project: aesthetic + data-driven + input-deterministic + bidirectional. Nothing else covers all four.


Contributing

The codebase is small (~4,500 lines total) and uses minimal frameworks (stdlib http.server for Prompt Sigil; FastAPI for Latent Sigil; no frontend build step). You should be able to read every file in one sitting.

Non-negotiables:

  • Determinism. Same input → same sigil. No randomness in the layout pipeline. (Sampling lives only in the steering decode path, and that is documented as variance-on-purpose.)
  • No decorative-only visual elements. Every mark maps to a measured property; "looks magical" is not a justification.
  • No build step for the frontend. The single-file static/*.html pattern is load-bearing — drop in a browser and it runs.

If you want to discuss a larger change before coding, open an issue describing the data → visual mapping you propose.


License

MIT — see LICENSE.

Citation

@misc{prompt-sigil-2026,
  title  = {Prompt Sigil + Latent Sigil:
            A Magic-Circle Protocol for Human--AI Communication},
  year   = {2026},
  url    = {https://github.com/jackasser/mahojin_magic_AI}
}

An open invitation: a small protocol that anyone can extend. The goal is not a polished product but a shared visual language that grows as more people contribute glyphs, mappings, and ways of listening to what the AI is saying back.