Source code for langchain_core.messages.base

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union

from langchain_core.load.serializable import Serializable
from langchain_core.pydantic_v1 import Extra, Field
from langchain_core.utils import get_bolded_text
from langchain_core.utils._merge import merge_dicts
from langchain_core.utils.interactive_env import is_interactive_env

if TYPE_CHECKING:
    from langchain_core.prompts.chat import ChatPromptTemplate


[docs]class BaseMessage(Serializable): """基础抽象消息类。 消息是ChatModels的输入和输出。 """ content: Union[str, List[Union[str, Dict]]] """消息的字符串内容。""" additional_kwargs: dict = Field(default_factory=dict) """为与消息相关的附加有效负载数据保留。 例如,对于来自人工智能的消息,这可能包括工具调用。""" response_metadata: dict = Field(default_factory=dict) """响应元数据。例如:响应头、日志概率、令牌计数。""" type: str name: Optional[str] = None id: Optional[str] = None """消息的可选唯一标识符。最好由创建消息的提供程序/模型提供。""" class Config: extra = Extra.allow def __init__( self, content: Union[str, List[Union[str, Dict]]], **kwargs: Any ) -> None: """将内容作为位置参数传递。""" return super().__init__(content=content, **kwargs)
[docs] @classmethod def is_lc_serializable(cls) -> bool: """返回此类是否可序列化。""" return True
[docs] @classmethod def get_lc_namespace(cls) -> List[str]: """获取langchain对象的命名空间。""" return ["langchain", "schema", "messages"]
def __add__(self, other: Any) -> ChatPromptTemplate: from langchain_core.prompts.chat import ChatPromptTemplate prompt = ChatPromptTemplate(messages=[self]) # type: ignore[call-arg] return prompt + other
[docs] def pretty_repr(self, html: bool = False) -> str: title = get_msg_title_repr(self.type.title() + " Message", bold=html) # TODO: handle non-string content. if self.name is not None: title += f"\nName: {self.name}" return f"{title}\n\n{self.content}"
[docs] def pretty_print(self) -> None: print(self.pretty_repr(html=is_interactive_env())) # noqa: T201
[docs]def merge_content( first_content: Union[str, List[Union[str, Dict]]], second_content: Union[str, List[Union[str, Dict]]], ) -> Union[str, List[Union[str, Dict]]]: """合并两个消息内容。 参数: first_content:第一个内容。 second_content:第二个内容。 返回: 合并后的内容。 """ # If first chunk is a string if isinstance(first_content, str): # If the second chunk is also a string, then merge them naively if isinstance(second_content, str): return first_content + second_content # If the second chunk is a list, add the first chunk to the start of the list else: return_list: List[Union[str, Dict]] = [first_content] return return_list + second_content # If both are lists, merge them naively elif isinstance(second_content, List): return first_content + second_content # If the first content is a list, and the second content is a string else: # If the last element of the first content is a string # Add the second content to the last element if isinstance(first_content[-1], str): return first_content[:-1] + [first_content[-1] + second_content] else: # Otherwise, add the second content as a new element of the list return first_content + [second_content]
[docs]class BaseMessageChunk(BaseMessage): """消息块,可以与其他消息块连接。"""
[docs] @classmethod def get_lc_namespace(cls) -> List[str]: """获取langchain对象的命名空间。""" return ["langchain", "schema", "messages"]
def __add__(self, other: Any) -> BaseMessageChunk: # type: ignore if isinstance(other, BaseMessageChunk): # If both are (subclasses of) BaseMessageChunk, # concat into a single BaseMessageChunk return self.__class__( # type: ignore[call-arg] id=self.id, content=merge_content(self.content, other.content), additional_kwargs=merge_dicts( self.additional_kwargs, other.additional_kwargs ), response_metadata=merge_dicts( self.response_metadata, other.response_metadata ), ) else: raise TypeError( 'unsupported operand type(s) for +: "' f"{self.__class__.__name__}" f'" and "{other.__class__.__name__}"' )
[docs]def message_to_dict(message: BaseMessage) -> dict: """将消息转换为字典。 参数: message:要转换的消息。 返回: 作为字典的消息。 """ return {"type": message.type, "data": message.dict()}
[docs]def messages_to_dict(messages: Sequence[BaseMessage]) -> List[dict]: """将消息序列转换为字典列表。 参数: messages:要转换的消息序列(作为BaseMessages)。 返回: 作为字典的消息列表。 """ return [message_to_dict(m) for m in messages]
[docs]def get_msg_title_repr(title: str, *, bold: bool = False) -> str: """获取消息的标题表示。 参数: title: 标题。 bold: 是否加粗标题。 返回: 标题表示。 """ padded = " " + title + " " sep_len = (80 - len(padded)) // 2 sep = "=" * sep_len second_sep = sep + "=" if len(padded) % 2 else sep if bold: padded = get_bolded_text(padded) return f"{sep}{padded}{second_sep}"