HaystackHaystack 3.1 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
19 small wins to finish your pathNext lesson

Prompt templates with ChatPromptBuilder

ChatPromptBuilder fills a Jinja template with variables, such as retrieved documents and the question, and outputs chat messages for a generator.

Example
from haystack.components.builders import ChatPromptBuilder
from haystack.dataclasses import ChatMessage

template = [ChatMessage.from_user(
    "Answer the question using only these documents.\n"
    "{% for document in documents %}- {{ document.content }}\n{% endfor %}"
    "Question: {{ question }}"
)]
prompt_builder = ChatPromptBuilder(template=template, required_variables=["question", "documents"])
Example
documents = [Document(content="Refunds are paid within five working days.")]
prompt = prompt_builder.run(documents=documents, question="How long do refunds take?")["prompt"]
print(prompt[0].role.value)
print(prompt[0].text)

{% for %} loops over the documents and {{ }} prints a value, standard Jinja. The template's variables become the builder's inputs. The output, prompt, is a list of ChatMessage, which is what chat generators take.

Example
prompt_builder.run(question="How long do refunds take?")

required_variables makes a missing input an error. Without it, a missing variable renders as empty, and a model would answer a question with no documents and no warning.

System messages and roles

Example
template = [
    ChatMessage.from_system("You answer questions for an online shop. If the documents do not say, say you do not know."),
    ChatMessage.from_user("Question: {{ question }}"),
]
for message in ChatPromptBuilder(template=template, required_variables=["question"]).run(question="Hi?")["prompt"]:
    print(message.role.value, "|", message.text)

A template can hold several messages with different roles. PromptBuilder, without Chat, builds a single string for generators that take plain text.

Try it yourself
  • Add {{ document.meta.topic }} to each document line.
  • Pass template= to run to use a different template for one call.
  • Use Jinja's {% if documents %} to write a different prompt when nothing was retrieved.

Every expert started right here.