Skip to main content

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 StrictUndefined so missing variables fail fast.

Install

pip install prompt-template-to-messages

Quick start

  1. 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 %}
    
  2. 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"},
    )
    
  3. Send messages to 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 format runs ruff format on src/ and tests/.
  • make git-push formats your code before pushing.
  • make release formats, tests, lints, type-checks, builds, and then tags the release.

Contributing

  1. Clone the repo and run make install-dev.
  2. Use make format, make lint, and make test while iterating.
  3. Before pushing, run make git-push to enforce formatting.
  4. For publishing, follow make release and make upload.

License

MIT Licensed. See LICENSE for details.

Metadata

Release files for pt2m 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pt2m 0.1.0
File Size Uploaded
pt2m-0.1.0.tar.gz 9.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pt2m 0.1.0
File Interpreter ABI Platform
pt2m-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.9 kB

Release files / pt2m-0.1.0.tar.gz

Download URL pt2m-0.1.0.tar.gz
Size 9.5 kB
Tags Source
SHA-256 checksum
How to use checksums
08f60e0be9960beeee0c2a28df2399b46a0476f82fc2eaf5ad81dc135d573d68
BLAKE2b-256 checksum
How to use checksums
eca06e60b32837ed15466159f5092be570e54c9ef30a668cd727b897d713353c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release files / pt2m-0.1.0-py3-none-any.whl

Download URL pt2m-0.1.0-py3-none-any.whl
Size 11.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cc42eb6303a72774cee6cdf5b56272a246ec04444abd1eb939713ad10214ee41
BLAKE2b-256 checksum
How to use checksums
2428af2f7d19bfc0fd0b943a65c98c1638a1de0b5ea312fb0233a1d82b12a9b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page