Why create a prompt template?
Prompt templates and schemas simplify engineering iteration, experimentation, and optimization, especially as application complexity and team size grow. Notably, they enable you to:- Decouple prompts from application code. As you iterate on your prompts over time (or A/B test different prompts), you’ll be able to manage them in a centralized way without making changes to the application code.
- Collect a structured inference dataset. Imagine down the road you want to fine-tune a model using your historical data. If you had only stored prompts as strings, you’d be stuck with the outdated prompts that were actually used at inference time. However, if you had access to the input variables in a structured dataset, you’d easily be able to counterfactually swap new prompts into your training data before fine-tuning. This is particularly important when experimenting with new models, because prompts don’t always translate well between them.
- Implement model-specific prompts. We often find that the best prompt for one model is different from the best prompt for another. As you try out different models, you’ll need to be able to independently vary the prompt and the model and try different combinations thereof. This is commonly challenging to implement in application code, but trivial in TensorZero.
You can also find a complete runnable example for this guide on GitHub.
Set up a prompt template
1
Create your template
Create a file with your MiniJinja template:
config/functions/fun_fact/gpt_5_mini/fun_fact_topic_template.minijinja
TensorZero uses the MiniJinja templating language.
MiniJinja is mostly compatible with Jinja2, which is used by many popular projects like Flask and Django.
MiniJinja provides a browser playground where you can test your templates.
2
Configure a template
Next, you must declare the template in the variant configuration.
You can do this by adding the field
templates.your_template_name.path
to your variant with a path to your template file.For example, let’s configure a template called fun_fact_topic
for our variant:config/tensorzero.toml
You can configure multiple templates for a variant.
3
Use your template during inference
Use your template during inference by sending a content block with the template name and arguments.
Set up a template schema
When you have multiple variants for a function, it becomes challenging to ensure all templates use consistent variable names and types. Schemas solve this by defining a contract that validates template variables and catches configuration errors before they reach production. Defining a schema is optional but recommended.1
Create a schema
Create a JSON Schema for the variables used by your templates.Let’s define a schema for our previous example, which includes only a single variable
topic
:config/functions/fun_fact/fun_fact_topic_schema.json
LLMs are great at generating JSON Schemas.
For example, the schema above was generated with the following request:You can also export JSON Schemas from Pydantic models and Zod schemas.
2
Configure a schema
Then, declare your schema in your function definition using
schemas.your_schema_name.path
.
This will ensure that every variant for the function has a template named your_schema_name
.In our example above, this would mean updating the function definition to:Re-use prompt snippets
You can enable template file system access to reuse shared snippets in your prompts. To use the MiniJinja directives{% include %}
and {% import %}
, you need to enable template file system access with gateway.template_filesystem_access
.
See Organize your configuration for details.
Migrate from legacy prompt templates
In earlier versions of TensorZero, prompt templates were defined assystem_template
, user_template
, and assistant_template
.
Similarly, template schemas were defined as system_schema
, user_schema
, and assistant_schema
.
This legacy approach limited the flexibility of prompt templates restricting the ability to define multiple templates per role.
As you create new functions and templates, you should use the new templates.your_template_name.path
format.
Historical observability data stored in your ClickHouse database still uses the legacy format.
If you want to keep this data forward-compatible (e.g. for fine-tuning), you can update your configuration as follows:
Legacy Configuration | Updated Configuration |
---|---|
system_template | templates.system.path |
system_schema | schemas.system.path |
user_template | templates.user.path |
user_schema | schemas.user.path |
assistant_template | templates.assistant.path |
assistant_schema | schemas.assistant.path |