Skip to main content

Git-native prompt engineering library with Registry/Lab dual-state model

Project description

PromptTree

PromptTree

Git-native prompt engineering library. Version and manage your LLM prompts like code — with a branching registry, Jinja2 templating, AES-256 encryption, and a visual UI.


Install

pip install prompttree          # core library + CLI
pip install "prompttree[ui]"    # with Streamlit UI

Requires Python 3.10+.


Quick Start

prompttree init    # creates .prompttree/ workspace in current directory
import prompttree as pt

engine = pt.PromptTree()

# Save a prompt and label it
node = engine.save(
    content="Analyze {{component}} in drawing {{drawing}}.",
    name="P&ID Analyzer",
    display_name="v1",
    model="gpt-4o",
    temperature=0.7,
    label="prod",
)

# Render it with variables
prompt = engine.get_prompt("prod", vars={"component": "valve", "drawing": "GAD_05"})
print(prompt)
# → "Analyze valve in drawing GAD_05."

Core Concepts

Registry

The Registry is the versioned store for your prompts. Each prompt is saved as a node — a YAML file containing the content, model settings, and a pointer to its parent node.

Nodes form a DAG (directed acyclic graph): you branch from any existing node to create a new version, preserving the full lineage.

P&ID Analyzer
├── v1  ←  label: prod
├── v2  (branched from v1)
└── v3  (branched from v1)

All nodes live in .prompttree/registry/nodes/ and are git-tracked — diffs, history, and blame work out of the box.

Labels

Labels are human-readable aliases that point to a specific node. Use them to decouple your application code from node IDs.

engine.set_label("prod", node.id)
engine.set_label("dev", other_node.id)

engine.get_prompt("prod", vars={...})   # always resolves to the labelled node

Labels are stored in .prompttree/registry/labels.json.

Jinja2 Templating

Prompt content supports Jinja2 {{ variable }} syntax. Variables are injected at render time via get_prompt().

node = engine.save("Summarise {{text}} in {{language}}.", name="Summariser")
prompt = engine.get_prompt(node.id, vars={"text": "the report", "language": "French"})

API Reference

PromptTree(storage, key)

Parameter Default Description
storage ".prompttree" Path to workspace directory
key None AES-256 decryption key (only needed for encrypted registries)

Methods

engine.save(content, name, display_name, model, temperature, parent_id, tags, label)  RegistryNode
engine.get_prompt(label_or_id, vars)  str
engine.get_node(node_id)  RegistryNode | None
engine.list_nodes()  list[RegistryNode]
engine.list_names()  list[str]
engine.get_labels()  dict[str, str]
engine.set_label(label, node_id)
engine.lock(key)  int
engine.unlock(key)  int

Branching Versions

Branch from any node by passing parent_id:

v1 = engine.save("Analyze {{component}}.", name="Analyzer", label="prod")

v2 = engine.save(
    "Analyze {{component}} and flag anomalies.",
    name="Analyzer",
    display_name="v2",
    parent_id=v1.id,
)

# Promote v2 to prod when ready
engine.set_label("prod", v2.id)

Encryption

Encrypt all registry nodes before deploying to CI/production:

prompttree lock --key $PT_KEY      # encrypts all nodes in-place
prompttree unlock --key $PT_KEY    # decrypts back to plaintext

Decryption happens in-memory at render time — the encrypted YAML is never modified:

engine = pt.PromptTree(key="my-secret-key")
prompt = engine.get_prompt("prod", vars={...})   # decrypts on the fly

Uses AES-256-GCM with a random nonce per encryption. The key is SHA-256 hashed so any string length is accepted.


CLI

prompttree init                        # initialise workspace + update .gitignore
prompttree list                        # list all nodes and labels
prompttree lock --key $PT_KEY          # encrypt registry
prompttree unlock --key $PT_KEY        # decrypt registry
prompttree ui                          # launch the visual UI
prompttree ui --port 8080              # on a custom port

Visual UI

Launch a browser-based DAG explorer to create, browse, and branch prompts:

prompttree ui

Opens at http://localhost:8501.

  • Browse all prompt families from the dropdown
  • Click any node in the DAG to inspect its content and metadata
  • Branch directly from any node
  • Assign labels to nodes

Workspace Layout

.prompttree/
├── registry/
│   ├── nodes/          # one YAML file per prompt node (git-tracked)
│   └── labels.json     # label → node ID map (git-tracked)

.prompttree/.lab/ and .prompttree/.artifacts/ are local-only and automatically added to .gitignore by prompttree init.


Node YAML Format

id: "a1b2c3d4..."
parent_id: null
name: "P&ID Analyzer"
display_name: "v1"
metadata:
  encrypted: false
  model: "gpt-4o"
  temperature: 0.7
  created_at: "2024-01-01T00:00:00+00:00"
  tags: []
content: "Analyze {{component}} in drawing {{drawing}}."

Development

git clone https://github.com/yedhuk/prompttree
cd prompttree
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,ui]"

pytest          # run tests
ruff check prompttree/
mypy prompttree/

License

MIT © Yedhu Krishna

Project details


Download files

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

Source Distribution

prompttree-1.0.3.tar.gz (51.7 kB view details)

Uploaded Source

Built Distribution

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

prompttree-1.0.3-py3-none-any.whl (48.8 kB view details)

Uploaded Python 3

File details

Details for the file prompttree-1.0.3.tar.gz.

File metadata

  • Download URL: prompttree-1.0.3.tar.gz
  • Upload date:
  • Size: 51.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for prompttree-1.0.3.tar.gz
Algorithm Hash digest
SHA256 bfe99894d32b66b5c9242e26b47e0065b46033068a21564d4d1366c6bc0b4a24
MD5 9b66d6efeb64fcc609e67a0d7f3915b1
BLAKE2b-256 f7e446bb8f2aa92a342107c61ed8a91a87a8a0e0b99571e9328114400c62aa53

See more details on using hashes here.

File details

Details for the file prompttree-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: prompttree-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 48.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for prompttree-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f589ab7df8083d07adefdce328dcf81f55e247e458aaf1537417a47d09e5910a
MD5 f5c5c4415712d9f9bde8922c07fa5e05
BLAKE2b-256 69ea1a6fd668011e5e80e022e1afa3027ffed5ad997981197a34953b2c4f952c

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