diff --git a/libs/core/langchain_core/messages/base.py b/libs/core/langchain_core/messages/base.py index 605f879e5b8..b1fb57a5cdd 100644 --- a/libs/core/langchain_core/messages/base.py +++ b/libs/core/langchain_core/messages/base.py @@ -139,7 +139,7 @@ def merge_content( else: # If the last element of the first content is a string # Add the second content to the last element - if isinstance(merged[-1], str): + if merged and isinstance(merged[-1], str): merged[-1] += content # If second content is an empty string, treat as a no-op elif content == "": diff --git a/libs/core/tests/unit_tests/test_messages.py b/libs/core/tests/unit_tests/test_messages.py index 3e0d9e31b29..b62803a3b40 100644 --- a/libs/core/tests/unit_tests/test_messages.py +++ b/libs/core/tests/unit_tests/test_messages.py @@ -1,5 +1,5 @@ import unittest -from typing import List, Type +from typing import List, Type, Union import pytest @@ -18,6 +18,7 @@ from langchain_core.messages import ( ToolMessage, convert_to_messages, get_buffer_string, + merge_content, message_chunk_to_message, message_to_dict, messages_from_dict, @@ -950,3 +951,27 @@ def test_tool_message_str() -> None: expected = "content='foo' tool_call_id='1' artifact={'bar': {'baz': 123}}" actual = str(message) assert expected == actual + + +@pytest.mark.parametrize( + ["first", "others", "expected"], + [ + ("", [""], ""), + ("", [[]], [""]), + ([], [""], []), + ([], [[]], []), + ("foo", [""], "foo"), + ("foo", [[]], ["foo"]), + (["foo"], [""], ["foo"]), + (["foo"], [[]], ["foo"]), + ("foo", ["bar"], "foobar"), + ("foo", [["bar"]], ["foo", "bar"]), + (["foo"], ["bar"], ["foobar"]), + (["foo"], [["bar"]], ["foo", "bar"]), + ], +) +def test_merge_content( + first: Union[list, str], others: list, expected: Union[list, str] +) -> None: + actual = merge_content(first, *others) + assert actual == expected