promptbuilder.mdx
1 --- 2 title: "PromptBuilder" 3 id: promptbuilder 4 slug: "/promptbuilder" 5 description: "Use this component in pipelines before a Generator to render a prompt template and fill in variable values." 6 --- 7 8 # PromptBuilder 9 10 Use this component in pipelines before a Generator to render a prompt template and fill in variable values. 11 12 <div className="key-value-table"> 13 14 | | | 15 | --- | --- | 16 | **Most common position in a pipeline** | In a querying pipeline, before a [Generator](../generators.mdx) | 17 | **Mandatory init variables** | `template`: A prompt template string that uses Jinja2 syntax | 18 | **Mandatory run variables** | `**kwargs`: Any strings that should be used to render the prompt template. See [Variables](#variables) section for more details. | 19 | **Output variables** | `prompt`: A string that represents the rendered prompt template | 20 | **API reference** | [Builders](/reference/builders-api) | 21 | **GitHub link** | https://github.com/deepset-ai/haystack/blob/main/haystack/components/builders/prompt_builder.py | 22 23 </div> 24 25 ## Overview 26 27 `PromptBuilder` is initialized with a prompt template and renders it by filling in parameters passed through keyword arguments, `kwargs`. With `kwargs`, you can pass a variable number of keyword arguments so that any variable used in the prompt template can be specified with the desired value. Values for all variables appearing in the prompt template need to be provided through the `kwargs`. 28 29 The template that is provided to the `PromptBuilder` during initialization needs to conform to the [Jinja2](https://palletsprojects.com/p/jinja/) template language. 30 31 ### Variables 32 33 The template variables found in the init template are used as input types for the component. If there are no `required_variables` set, all variables are considered optional by default. In this case, any missing variables are replaced with empty strings, which can lead to unintended behavior, especially in complex pipelines. 34 35 Use `required_variables` and `variables` to specify the input types and required variables: 36 37 - `required_variables` 38 - Defines which template variables must be provided when the component runs. 39 - If any required variable is missing, the component raises an error and halts execution. 40 - You can: 41 - Pass a list of required variable names (such as `["query"]`), or 42 - Use `"*"` to mark all variables in the template as required. 43 44 - `variables` 45 - Lists all variables that can appear in the template, whether required or optional. 46 - Optional variables that aren't provided are replaced with an empty string in the rendered prompt. 47 - This allows partial prompts to be constructed without errors, unless a variable is marked as required. 48 49 ```python 50 from haystack.components.builders import PromptBuilder 51 52 ## All variables optional (default to empty string) 53 builder = PromptBuilder( 54 template="Hello {{name}}! {{greeting}}", 55 required_variables=[], # or omit this parameter entirely 56 ) 57 58 ## Some variables required 59 builder = PromptBuilder( 60 template="Hello {{name}}! {{greeting}}", 61 required_variables=["name"], # 'greeting' remains optional 62 ) 63 ``` 64 65 The component only waits for the required inputs before running. 66 67 ### Jinja2 Time Extension 68 69 `PromptBuilder` supports the Jinja2 TimeExtension, which allows you to work with datetime formats. 70 71 The Time Extension provides two main features: 72 73 1. A `now` tag that gives you access to the current time, 74 2. Date/time formatting capabilities through Python's datetime module. 75 76 To use the Jinja2 TimeExtension, you need to install a dependency with: 77 78 ```shell 79 pip install arrow>=1.3.0 80 ``` 81 82 #### The `now` Tag 83 84 The `now` tag creates a datetime object representing the current time, which you can then store in a variable: 85 86 ```jinja2 87 {% now 'utc' as current_time %} 88 The current UTC time is: {{ current_time }} 89 ``` 90 91 You can specify different timezones: 92 93 ```jinja2 94 {% now 'America/New_York' as ny_time %} 95 The time in New York is: {{ ny_time }} 96 ``` 97 98 If you don't specify a timezone, your system's local timezone will be used: 99 100 ```jinja2 101 {% now as local_time %} 102 Local time: {{ local_time }} 103 ``` 104 105 #### Date Formatting 106 107 You can format the datetime objects using Python's `strftime` syntax: 108 109 ```jinja2 110 {% now as current_time %} 111 Formatted date: {{ current_time.strftime('%Y-%m-%d %H:%M:%S') }} 112 ``` 113 114 The common format codes are: 115 116 - `%Y`: 4-digit year (for example, 2025) 117 - `%m`: Month as a zero-padded number (01-12) 118 - `%d`: Day as a zero-padded number (01-31) 119 - `%H`: Hour (24-hour clock) as a zero-padded number (00-23) 120 - `%M`: Minute as a zero-padded number (00-59) 121 - `%S`: Second as a zero-padded number (00-59) 122 123 #### Example 124 125 ```python 126 from haystack.components.builders import PromptBuilder 127 128 ## Define template using Jinja-style formatting 129 template = """ 130 Current date is: {% now 'UTC' %} 131 Thank you for providing the date 132 Yesterday was: {% now 'UTC' - 'days=1' %} 133 """ 134 135 builder = PromptBuilder(template=template) 136 137 result = builder.run()["prompt"] 138 ``` 139 140 ## Usage 141 142 ### On its own 143 144 Below is an example of using the `PromptBuilder` to render a prompt template and fill it with `target_language` and `snippet`. The PromptBuilder returns a prompt with the string `Translate the following context to spanish. Context: I can't speak spanish.; Translation:`. 145 146 ```python 147 from haystack.components.builders import PromptBuilder 148 149 template = "Translate the following context to {{ target_language }}. Context: {{ snippet }}; Translation:" 150 builder = PromptBuilder(template=template) 151 builder.run(target_language="spanish", snippet="I can't speak spanish.") 152 ``` 153 154 ### In a pipeline 155 156 Below is an example of a RAG pipeline where we use a `PromptBuilder` to render a custom prompt template and fill it with the contents of retrieved documents and a query. The rendered prompt is then sent to a Generator. 157 158 ```python 159 from haystack import Pipeline, Document 160 from haystack.utils import Secret 161 from haystack.components.generators import OpenAIGenerator 162 from haystack.components.builders.prompt_builder import PromptBuilder 163 164 ## in a real world use case documents could come from a retriever, web, or any other source 165 documents = [ 166 Document(content="Joe lives in Berlin"), 167 Document(content="Joe is a software engineer"), 168 ] 169 prompt_template = """ 170 Given these documents, answer the question.\nDocuments: 171 {% for doc in documents %} 172 {{ doc.content }} 173 {% endfor %} 174 175 \nQuestion: {{query}} 176 \nAnswer: 177 """ 178 p = Pipeline() 179 p.add_component(instance=PromptBuilder(template=prompt_template), name="prompt_builder") 180 p.add_component( 181 instance=OpenAIGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")), 182 name="llm", 183 ) 184 p.connect("prompt_builder", "llm") 185 186 question = "Where does Joe live?" 187 result = p.run({"prompt_builder": {"documents": documents, "query": question}}) 188 print(result) 189 ``` 190 191 #### Changing the template at runtime (Prompt Engineering) 192 193 `PromptBuilder` allows you to switch the prompt template of an existing pipeline. The example below builds on top of the existing pipeline in the previous section. We are invoking the existing pipeline with a new prompt template: 194 195 ```python 196 documents = [ 197 Document(content="Joe lives in Berlin", meta={"name": "doc1"}), 198 Document(content="Joe is a software engineer", meta={"name": "doc1"}), 199 ] 200 new_template = """ 201 You are a helpful assistant. 202 Given these documents, answer the question. 203 Documents: 204 {% for doc in documents %} 205 Document {{ loop.index }}: 206 Document name: {{ doc.meta['name'] }} 207 {{ doc.content }} 208 {% endfor %} 209 210 Question: {{ query }} 211 Answer: 212 """ 213 p.run( 214 { 215 "prompt_builder": { 216 "documents": documents, 217 "query": question, 218 "template": new_template, 219 }, 220 }, 221 ) 222 ``` 223 224 If you want to use different variables during prompt engineering than in the default template, you can do so by setting `PromptBuilder`'s variables init parameter accordingly. 225 226 #### Overwriting variables at runtime 227 228 In case you want to overwrite the values of variables, you can use `template_variables` during runtime, as shown below: 229 230 ```python 231 language_template = """ 232 You are a helpful assistant. 233 Given these documents, answer the question. 234 Documents: 235 {% for doc in documents %} 236 Document {{ loop.index }}: 237 Document name: {{ doc.meta['name'] }} 238 {{ doc.content }} 239 {% endfor %} 240 241 Question: {{ query }} 242 Please provide your answer in {{ answer_language | default('English') }} 243 Answer: 244 """ 245 p.run( 246 { 247 "prompt_builder": { 248 "documents": documents, 249 "query": question, 250 "template": language_template, 251 "template_variables": {"answer_language": "German"}, 252 }, 253 }, 254 ) 255 ``` 256 257 Note that `language_template` introduces `answer_language` variable which is not bound to any pipeline variable. If not set otherwise, it would use its default value, "English". In this example, we overwrite its value to "German". 258 The `template_variables` allows you to overwrite pipeline variables (such as documents) as well. 259 260 ## Additional References 261 262 🧑🍳 Cookbooks: 263 264 - [Advanced Prompt Customization for Anthropic](https://haystack.deepset.ai/cookbook/prompt_customization_for_anthropic) 265 - [Prompt Optimization with DSPy](https://haystack.deepset.ai/cookbook/prompt_optimization_with_dspy)