langchain/tests/unit_tests/prompts/test_prompt.py
Mohammad Mohtashim 7d92e9407b
Jinja2 validation changed to issue warnings rather than issuing exceptions. (#7161)
- Description: If their are missing or extra variables when validating
Jinja 2 template then a warning is issued rather than raising an
exception. This allows for better flexibility for the developer as
described in #7044. Also changed the relevant test so pytest is checking
for raised warnings rather than exceptions.
  - Issue: #7044 
  - Tag maintainer: @hwchase17, @baskaryan

---------

Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
2023-07-05 14:04:29 -04:00

245 lines
7.6 KiB
Python

"""Test functionality related to prompts."""
import pytest
from langchain.prompts.prompt import PromptTemplate
def test_prompt_valid() -> None:
"""Test prompts can be constructed."""
template = "This is a {foo} test."
input_variables = ["foo"]
prompt = PromptTemplate(input_variables=input_variables, template=template)
assert prompt.template == template
assert prompt.input_variables == input_variables
def test_prompt_from_template() -> None:
"""Test prompts can be constructed from a template."""
# Single input variable.
template = "This is a {foo} test."
prompt = PromptTemplate.from_template(template)
expected_prompt = PromptTemplate(template=template, input_variables=["foo"])
assert prompt == expected_prompt
# Multiple input variables.
template = "This {bar} is a {foo} test."
prompt = PromptTemplate.from_template(template)
expected_prompt = PromptTemplate(template=template, input_variables=["bar", "foo"])
assert prompt == expected_prompt
# Multiple input variables with repeats.
template = "This {bar} is a {foo} test {foo}."
prompt = PromptTemplate.from_template(template)
expected_prompt = PromptTemplate(template=template, input_variables=["bar", "foo"])
assert prompt == expected_prompt
def test_prompt_missing_input_variables() -> None:
"""Test error is raised when input variables are not provided."""
template = "This is a {foo} test."
input_variables: list = []
with pytest.raises(ValueError):
PromptTemplate(input_variables=input_variables, template=template)
def test_prompt_extra_input_variables() -> None:
"""Test error is raised when there are too many input variables."""
template = "This is a {foo} test."
input_variables = ["foo", "bar"]
with pytest.raises(ValueError):
PromptTemplate(input_variables=input_variables, template=template)
def test_prompt_wrong_input_variables() -> None:
"""Test error is raised when name of input variable is wrong."""
template = "This is a {foo} test."
input_variables = ["bar"]
with pytest.raises(ValueError):
PromptTemplate(input_variables=input_variables, template=template)
def test_prompt_from_examples_valid() -> None:
"""Test prompt can be successfully constructed from examples."""
template = """Test Prompt:
Question: who are you?
Answer: foo
Question: what are you?
Answer: bar
Question: {question}
Answer:"""
input_variables = ["question"]
example_separator = "\n\n"
prefix = """Test Prompt:"""
suffix = """Question: {question}\nAnswer:"""
examples = [
"""Question: who are you?\nAnswer: foo""",
"""Question: what are you?\nAnswer: bar""",
]
prompt_from_examples = PromptTemplate.from_examples(
examples,
suffix,
input_variables,
example_separator=example_separator,
prefix=prefix,
)
prompt_from_template = PromptTemplate(
input_variables=input_variables, template=template
)
assert prompt_from_examples.template == prompt_from_template.template
assert prompt_from_examples.input_variables == prompt_from_template.input_variables
def test_prompt_invalid_template_format() -> None:
"""Test initializing a prompt with invalid template format."""
template = "This is a {foo} test."
input_variables = ["foo"]
with pytest.raises(ValueError):
PromptTemplate(
input_variables=input_variables, template=template, template_format="bar"
)
def test_prompt_from_file() -> None:
"""Test prompt can be successfully constructed from a file."""
template_file = "tests/unit_tests/data/prompt_file.txt"
input_variables = ["question"]
prompt = PromptTemplate.from_file(template_file, input_variables)
assert prompt.template == "Question: {question}\nAnswer:"
def test_partial_init_string() -> None:
"""Test prompt can be initialized with partial variables."""
template = "This is a {foo} test."
prompt = PromptTemplate(
input_variables=[], template=template, partial_variables={"foo": 1}
)
assert prompt.template == template
assert prompt.input_variables == []
result = prompt.format()
assert result == "This is a 1 test."
def test_partial_init_func() -> None:
"""Test prompt can be initialized with partial variables."""
template = "This is a {foo} test."
prompt = PromptTemplate(
input_variables=[], template=template, partial_variables={"foo": lambda: 2}
)
assert prompt.template == template
assert prompt.input_variables == []
result = prompt.format()
assert result == "This is a 2 test."
def test_partial() -> None:
"""Test prompt can be partialed."""
template = "This is a {foo} test."
prompt = PromptTemplate(input_variables=["foo"], template=template)
assert prompt.template == template
assert prompt.input_variables == ["foo"]
new_prompt = prompt.partial(foo="3")
new_result = new_prompt.format()
assert new_result == "This is a 3 test."
result = prompt.format(foo="foo")
assert result == "This is a foo test."
def test_prompt_from_jinja2_template() -> None:
"""Test prompts can be constructed from a jinja2 template."""
# Empty input variable.
template = """Hello there
There is no variable here {
Will it get confused{ }?
"""
prompt = PromptTemplate.from_template(template, template_format="jinja2")
expected_prompt = PromptTemplate(
template=template, input_variables=[], template_format="jinja2"
)
assert prompt == expected_prompt
# Multiple input variables.
template = """\
Hello world
Your variable: {{ foo }}
{# This will not get rendered #}
{% if bar %}
You just set bar boolean variable to true
{% endif %}
{% for i in foo_list %}
{{ i }}
{% endfor %}
"""
prompt = PromptTemplate.from_template(template, template_format="jinja2")
expected_prompt = PromptTemplate(
template=template,
input_variables=["bar", "foo", "foo_list"],
template_format="jinja2",
)
assert prompt == expected_prompt
# Multiple input variables with repeats.
template = """\
Hello world
Your variable: {{ foo }}
{# This will not get rendered #}
{% if bar %}
You just set bar boolean variable to true
{% endif %}
{% for i in foo_list %}
{{ i }}
{% endfor %}
{% if bar %}
Your variable again: {{ foo }}
{% endif %}
"""
prompt = PromptTemplate.from_template(template, template_format="jinja2")
expected_prompt = PromptTemplate(
template=template,
input_variables=["bar", "foo", "foo_list"],
template_format="jinja2",
)
assert prompt == expected_prompt
def test_prompt_jinja2_missing_input_variables() -> None:
"""Test error is raised when input variables are not provided."""
template = "This is a {{ foo }} test."
input_variables: list = []
with pytest.warns(UserWarning):
PromptTemplate(
input_variables=input_variables, template=template, template_format="jinja2"
)
def test_prompt_jinja2_extra_input_variables() -> None:
"""Test error is raised when there are too many input variables."""
template = "This is a {{ foo }} test."
input_variables = ["foo", "bar"]
with pytest.warns(UserWarning):
PromptTemplate(
input_variables=input_variables, template=template, template_format="jinja2"
)
def test_prompt_jinja2_wrong_input_variables() -> None:
"""Test error is raised when name of input variable is wrong."""
template = "This is a {{ foo }} test."
input_variables = ["bar"]
with pytest.warns(UserWarning):
PromptTemplate(
input_variables=input_variables, template=template, template_format="jinja2"
)