core: allow passing message dicts into ChatPromptTemplate (#29363)

Co-authored-by: Erick Friis <erick@langchain.dev>
This commit is contained in:
Isaac Francisco 2025-02-05 09:45:52 -08:00 committed by GitHub
parent 69595b0914
commit 91ffd7caad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 1 deletions

View File

@ -828,6 +828,7 @@ MessageLikeRepresentation = Union[
Union[str, list[dict], list[object]],
],
str,
dict,
]
@ -1461,7 +1462,15 @@ def _convert_to_message(
_message = _create_template_from_message_type(
"human", message, template_format=template_format
)
elif isinstance(message, tuple):
elif isinstance(message, (tuple, dict)):
if isinstance(message, dict):
if set(message.keys()) != {"content", "role"}:
msg = (
"Expected dict to have exact keys 'role' and 'content'."
f" Got: {message}"
)
raise ValueError(msg)
message = (message["role"], message["content"])
if len(message) != 2:
msg = f"Expected 2-tuple of (role, template), got {message}"
raise ValueError(msg)

View File

@ -824,6 +824,41 @@ def test_chat_prompt_message_placeholder_tuple() -> None:
assert optional_prompt.format_messages() == []
def test_chat_prompt_message_placeholder_dict() -> None:
prompt = ChatPromptTemplate([{"role": "placeholder", "content": "{convo}"}])
assert prompt.format_messages(convo=[("user", "foo")]) == [
HumanMessage(content="foo")
]
assert prompt.format_messages() == []
# Is optional = True
optional_prompt = ChatPromptTemplate(
[{"role": "placeholder", "content": ["{convo}", False]}]
)
assert optional_prompt.format_messages(convo=[("user", "foo")]) == [
HumanMessage(content="foo")
]
with pytest.raises(KeyError):
assert optional_prompt.format_messages() == []
def test_chat_prompt_message_dict() -> None:
prompt = ChatPromptTemplate(
[{"role": "system", "content": "foo"}, {"role": "user", "content": "bar"}]
)
assert prompt.format_messages() == [
SystemMessage(content="foo"),
HumanMessage(content="bar"),
]
with pytest.raises(ValueError):
ChatPromptTemplate([{"role": "system", "content": False}])
with pytest.raises(ValueError):
ChatPromptTemplate([{"role": "foo", "content": "foo"}])
async def test_messages_prompt_accepts_list() -> None:
prompt = ChatPromptTemplate([MessagesPlaceholder("history")])
value = prompt.invoke([("user", "Hi there")]) # type: ignore