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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03c2099b83080d144448e12c7f94192e3503cfa5c55359f2e07a6143703d97c2
|
|
| MD5 |
1227357bda238b022ecb40d185ded25d
|
|
| BLAKE2b-256 |
bc3b6918eeede245be7b22bcbb3419d85aadb2e9d7fd201c2384389ca1dc8dc8
|
Provenance
The following attestation bundles were made for prompt_template-1.2.0.tar.gz:
Publisher:
release.yaml on Goldziher/prompt-template
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prompt_template-1.2.0.tar.gz -
Subject digest:
03c2099b83080d144448e12c7f94192e3503cfa5c55359f2e07a6143703d97c2 - Sigstore transparency entry: 170712034
- Sigstore integration time:
-
Permalink:
Goldziher/prompt-template@e265792a8fd84d196df792a27f4280385f5fc34e -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/Goldziher
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@e265792a8fd84d196df792a27f4280385f5fc34e -
Trigger Event:
release
-
Statement type:
File details
Details for the file prompt_template-1.2.0-py3-none-any.whl.
File metadata
- Download URL: prompt_template-1.2.0-py3-none-any.whl
- Upload date:
- Size: 8.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96f6f0f8d3fcbddd0816aeb2cd95632b9e08d38e786963a23260abf6da45629b
|
|
| MD5 |
25d1aa797f7c77ae108ea3e3bc01ab2d
|
|
| BLAKE2b-256 |
34d0ed203aabbb1d131fbea89c5fe42aa13cadb49ebc5dafc781170049e3c7f5
|
Provenance
The following attestation bundles were made for prompt_template-1.2.0-py3-none-any.whl:
Publisher:
release.yaml on Goldziher/prompt-template
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
prompt_template-1.2.0-py3-none-any.whl -
Subject digest:
96f6f0f8d3fcbddd0816aeb2cd95632b9e08d38e786963a23260abf6da45629b - Sigstore transparency entry: 170712035
- Sigstore integration time:
-
Permalink:
Goldziher/prompt-template@e265792a8fd84d196df792a27f4280385f5fc34e -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/Goldziher
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@e265792a8fd84d196df792a27f4280385f5fc34e -
Trigger Event:
release
-
Statement type: