Skip to main content

A prompt template engine for LLM apps: validated variables, reusable few-shot blocks, and clean chat/message construction.

Project description

promptkit

PyPI Python versions License: MIT

promptkit

A prompt template engine for LLM apps: validated variables, reusable few-shot blocks, and clean chat/message construction.

Part of the ragkit suite. Install with pip install ragkit-promptkit, then import promptkit.

promptkit replaces scattered f-strings that silently break when a variable is missing. You define templates once, get up-front validation of required variables, compose few-shot prompts, and build OpenAI-style message lists without hand-assembling dicts. Zero third-party dependencies -- standard library only, Python 3.8+.

Install

pip install ragkit-promptkit

Local development (from promptkit/):

pip install -e .

Quick Start

Define a template, inspect its variables, and render it:

from promptkit import PromptTemplate

tmpl = PromptTemplate("Summarize the following {kind} in {n} sentences:\n\n{text}")

print(tmpl.variables)   # {'kind', 'n', 'text'}

print(tmpl.render(kind="article", n=3, text="..."))

render() also accepts a single dict:

tmpl.render({"kind": "article", "n": 3, "text": "..."})

Missing variables are reported all at once

If a referenced variable has no value (and no default), you get a MissingVariableError listing every missing name -- not just the first:

from promptkit import PromptTemplate, MissingVariableError

tmpl = PromptTemplate("{greeting}, {name}! Welcome to {place}.")

try:
    tmpl.render(greeting="Hello")
except MissingVariableError as exc:
    print(exc)          # Missing required variable(s): 'name', 'place'
    print(exc.missing)  # ['name', 'place']

Extra/unknown keyword arguments are ignored, so you can safely pass a shared context dict to many templates.

Literal braces

Use {{ and }} for literal braces (same rules as str.format):

PromptTemplate('Return JSON like {{"score": {n}}}').render(n=5)
# Return JSON like {"score": 5}

Defaults and partial()

Provide defaults for optional variables, and use partial() to bake in some values while leaving the rest open:

from promptkit import PromptTemplate

tmpl = PromptTemplate(
    "You are a {tone} assistant. Answer: {question}",
    defaults={"tone": "friendly"},
)

tmpl.render(question="What is Python?")
# "You are a friendly assistant. Answer: What is Python?"

# Bake in the tone, get a new reusable template:
sarcastic = tmpl.partial(tone="sarcastic")
sarcastic.render(question="What is Python?")
# "You are a sarcastic assistant. Answer: What is Python?"

An explicit value always overrides a default. partial() returns a new template and never mutates the original.

Few-shot prompts

FewShotTemplate stitches a prefix, a list of rendered examples, and a suffix (which usually holds the final user query):

from promptkit import FewShotTemplate

few = FewShotTemplate(
    example_template="Q: {q}\nA: {a}",
    examples=[
        {"q": "2 + 2", "a": "4"},
        {"q": "3 * 3", "a": "9"},
    ],
    prefix="Solve the math problems.",
    suffix="Q: {question}\nA:",
    example_separator="\n\n",
)

# Add more examples dynamically:
few.add_example(q="10 - 4", a="6")

print(few.render(question="7 + 5"))

Output:

Solve the math problems.

Q: 2 + 2
A: 4

Q: 3 * 3
A: 9

Q: 10 - 4
A: 6

Q: 7 + 5
A:

Missing-variable validation applies across the prefix, examples, and suffix.

Chat prompts -> message dicts

ChatPromptTemplate builds OpenAI-style list[dict] message payloads. Each message content is rendered with the same PromptTemplate rules, and missing variables are aggregated across all messages:

from promptkit import ChatPromptTemplate, system, user, assistant

chat = ChatPromptTemplate.from_messages([
    system("You are a helpful {role}."),
    user("Explain {topic} to a {level} audience."),
])

messages = chat.render(role="tutor", topic="recursion", level="beginner")
# [
#   {"role": "system", "content": "You are a helpful tutor."},
#   {"role": "user", "content": "Explain recursion to a beginner audience."},
# ]

Pass messages straight to your LLM client. The system, user, and assistant helpers just return (role, template) tuples. If you prefer typed objects, chat.render_messages(...) returns Message(role, content) dataclass instances (each has .to_dict()).

Prompt registry and versioning

PromptRegistry is a tiny in-memory store for named, versioned prompts. get() returns the latest version by default:

from promptkit import PromptRegistry, PromptTemplate

registry = PromptRegistry()

registry.register(PromptTemplate("Summarize: {text}", name="summarize", version="1.0"))
registry.register(PromptTemplate("TL;DR the following:\n{text}", name="summarize", version="2.0"))

registry.list()                       # ['summarize']
registry.get("summarize")             # v2.0 (latest)
registry.get("summarize", version="1.0")  # the v1.0 template

latest = registry.get("summarize")
latest.render(text="...")

Versions are compared numerically when they look like dotted numbers ("1.0", "2.3"), falling back to string comparison otherwise.

API summary

Object Purpose
PromptTemplate Single-string template with {var} placeholders, defaults, partial(), and .variables.
FewShotTemplate Prefix + examples + suffix composition with add_example().
ChatPromptTemplate Renders (role, template) pairs to message dicts.
Message dataclass(role, content) with .to_dict().
system / user / assistant Helpers returning (role, template) tuples.
PromptRegistry In-memory register / get / list with versioning.
MissingVariableError Raised with .missing listing every unresolved variable.

License

MIT

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

ragkit_promptkit-0.1.1.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

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

ragkit_promptkit-0.1.1-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file ragkit_promptkit-0.1.1.tar.gz.

File metadata

  • Download URL: ragkit_promptkit-0.1.1.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for ragkit_promptkit-0.1.1.tar.gz
Algorithm Hash digest
SHA256 33db66adcfeb324d59d739898980e5f87331b73d0d029963a12475d3640b5f2b
MD5 9e28e351496c83b2f9ffb99711f8e745
BLAKE2b-256 6fa98c82a583a08cd04da6b4a359873b9f68a0901fe070eb2fa9d8adee6d68b6

See more details on using hashes here.

Provenance

The following attestation bundles were made for ragkit_promptkit-0.1.1.tar.gz:

Publisher: publish.yml on Meet2147/pythonLibraries

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ragkit_promptkit-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for ragkit_promptkit-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2de9e349d91aeea0f6e452811a6b972a5e2ff8d1ba9a99b3027f86b38f6bb69c
MD5 64709795e4b337d54a450555ba40bd6b
BLAKE2b-256 a52a335ca824a8ede9fca0fdcfdb63797c1b291f18473a8ef716cd991105177e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ragkit_promptkit-0.1.1-py3-none-any.whl:

Publisher: publish.yml on Meet2147/pythonLibraries

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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