This project has been archived by its maintainers, and is no longer receiving any updates.
prompt-template-to-messages
Turn richly annotated Jinja2 prompts into OpenAI-compatible message payloads without giving up the ergonomics of plain text version control.
Why this project exists
Most prompt repositories still manage prompts as plain text. Diffing, reviewing, and versioning become easy, but multimodal prompts are hard to author and ship. prompt-template-to-messages embraces templates: you keep a single text file that mixes roles, function calls, and rich metadata via helper functions, which render into HTML-like tags prefixed with pt2m-. Under the hood, we combine Jinja2 for rendering dynamic content and BeautifulSoup-powered parsing to compile the result into the structured messages array required by OpenAI-compatible APIs. Welcome to the template era.
Key features
- Author prompts once and render them as OpenAI
messages. - Keep prompts in Git-friendly text files while supporting multimodal content.
- Compose translators to customize how tags produce message fragments.
- Strict rendering: Jinja2 runs with
StrictUndefinedso missing variables fail fast.
Install
pip install prompt-template-to-messages
Quick start
-
Create a template file
welcome.pt2m.jinja:{% set user_name = user_name or "friend" %} {% call _pt2m_message('system') %} You are a concise onboarding assistant. {% endcall %} {% call _pt2m_message('user') %} Hello, {{ user_name }}! {{ _pt2m_resolve_image(intro_image_url, alt='Welcome illustration') }} {% endcall %} -
Render it with Python:
from prompt_template_to_messages import compile_prompt_to_messages template_text = open("welcome.pt2m.jinja", "r", encoding="utf-8").read() messages = compile_prompt_to_messages( template_text, scope={"user_name": "Ada", "intro_image_url": "https://example.com/welcome.png"}, )
-
Send
messagesto your favorite chat completion client.
Examples
Image-only broadcast
Use a scope variable to supply an image URL and render a message that contains only image_url content:
template
{% call _pt2m_message('user') -%}
{{ _pt2m_resolve_image(hero_image, detail='high') }}
{%- endcall %}
scope
scope = {"hero_image": "https://cdn.example/hero.png"}
messages = compile_prompt_to_messages(template, scope=scope)
# -> [{'role': 'user', 'content': [{'type': 'image_url', 'image_url': {'url': 'https://cdn.example/hero.png', 'detail': 'high'}}]}]
Custom translator with plain tags
Plain HTML-like tags that appear in the rendered template can be whitelisted by registering translators. The example below mixes _pt2m_ helpers with a scope function that emits <multi-modal> tags:
from prompt_template_to_messages import compile_prompt_to_messages
template = """{% call _pt2m_message('assistant') -%}Gallery incoming: {{ render_multi_modal(featured) }}{%- endcall %}"""
def render_multi_modal(asset):
return f'<multi-modal ref="{asset["ref"]}" caption="{asset["caption"]}" detail="{asset["detail"]}" />'
def multi_modal_translator(tag, context):
return {
"type": "multi-modal",
"multi_modal": {
"ref": tag.attrs.get("ref"),
"caption": tag.attrs.get("caption"),
"detail": tag.attrs.get("detail"),
},
}
scope = {"featured": {"ref": "hero.png", "caption": "Hero", "detail": "medium"}, "render_multi_modal": render_multi_modal}
messages = compile_prompt_to_messages(template, scope=scope, translators=[("multi-modal", multi_modal_translator)])
Any translator added through translators=[...] is treated as part of the whitelist, so its tag will be parsed even without the pt2m- prefix.
CLI usage
This package ships a CLI named ptm.
ptm render TEMPLATE_PATH --scope scope.json --output messages.json
--scope accepts a JSON file, and --output writes the compiled messages. Run ptm --help for all options.
Formatting and release workflow
The Makefile encodes the recommended workflow:
make formatrunsruff formatonsrc/andtests/.make git-pushformats your code before pushing.make releaseformats, tests, lints, type-checks, builds, and then tags the release.
Contributing
- Clone the repo and run
make install-dev. - Use
make format,make lint, andmake testwhile iterating. - Before pushing, run
make git-pushto enforce formatting. - For publishing, follow
make releaseandmake upload.
License
MIT Licensed. See LICENSE for details.
Metadata
Release files for prompt-template-to-messages 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| prompt_template_to_messages-0.1.0.tar.gz | 9.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| prompt_template_to_messages-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.1 kB
Release files / prompt_template_to_messages-0.1.0.tar.gz
| Download URL | prompt_template_to_messages-0.1.0.tar.gz |
|---|---|
| Size | 9.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3ace4e83de67363cf731aee1e4dcc39b4087ed2eb25fd1f43d34e03dda64c39d
|
|
BLAKE2b-256 checksum How to use checksums |
2c0c550f9338040605fcd0b05af3bcb7551487470cf14ff24b7189fb12e93d8a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.7
|
Release files / prompt_template_to_messages-0.1.0-py3-none-any.whl
| Download URL | prompt_template_to_messages-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6078f54872a6f93c0ebb96e0c1d73b1d5ce1be53aa506bf35a99580911ab3496
|
|
BLAKE2b-256 checksum How to use checksums |
68d74096df6af9e88971ae4fd6beff9afcaecf173b454ffa323874b4c8768c80
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.7
|