Templates

Embabel supports Jinja templates for generating prompts. You do this via the PromptRunner.rendering(String) method.

This method takes a Spring resource path to a Jinja template. The default location is under classpath:/prompts/ and the .jinja extension is added automatically.

You can also specify a full resource path with Spring resource conventions.

Once you have specified the template, you can create objects using a model map.

Template syntax inside substituted values is treated as literal data by default. This prevents values such as user-provided text containing {{ expression }} from being evaluated recursively.

The renderer can be configured under embabel.agent.platform.template:

embabel:
  agent:
    platform:
      template:
        prefix: "classpath:/prompts/"
        suffix: ".jinja"
        fail-on-unknown-tokens: false
        nested-interpretation-enabled: false

Do not enable it for templates that interpolate untrusted or user-provided text.

An example:

DistinctFactualAssertions distinctFactualAssertions = context.ai()
    .withLlm(properties.deduplicationLlm())
    // Jinjava template from classpath at prompts/factchecker/consolidate_assertions.jinja
    .rendering("factchecker/consolidate_assertions")
    .createObject(
            DistinctFactualAssertions.class,
            Map.of(
                    "assertions", allAssertions,
                    "reasoningWordCount", properties.reasoningWordCount()
            )
    );

System Prompts from Templates

To render a template into the system prompt of a regular PromptRunner chain, wrap the runner in a TemplatedPromptRunnerBuilder. It renders the template with the platform’s TemplateRenderer and returns a runner with the result applied via withSystemPrompt(), leaving all downstream operations unchanged.

PromptRunner runner = new TemplatedPromptRunnerBuilder(context, context.ai().withLlm(llm))
    .withSystemPromptTemplate(
            "support/system_prompt",
            Map.of("company", companyName)
    );

Answer answer = runner.createObject(question, Answer.class);

Custom Template Renderer

By default, rendering() uses the platform’s TemplateRenderer (a Jinja-based renderer that loads templates from the classpath). You can override this on a per-rendering basis using withTemplateRenderer(), which lets you supply a custom TemplateRenderer implementation.

This is useful when you need to load templates from a different source—for example, pulling templates from a user-specific directory on the file system, or from a database, enabling per-tenant or per-user prompt customization.

TemplateRenderer perUserRenderer = createRendererForUser(userId);

String result = context.ai()
    .rendering("user-greeting")
    .withTemplateRenderer(perUserRenderer)
    .generateText(
            Map.of("userName", userName)
    );

In modern languages with multi-line strings, it’s often easier to keep prompts in the codebase. Externalizing them can sacrifice type safety and lead to complexity and maintenance challenges.

Was this page helpful?

Share