diff --git a/libs/core/langchain_core/messages/utils.py b/libs/core/langchain_core/messages/utils.py index 9bf617af17d..0ea03e40d00 100644 --- a/libs/core/langchain_core/messages/utils.py +++ b/libs/core/langchain_core/messages/utils.py @@ -1210,13 +1210,14 @@ def _first_max_tokens( ] = None, ) -> list[BaseMessage]: messages = list(messages) + if not messages: + return messages idx = 0 for i in range(len(messages)): if token_counter(messages[:-i] if i else messages) <= max_tokens: idx = len(messages) - i break - - if idx < len(messages) - 1 and partial_strategy: + if partial_strategy and (idx < len(messages) - 1 or idx == 0): included_partial = False if isinstance(messages[idx].content, list): excluded = messages[idx].model_copy(deep=True) diff --git a/libs/core/tests/unit_tests/messages/test_utils.py b/libs/core/tests/unit_tests/messages/test_utils.py index 9cd9543dc7c..ff251e36320 100644 --- a/libs/core/tests/unit_tests/messages/test_utils.py +++ b/libs/core/tests/unit_tests/messages/test_utils.py @@ -301,6 +301,42 @@ def test_trim_messages_last_40_include_system_allow_partial_start_on_human() -> assert _MESSAGES_TO_TRIM == _MESSAGES_TO_TRIM_COPY +def test_trim_messages_allow_partial_one_message() -> None: + expected = [ + HumanMessage("Th", id="third"), + ] + + actual = trim_messages( + [HumanMessage("This is a funky text.", id="third")], + max_tokens=2, + token_counter=lambda messages: sum(len(m.content) for m in messages), + text_splitter=lambda x: list(x), + strategy="first", + allow_partial=True, + ) + + assert actual == expected + assert _MESSAGES_TO_TRIM == _MESSAGES_TO_TRIM_COPY + + +def test_trim_messages_last_allow_partial_one_message() -> None: + expected = [ + HumanMessage("t.", id="third"), + ] + + actual = trim_messages( + [HumanMessage("This is a funky text.", id="third")], + max_tokens=2, + token_counter=lambda messages: sum(len(m.content) for m in messages), + text_splitter=lambda x: list(x), + strategy="last", + allow_partial=True, + ) + + assert actual == expected + assert _MESSAGES_TO_TRIM == _MESSAGES_TO_TRIM_COPY + + def test_trim_messages_allow_partial_text_splitter() -> None: expected = [ HumanMessage("a 4 token text.", id="third"),