This commit is contained in:
Bagatur 2024-08-28 17:01:23 -07:00
parent bd48abe54a
commit ca5773dc0a
4 changed files with 32 additions and 8 deletions

View File

@ -44,6 +44,7 @@ from langchain_core.messages.utils import (
_message_from_dict, _message_from_dict,
convert_to_messages, convert_to_messages,
filter_messages, filter_messages,
format_messages_as,
get_buffer_string, get_buffer_string,
merge_message_runs, merge_message_runs,
message_chunk_to_message, message_chunk_to_message,
@ -83,4 +84,5 @@ __all__ = [
"filter_messages", "filter_messages",
"merge_message_runs", "merge_message_runs",
"trim_messages", "trim_messages",
"format_messages_as",
] ]

View File

@ -940,17 +940,38 @@ def format_messages_as(
.. code-block:: python .. code-block:: python
from langchain_core.messages import format_messages_as from langchain_core.messages import (
format_messages_as,
AIMessage,
HumanMessage,
SystemMessage,
ToolMessage,
)
messages = [ messages = [
SystemMessage, SystemMessage([{"type": "text", "text": "foo"}]),
{}, {"role": "user", "content": [{"type": "text", "text": "whats in this"}, {"type": "image_url", "image_url": {"url": "data:image/png;base64,'/9j/4AAQSk'"}}]},
(), AIMessage("", tool_calls=[{"name": "analyze", "args": {"baz": "buz"}, "id": "1", "type": "tool_call"}]),
AIMessage(), ToolMessage("foobar", tool_call_id="1", name="bar"),
ToolMessage(), {"role": "assistant", "content": "thats nice"},
] ]
oai_strings = format_messages_as(messages, format="openai", text="string") oai_strings = format_messages_as(messages, format="openai", text="string")
# -> [
# SystemMessage(content='foo'),
# HumanMessage(content=[{'type': 'text', 'text': 'whats in this'}, {'type': 'image_url', 'image_url': {'url': "data:image/png;base64,'/9j/4AAQSk'"}}]),
# AIMessage(content='', tool_calls=[{'name': 'analyze', 'args': {'baz': 'buz'}, 'id': '1', 'type': 'tool_call'}]),
# ToolMessage(content='foobar', name='bar', tool_call_id='1'),
# AIMessage(content='thats nice')
# ]
anthropic_blocks = format_messages_as(messages, format="anthropic", text="block") anthropic_blocks = format_messages_as(messages, format="anthropic", text="block")
# -> [
# SystemMessage(content=[{'type': 'text', 'text': 'foo'}]),
# HumanMessage(content=[{'type': 'text', 'text': 'whats in this'}, {'type': 'image', 'source': {'type': 'base64', 'media_type': 'image/png', 'data': "'/9j/4AAQSk'"}}]),
# AIMessage(content=[{'type': 'tool_use', 'input': {'baz': 'buz'}, 'id': '1', 'name': 'analyze'}], tool_calls=[{'name': 'analyze', 'args': {'baz': 'buz'}, 'id': '1', 'type': 'tool_call'}]),
# HumanMessage(content=[{'type': 'tool_result', 'content': 'foobar', 'tool_use_id': '1', 'is_error': False}]),
# AIMessage(content=[{'type': 'text', 'text': 'thats nice'}])
# ]
.. dropdown:: Chain usage .. dropdown:: Chain usage
:open: :open:
@ -1679,7 +1700,7 @@ def _openai_image_to_anthropic(image: dict) -> Dict:
And throws an error if it's not a b64 image And throws an error if it's not a b64 image
""" """
regex = r"^data:(?P<media_type>image/.+);base64,(?P<data>.+)$" regex = r"^data:(?P<media_type>image/.+);base64,(?P<data>.+)$"
match = re.match(regex, image["image_url"]) match = re.match(regex, image["image_url"]["url"])
if match is None: if match is None:
raise ValueError( raise ValueError(
"Anthropic only supports base64-encoded images currently." "Anthropic only supports base64-encoded images currently."

View File

@ -32,6 +32,7 @@ EXPECTED_ALL = [
"filter_messages", "filter_messages",
"merge_message_runs", "merge_message_runs",
"trim_messages", "trim_messages",
"format_messages_as",
] ]

View File

@ -672,7 +672,7 @@ def test_format_messages_as_anthropic_image() -> None:
HumanMessage( HumanMessage(
content=[ content=[
{"type": "text", "text": "Here's an image:"}, {"type": "text", "text": "Here's an image:"},
{"type": "image_url", "image_url": base64_image}, {"type": "image_url", "image_url": {"url": base64_image}},
] ]
) )
] ]