Skip to content

Commit 363ac50

Browse files
authored
feat: Add warning to ChatPromptBuilder and PromptBuilder if they have variables, but required_variables is not set (#9027)
* Add warning to ChatPromptBuilder and PromptBuilder if they have variables, but required variables is not set. * Add reno
1 parent 4edefe3 commit 363ac50

File tree

5 files changed

+52
-11
lines changed

5 files changed

+52
-11
lines changed

haystack/components/builders/chat_prompt_builder.py

+9
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ def __init__(
136136
variables += list(template_variables)
137137
self.variables = variables
138138

139+
if len(self.variables) > 0 and required_variables is None:
140+
logger.warning(
141+
"ChatPromptBuilder has {length} prompt variables, but `required_variables` is not set. "
142+
"By default, all prompt variables are treated as optional, which may lead to unintended behavior in "
143+
"multi-branch pipelines. To avoid unexpected execution, ensure that variables intended to be required "
144+
"are explicitly set in `required_variables`.",
145+
length=len(self.variables),
146+
)
147+
139148
# setup inputs
140149
for var in self.variables:
141150
if self.required_variables == "*" or var in self.required_variables:

haystack/components/builders/prompt_builder.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
from jinja2 import meta
88
from jinja2.sandbox import SandboxedEnvironment
99

10-
from haystack import component, default_to_dict
10+
from haystack import component, default_to_dict, logging
1111
from haystack.utils import Jinja2TimeExtension
1212

13+
logger = logging.getLogger(__name__)
14+
1315

1416
@component
1517
class PromptBuilder:
@@ -180,6 +182,15 @@ def __init__(
180182
variables = variables or []
181183
self.variables = variables
182184

185+
if len(self.variables) > 0 and required_variables is None:
186+
logger.warning(
187+
"PromptBuilder has {length} prompt variables, but `required_variables` is not set. "
188+
"By default, all prompt variables are treated as optional, which may lead to unintended behavior in "
189+
"multi-branch pipelines. To avoid unexpected execution, ensure that variables intended to be required "
190+
"are explicitly set in `required_variables`.",
191+
length=len(self.variables),
192+
)
193+
183194
# setup inputs
184195
for var in self.variables:
185196
if self.required_variables == "*" or var in self.required_variables:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
enhancements:
3+
- |
4+
Added a warning to ChatPromptBuilder and PromptBuilder when prompt variables are present and `required_variables` is unset to help users avoid unexpected execution in multi-branch pipelines. The warning recommends users to set `required_variables`.

test/components/builders/test_chat_prompt_builder.py

+21-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import Any, Dict, List, Optional
22
from jinja2 import TemplateSyntaxError
3+
import logging
34
import pytest
45

56
from haystack.components.builders.chat_prompt_builder import ChatPromptBuilder
@@ -335,6 +336,16 @@ def test_example_in_pipeline_simple(self):
335336
}
336337
assert result == expected_dynamic
337338

339+
def test_warning_no_required_variables(self, caplog):
340+
with caplog.at_level(logging.WARNING):
341+
_ = ChatPromptBuilder(
342+
template=[
343+
ChatMessage.from_system("Write your response in this language:{{language}}"),
344+
ChatMessage.from_user("Tell me about {{location}}"),
345+
]
346+
)
347+
assert "ChatPromptBuilder has 2 prompt variables, but `required_variables` is not set. " in caplog.text
348+
338349

339350
class TestChatPromptBuilderDynamic:
340351
def test_multiple_templated_chat_messages(self):
@@ -521,13 +532,13 @@ def run(self):
521532
}
522533

523534
def test_to_dict(self):
524-
component = ChatPromptBuilder(
535+
comp = ChatPromptBuilder(
525536
template=[ChatMessage.from_user("text and {var}"), ChatMessage.from_assistant("content {required_var}")],
526537
variables=["var", "required_var"],
527538
required_variables=["required_var"],
528539
)
529540

530-
assert component.to_dict() == {
541+
assert comp.to_dict() == {
531542
"type": "haystack.components.builders.chat_prompt_builder.ChatPromptBuilder",
532543
"init_parameters": {
533544
"template": [
@@ -545,7 +556,7 @@ def test_to_dict(self):
545556
}
546557

547558
def test_from_dict(self):
548-
component = ChatPromptBuilder.from_dict(
559+
comp = ChatPromptBuilder.from_dict(
549560
data={
550561
"type": "haystack.components.builders.chat_prompt_builder.ChatPromptBuilder",
551562
"init_parameters": {
@@ -564,21 +575,21 @@ def test_from_dict(self):
564575
}
565576
)
566577

567-
assert component.template == [
578+
assert comp.template == [
568579
ChatMessage.from_user("text and {var}"),
569580
ChatMessage.from_assistant("content {required_var}"),
570581
]
571-
assert component._variables == ["var", "required_var"]
572-
assert component._required_variables == ["required_var"]
582+
assert comp._variables == ["var", "required_var"]
583+
assert comp._required_variables == ["required_var"]
573584

574585
def test_from_dict_template_none(self):
575-
component = ChatPromptBuilder.from_dict(
586+
comp = ChatPromptBuilder.from_dict(
576587
data={
577588
"type": "haystack.components.builders.chat_prompt_builder.ChatPromptBuilder",
578589
"init_parameters": {"template": None},
579590
}
580591
)
581592

582-
assert component.template is None
583-
assert component._variables is None
584-
assert component._required_variables is None
593+
assert comp.template is None
594+
assert comp._variables is None
595+
assert comp._required_variables is None

test/components/builders/test_prompt_builder.py

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from unittest.mock import patch
66

77
import arrow
8+
import logging
89
import pytest
910
from jinja2 import TemplateSyntaxError
1011

@@ -330,3 +331,8 @@ def test_invalid_offset(self) -> None:
330331
# Expect ValueError for invalid offset
331332
with pytest.raises(ValueError, match="Invalid offset or operator"):
332333
builder.run()
334+
335+
def test_warning_no_required_variables(self, caplog):
336+
with caplog.at_level(logging.WARNING):
337+
_ = PromptBuilder(template="This is a {{ variable }}")
338+
assert "but `required_variables` is not set." in caplog.text

0 commit comments

Comments
 (0)