Skip to main content

A robust zero-dependency library for creating prompt templates

Project description

Prompt Template

A lightweight, zero-dependency Python library for managing LLM prompt templates. Built on the design principles of string.Template but with enhanced features specifically designed for LLM prompt engineering.

Features

  • Strong template validation with detailed error messages
  • Support for nested braces and complex JSON structures
  • Automatic value serialization for common Python types
  • Default value support with deep copying for mutable types
  • Incremental template population with value inheritance
  • Type hints for enhanced IDE support
  • Zero dependencies - just pure Python
  • 100% test coverage

Installation

pip install prompt-template

Usage

The library is intentionally very simple to use. The idea is to keep it simple, have validation and serialization builtin, and make debugging simple.

Simple Templates

from prompt_template import PromptTemplate

# Create a template
template = PromptTemplate("Hello ${name}! Welcome to ${location}.")

# Render with values
result = template.to_string(name="Alice", location="Wonderland")
print(result)  # Hello Alice! Welcome to Wonderland.

Default Values

# Set default values that can be overridden later
template = PromptTemplate("Hello ${name}! Your settings are: ${settings}")

# Set default values - they're safely deep copied
template.set_default(
    name="Guest",
    settings={"theme": "light", "language": "en"}
)

# Use with defaults
print(template.to_string())
# Hello Guest! Your settings are: {"theme": "light", "language": "en"}

# Override specific values
print(template.to_string(name="Alice"))
# Hello Alice! Your settings are: {"theme": "light", "language": "en"}

# Override everything
print(template.to_string(
    name="Bob",
    settings={"theme": "dark", "language": "fr"}
))
# Hello Bob! Your settings are: {"theme": "dark", "language": "fr"}

Named Templates

Adding a name to your template enhances error messages with context. Templates with the same name and content are considered equal:

# Create named templates
template1 = PromptTemplate(
    name="user_greeting",
    template="Hello ${name}! Welcome to ${location}."
)

# Templates can be compared and used as dictionary keys
template2 = PromptTemplate(
    name="user_greeting",
    template="Hello ${name}! Welcome to ${location}."
)
assert template1 == template2

# Templates have a readable string representation
print(template1)  # PromptTemplate [user_greeting]:\n\nHello ${name}! Welcome to ${location}.

Complex JSON Templates

The library handles nested structures elegantly:

template = PromptTemplate("""
{
    "user": {
        "name": "${username}",
        "role": "${role}"
    },
    "settings": {
        "theme": "${theme}",
        "notifications": ${notifications},
        "preferences": ${preferences}
    }
}
""")

# Values are automatically serialized
result = template.to_string(
    username="john_doe",
    role="admin",
    theme="dark",
    notifications={"email": True, "push": False},
    preferences=["daily_digest", "weekly_report"]
)

Template Methods

The library provides two main methods for populating templates:

# to_string(): Validates inputs, uses defaults, and serializes values
template = PromptTemplate("Hello ${name}!")
template.set_default(name="Guest")
result = template.to_string()  # Uses default
result = template.to_string(name="Alice")  # Overrides default

# substitute(): Lower-level method for partial population
base = PromptTemplate("${greeting} ${name}!")
partial = base.substitute(greeting="Hello")  # Returns a string
final = PromptTemplate(partial).to_string(name="Alice")

Nested Templates

Templates can be nested within other templates:

# Create nested templates
inner = PromptTemplate("My name is ${name}")
inner.set_default(name="Alice")

outer = PromptTemplate("""
User message:
${message}
""")

# Combine templates
result = outer.to_string(message=inner.to_string())
print(result)
# User message:
# My name is Alice

Type Handling and Automatic Serialization

The library automatically handles various Python types:

from uuid import UUID
from decimal import Decimal
from datetime import datetime

template = PromptTemplate("""
{
    "id": "${id}",
    "amount": "${amount}",
    "metadata": ${metadata}
}
""")

result = template.to_string(
    id=UUID("550e8400-e29b-41d4-a716-446655440000"),
    amount=Decimal("45.67"),
    metadata={
        "timestamp": datetime.now(),  # Serialized via JSON
        "values": [1, 2, 3]
    }
)

Custom Serialization

Extend the base class to customize value serialization with proper error handling:

from typing import Any
from datetime import datetime
from decimal import Decimal
from prompt_template import PromptTemplate as BasePromptTemplate
import orjson


class PromptTemplate(BasePromptTemplate):
    @staticmethod
    def serializer(value: Any) -> str:
        """Custom serializer with orjson for better performance.

        Handles special cases and provides detailed error messages.
        """
        try:
            # Handle special types first
            if isinstance(value, (datetime, Decimal)):
                return str(value)

            # Use orjson for everything else
            return orjson.dumps(value).decode('utf-8')
        except (TypeError, ValueError) as e:
            raise TypeError(
                f"Failed to serialize value of type {type(value).__name__}: {e}"
            ) from e

The custom serializer will be used automatically:

template = PromptTemplate("""
{
    "timestamp": "${time}",
    "amount": "${price}",
    "data": ${complex_data}
}
""")

result = template.to_string(
    time=datetime.now(),
    price=Decimal("45.67"),
    complex_data={"nested": [1, 2, 3]}
)

Error Handling

The library provides specific extensive errors:

Missing Values

from prompt_template import MissingTemplateValuesError

template = PromptTemplate("Hello ${name}!")
try:
    template.to_string()  # No values provided
except MissingTemplateValuesError as e:
    print(f"Missing values: {e.missing_values}")  # {'name'}

Invalid Keys

from prompt_template import InvalidTemplateKeysError

template = PromptTemplate("Hello ${name}!")
try:
    template.to_string(name="World", invalid_key="value")
except InvalidTemplateKeysError as e:
    print(f"Invalid keys: {e.invalid_keys}")  # ['invalid_key']
    print(f"Valid keys: {e.valid_keys}")  # {'name'}

Serialization Errors

from prompt_template import TemplateSerializationError

template = PromptTemplate("Value: ${value}")
try:
    template.to_string(value=object())  # Non-serializable object
except TemplateSerializationError as e:
    print(f"Failed to serialize key '{e.key}': {e.original_error}")

License

MIT License

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

prompt_template-1.2.0.tar.gz (39.1 kB view details)

Uploaded Source

Built Distribution

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

prompt_template-1.2.0-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file prompt_template-1.2.0.tar.gz.

File metadata

  • Download URL: prompt_template-1.2.0.tar.gz
  • Upload date:
  • Size: 39.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for prompt_template-1.2.0.tar.gz
Algorithm Hash digest
SHA256 03c2099b83080d144448e12c7f94192e3503cfa5c55359f2e07a6143703d97c2
MD5 1227357bda238b022ecb40d185ded25d
BLAKE2b-256 bc3b6918eeede245be7b22bcbb3419d85aadb2e9d7fd201c2384389ca1dc8dc8

See more details on using hashes here.

Provenance

The following attestation bundles were made for prompt_template-1.2.0.tar.gz:

Publisher: release.yaml on Goldziher/prompt-template

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

File details

Details for the file prompt_template-1.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for prompt_template-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 96f6f0f8d3fcbddd0816aeb2cd95632b9e08d38e786963a23260abf6da45629b
MD5 25d1aa797f7c77ae108ea3e3bc01ab2d
BLAKE2b-256 34d0ed203aabbb1d131fbea89c5fe42aa13cadb49ebc5dafc781170049e3c7f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for prompt_template-1.2.0-py3-none-any.whl:

Publisher: release.yaml on Goldziher/prompt-template

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