diff --git a/llm/templates.py b/llm/templates.py index 1919e0484..7d0c162f4 100644 --- a/llm/templates.py +++ b/llm/templates.py @@ -76,7 +76,7 @@ def interpolate(cls, text: str | None, params: dict[str, Any]) -> str | None: # Confirm all variables in text are provided string_template = string.Template(text) vars = cls.extract_vars(string_template) - missing = [p for p in vars if p not in params] + missing = list(dict.fromkeys(p for p in vars if p not in params)) if missing: raise cls.MissingVariables( "Missing variables: {}".format(", ".join(missing)) diff --git a/tests/test_templates.py b/tests/test_templates.py index 9ef2d8888..b9cef9db0 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -21,6 +21,9 @@ ("S: $input", "system", None, {}, "S: input", "system", None), ("No vars", None, None, {}, "No vars", None, None), ("$one and $two", None, None, {}, None, None, "Missing variables: one, two"), + # A variable reused in the template is reported once, not once per use. + ("$name and $name", None, None, {}, None, None, "Missing variables: name"), + ("$a $b $a", None, None, {}, None, None, "Missing variables: a, b"), ("$one and $two", None, None, {"one": 1, "two": 2}, "1 and 2", None, None), ("$one and $two", None, {"one": 1}, {"two": 2}, "1 and 2", None, None), ("$one and $$2", None, None, {"one": 1}, "1 and $2", None, None),