Skip to content

Commit b4c5b83

Browse files
authored
Python: Fix Handlebars messages helper ignoring its argument (#14537)
### Motivation and Context The Handlebars `messages` helper ignores its argument. `{{messages my_history}}` always reads `chat_history` from the context, so it raises `KeyError` when that variable is missing and renders the wrong history when both exist. The Jinja2 `messages(history)` helper uses its argument. Fixes #14535 ### Description `_messages` in `handlebars_system_helpers.py` now uses the first positional argument. If no argument is given it falls back to the `chat_history` context variable, so existing `{{messages chat_history}}` templates behave the same. The unused `options` parameter was removed. For a non-block helper pybars passes the first argument in that slot, which is why the argument was never visible. A bare `{{messages}}` used to raise `TypeError` and now works through the fallback. Added two tests (argument with a different variable name, and argument preferred over a `chat_history` variable). Both fail on `main`. `tests/unit/prompt_template`, `tests/unit/kernel` and `tests/unit/functions` pass. ruff check clean on the touched files, mypy clean on the helper module. ### Contribution Checklist - [x] The code builds clean without any errors or warnings - [x] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [x] All unit tests pass, and I have added new tests where possible - [x] I didn't break anyone 😄
1 parent 05b6569 commit b4c5b83

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

‎python/semantic_kernel/prompt_template/utils/handlebars_system_helpers.py‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
logger: logging.Logger = logging.getLogger(__name__)
1111

1212

13-
def _messages(this, options, *args, **kwargs):
13+
def _messages(this, *args, **kwargs):
1414
from semantic_kernel.contents.chat_history import ChatHistory
1515

16-
if not isinstance(this.context["chat_history"], ChatHistory):
16+
# Use the argument passed to the helper, e.g. {{messages my_history}}.
17+
# Fall back to the "chat_history" variable when no argument is given.
18+
chat_history = args[0] if args else this.context.get("chat_history")
19+
if not isinstance(chat_history, ChatHistory):
1720
return ""
18-
return this.context["chat_history"].to_prompt()
21+
return chat_history.to_prompt()
1922

2023

2124
def _message_to_prompt(this, *args, **kwargs):

‎python/tests/unit/prompt_template/test_handlebars_prompt_template.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,37 @@ async def test_safe_types_are_allowed():
479479

480480
assert "42" in result
481481
assert "true" in result
482+
483+
484+
async def test_helpers_chat_history_messages_uses_argument(kernel: Kernel):
485+
template = """{{messages history}}"""
486+
target = create_handlebars_prompt_template(template, allow_dangerously_set_content=True)
487+
chat_history = ChatHistory()
488+
chat_history.add_user_message("User message")
489+
rendered = await target.render(kernel, KernelArguments(history=chat_history))
490+
assert (
491+
rendered.strip() == """<chat_history><message role="user"><text>User message</text></message></chat_history>"""
492+
)
493+
494+
495+
async def test_helpers_chat_history_messages_prefers_argument_over_chat_history_variable(kernel: Kernel):
496+
template = """{{messages other}}"""
497+
target = create_handlebars_prompt_template(template, allow_dangerously_set_content=True)
498+
wrong = ChatHistory()
499+
wrong.add_user_message("WRONG")
500+
right = ChatHistory()
501+
right.add_user_message("RIGHT")
502+
rendered = await target.render(kernel, KernelArguments(chat_history=wrong, other=right))
503+
assert "RIGHT" in rendered
504+
assert "WRONG" not in rendered
505+
506+
507+
async def test_helpers_chat_history_messages_without_argument_uses_chat_history_variable(kernel: Kernel):
508+
template = """{{messages}}"""
509+
target = create_handlebars_prompt_template(template, allow_dangerously_set_content=True)
510+
chat_history = ChatHistory()
511+
chat_history.add_user_message("User message")
512+
rendered = await target.render(kernel, KernelArguments(chat_history=chat_history))
513+
assert (
514+
rendered.strip() == """<chat_history><message role="user"><text>User message</text></message></chat_history>"""
515+
)

0 commit comments

Comments
 (0)