|
|
@ -1,4 +1,4 @@
|
|
|
|
from typing import List, Sequence, Union
|
|
|
|
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
|
|
|
|
|
|
|
|
|
|
|
from langchain_core.messages.ai import AIMessage, AIMessageChunk
|
|
|
|
from langchain_core.messages.ai import AIMessage, AIMessageChunk
|
|
|
|
from langchain_core.messages.base import (
|
|
|
|
from langchain_core.messages.base import (
|
|
|
@ -117,6 +117,110 @@ def message_chunk_to_message(chunk: BaseMessageChunk) -> BaseMessage:
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MessageLikeRepresentation = Union[BaseMessage, Tuple[str, str], str, Dict[str, Any]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _create_message_from_message_type(
|
|
|
|
|
|
|
|
message_type: str,
|
|
|
|
|
|
|
|
content: str,
|
|
|
|
|
|
|
|
name: Optional[str] = None,
|
|
|
|
|
|
|
|
tool_call_id: Optional[str] = None,
|
|
|
|
|
|
|
|
**additional_kwargs: Any,
|
|
|
|
|
|
|
|
) -> BaseMessage:
|
|
|
|
|
|
|
|
"""Create a message from a message type and content string.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
message_type: str the type of the message (e.g., "human", "ai", etc.)
|
|
|
|
|
|
|
|
content: str the content string.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
a message of the appropriate type.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
kwargs: Dict[str, Any] = {}
|
|
|
|
|
|
|
|
if name is not None:
|
|
|
|
|
|
|
|
kwargs["name"] = name
|
|
|
|
|
|
|
|
if tool_call_id is not None:
|
|
|
|
|
|
|
|
kwargs["tool_call_id"] = tool_call_id
|
|
|
|
|
|
|
|
if additional_kwargs:
|
|
|
|
|
|
|
|
kwargs["additional_kwargs"] = additional_kwargs # type: ignore[assignment]
|
|
|
|
|
|
|
|
if message_type in ("human", "user"):
|
|
|
|
|
|
|
|
message: BaseMessage = HumanMessage(content=content, **kwargs)
|
|
|
|
|
|
|
|
elif message_type in ("ai", "assistant"):
|
|
|
|
|
|
|
|
message = AIMessage(content=content, **kwargs)
|
|
|
|
|
|
|
|
elif message_type == "system":
|
|
|
|
|
|
|
|
message = SystemMessage(content=content, **kwargs)
|
|
|
|
|
|
|
|
elif message_type == "function":
|
|
|
|
|
|
|
|
message = FunctionMessage(content=content, **kwargs)
|
|
|
|
|
|
|
|
elif message_type == "tool":
|
|
|
|
|
|
|
|
message = ToolMessage(content=content, **kwargs)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
raise ValueError(
|
|
|
|
|
|
|
|
f"Unexpected message type: {message_type}. Use one of 'human',"
|
|
|
|
|
|
|
|
f" 'user', 'ai', 'assistant', or 'system'."
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
return message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _convert_to_message(
|
|
|
|
|
|
|
|
message: MessageLikeRepresentation,
|
|
|
|
|
|
|
|
) -> BaseMessage:
|
|
|
|
|
|
|
|
"""Instantiate a message from a variety of message formats.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The message format can be one of the following:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- BaseMessagePromptTemplate
|
|
|
|
|
|
|
|
- BaseMessage
|
|
|
|
|
|
|
|
- 2-tuple of (role string, template); e.g., ("human", "{user_input}")
|
|
|
|
|
|
|
|
- dict: a message dict with role and content keys
|
|
|
|
|
|
|
|
- string: shorthand for ("human", template); e.g., "{user_input}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
message: a representation of a message in one of the supported formats
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
an instance of a message or a message template
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
if isinstance(message, BaseMessage):
|
|
|
|
|
|
|
|
_message = message
|
|
|
|
|
|
|
|
elif isinstance(message, str):
|
|
|
|
|
|
|
|
_message = _create_message_from_message_type("human", message)
|
|
|
|
|
|
|
|
elif isinstance(message, tuple):
|
|
|
|
|
|
|
|
if len(message) != 2:
|
|
|
|
|
|
|
|
raise ValueError(f"Expected 2-tuple of (role, template), got {message}")
|
|
|
|
|
|
|
|
message_type_str, template = message
|
|
|
|
|
|
|
|
_message = _create_message_from_message_type(message_type_str, template)
|
|
|
|
|
|
|
|
elif isinstance(message, dict):
|
|
|
|
|
|
|
|
msg_kwargs = message.copy()
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
msg_type = msg_kwargs.pop("role")
|
|
|
|
|
|
|
|
msg_content = msg_kwargs.pop("content")
|
|
|
|
|
|
|
|
except KeyError:
|
|
|
|
|
|
|
|
raise ValueError(
|
|
|
|
|
|
|
|
f"Message dict must contain 'role' and 'content' keys, got {message}"
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
_message = _create_message_from_message_type(
|
|
|
|
|
|
|
|
msg_type, msg_content, **msg_kwargs
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
raise NotImplementedError(f"Unsupported message type: {type(message)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return _message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def convert_to_messages(
|
|
|
|
|
|
|
|
messages: Sequence[MessageLikeRepresentation],
|
|
|
|
|
|
|
|
) -> List[BaseMessage]:
|
|
|
|
|
|
|
|
"""Convert a sequence of messages to a list of messages.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
messages: Sequence of messages to convert.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
List of messages (BaseMessages).
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
return [_convert_to_message(m) for m in messages]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__all__ = [
|
|
|
|
__all__ = [
|
|
|
|
"AIMessage",
|
|
|
|
"AIMessage",
|
|
|
|
"AIMessageChunk",
|
|
|
|
"AIMessageChunk",
|
|
|
@ -133,6 +237,7 @@ __all__ = [
|
|
|
|
"SystemMessageChunk",
|
|
|
|
"SystemMessageChunk",
|
|
|
|
"ToolMessage",
|
|
|
|
"ToolMessage",
|
|
|
|
"ToolMessageChunk",
|
|
|
|
"ToolMessageChunk",
|
|
|
|
|
|
|
|
"convert_to_messages",
|
|
|
|
"get_buffer_string",
|
|
|
|
"get_buffer_string",
|
|
|
|
"message_chunk_to_message",
|
|
|
|
"message_chunk_to_message",
|
|
|
|
"messages_from_dict",
|
|
|
|
"messages_from_dict",
|
|
|
|