作为消息的基类,BaseMessage利用其content字段存储原始的内容,它可以是一个字符串或者字典列表。原始的内容会转换成一个ContentBlock列表通过content_blocks的属性返回。作为消息的主体内容,它们可以是一段单纯的字符串文本,也可以一段多媒体内容(比如图片、音频和视频)或者一个二进制文件,不同的内容形态对应着相应的ContentBlock类型,这些类型之间的关系体现在如下这个UML类图中(框起来的部分)

Alternative Text

ContentBlock并不是一个基类,而是针对六个类型的联合,它们仅仅是单纯的类型字典。这些类型具有一些相同的数据成员,比如表示专属类型的type字段,作为唯一标识的id字段,表示当偏移位置的index字段和一个存放额外数据的extras字段。

class BaseMessage(Serializable):
    content: str | list[str | dict]
    @property
    def content_blocks(self) -> list[types.ContentBlock]

ContentBlock = (
    TextContentBlock
    | InvalidToolCall
    | ReasoningContentBlock
    | NonStandardContentBlock
    | DataContentBlock
    | ToolContentBlock
)

1. TextContentBlock

TextContentBlock的荷载内容是一个单纯的字符串文本。它专属的类型为“text”,作为主体内容的文本存储于text字段中。

class TextContentBlock(TypedDict):
    type: Literal["text"]
    id: NotRequired[str]
    text: str
    annotations: NotRequired[list[Annotation]]
    index: NotRequired[int | str]
    extras: NotRequired[dict[str, Any]]

它的annotations字段返回一个表示元数据标注Annotation列表。Annotation是针对CitationNonStandardAnnotation的联合类型。在LangChain的多模态和RAG体系中,表示“引文”的CitationTextContentBlock中最重要的标注类型,它构建了模型回答与原始数据源之间的引用关系。当模型基于外部文档(如 PDF、网页、数据库)生成回答时,它会在文本中插入引用标准,并在消息的annotations字段中提供该引用的详细元数据。

Annotation = Citation | NonStandardAnnotation

class Citation(TypedDict):
    type: Literal["citation"]
    id: NotRequired[str]
    url: NotRequired[str]
    title: NotRequired[str]
    start_index: NotRequired[int]
    end_index: NotRequired[int]
    cited_text: NotRequired[str]
    extras: NotRequired[dict[str, Any]]

Citation同样具有专属的类型“citation”,其urltitlestart_indexend_indexcited_text分别表示引用的地址、标题、起止位置和引用文本。除了这种“标准”的基于引用的标注之外,其他标注都使用非标准的NonStandardAnnotation类型来定义。它对应的专属类型为“non_standard”,标注的内容以字典的形式存储于value字段。

class NonStandardContentBlock(TypedDict):
    type: Literal["non_standard"]
    id: NotRequired[str]
    value: dict[str, Any]
    index: NotRequired[int | str]

2. InvalidToolCall

InvalidToolCall是专门为处理模型幻觉或解析失败而设计的结构化错误类型。当模型通过分析提示词并确定需要调用某个工具时,它会尝试生成对应的ToolCall。如果生成的参数不具有有效结构,此时不会有异常抛出来,而是会生成一个InvalidToolCall来描述这种“生成TooCall失败”的场景。

class InvalidToolCall(TypedDict):
    type: Literal["invalid_tool_call"]
    id: str | None
    name: str | None
    args: str | None
    error: str | None
    index: NotRequired[int | str]
    extras: NotRequired[dict[str, Any]]

InvalidToolCall专属的类型为“invalid_tool_call”,其idnameargserror分别表示试图生成“工具调用”的唯一标识、名称、输入参数和错误描述。

3. ReasoningContentBlock

ReasoningContentBlock是专门为“推理型模型”设计的结构化内容块。它的应用标志着大模型从直接给出答案进化到了“先思考,后回答”的显式表达阶段。它专属的类型为“reasoning”,具体的推理逻辑通过reasoning字段返回的文本进行描述。

class ReasoningContentBlock(TypedDict):
    type: Literal["reasoning"]
    id: NotRequired[str]
    reasoning: NotRequired[str]
    index: NotRequired[int | str]
    extras: NotRequired[dict[str, Any]]

4. NonStandardContentBlock

NonStandardContentBlock是一个典型的“中间层兼容方案”。它的存在是为了解决大模型行业飞速发展带来的非标准输出与LangChain 核心标准之间的冲突。大模型厂商竞争激烈,经常推出新的内容形式(比如自定义的3D渲染数据、特定的数学公式格式或私有的文件引用结构等),当 LangChain 的核心库还没来得及为它们定义专属的ContentBlock类型时,统一使用NonStandardContentBlock来表示。它对应的专属类型为“non_standard”,承载的内容存储于value字段返回的字典中。

class NonStandardContentBlock(TypedDict):
    type: Literal["non_standard"]
    id: NotRequired[str]
    value: dict[str, Any]
    index: NotRequired[int | str]

5. DataContentBlock

表示“数据内容”的DataContentBlock也不是一个具体的类型,而是针对五个具体类型的联合,它们分别对应于图片、视频、音频、纯文本和文件五种内容形式。它们与HTTP请求和响应的主体内容极其相似,而且它们的mime_type字段表示的MIME类型与HTTP中的语义是完全一致的。

DataContentBlock = (
    ImageContentBlock
    | VideoContentBlock
    | AudioContentBlock
    | PlainTextContentBlock
    | FileContentBlock
)

这五个具体的数据内容块专属的类型分别是“image”、“video”、“audio”、“text-plain”和“file”。共同的字段除了mime_type之外,还有表示文件标识的file_id字段,表示目标地址的url字段和采用Base64编码内容base64字段。PlainTextContentBlock处理表示文本内容的text之外,还有表示标题和上下文的titlecontext字段。

class ImageContentBlock(TypedDict):
    type: Literal["image"]
    id: NotRequired[str]
    file_id: NotRequired[str]
    mime_type: NotRequired[str]
    index: NotRequired[int | str]
    url: NotRequired[str]
    base64: NotRequired[str]
    extras: NotRequired[dict[str, Any]]

class VideoContentBlock(TypedDict):
    type: Literal["video"]
    id: NotRequired[str]
    file_id: NotRequired[str]
    mime_type: NotRequired[str]
    index: NotRequired[int | str]
    url: NotRequired[str]
    base64: NotRequired[str]
    extras: NotRequired[dict[str, Any]]

class AudioContentBlock(TypedDict):
    type: Literal["audio"]
    id: NotRequired[str]
    file_id: NotRequired[str]
    mime_type: NotRequired[str]
    index: NotRequired[int | str]
    url: NotRequired[str]
    base64: NotRequired[str]
    extras: NotRequired[dict[str, Any]]

class PlainTextContentBlock(TypedDict):
    type: Literal["text-plain"]
    id: NotRequired[str]
    file_id: NotRequired[str]
    mime_type: Literal["text/plain"]
    index: NotRequired[int | str]
    url: NotRequired[str]
    base64: NotRequired[str]
    text: NotRequired[str]
    title: NotRequired[str]
    context: NotRequired[str]
    extras: NotRequired[dict[str, Any]]

class FileContentBlock(TypedDict):
    type: Literal["file"]
    id: NotRequired[str]
    file_id: NotRequired[str]
    mime_type: NotRequired[str]
    index: NotRequired[int | str]
    url: NotRequired[str]
    base64: NotRequired[str]
    extras: NotRequired[dict[str, Any]]

6. ToolContentBlock

ToolContent同样不是一个具体的类型,而是与工具调用相关的五个类型的联合,其中包括前面介绍的ToolCallToolCallChunk。它们是语言模型的产物,是模型“工具调用”的结构化描述,分别通过AIMessageAIMessageChunk返回给Agent,然后由后者实施调用。

ToolContentBlock = (
    ToolCall | ToolCallChunk | ServerToolCall | ServerToolCallChunk | ServerToolResult
)

如果我们使用HTTP作为类比,这样的作法相当于客户端重定向,那么有没有服务端重定向呢?当然有,当承载模型的服务端接收到Agent发送的提示词后,它其实可以在需要的时候自行实施工具调用。ServerToolCallServerToolCallChunk用于木描述这种由“服务端实施”的工具调用。这两个类型的成员定义与ToolCallToolCallChunk很类似,专属类型分别为“server_tool_call”和“server_tool_call_chunk”

class ServerToolCall(TypedDict):
    type: Literal["server_tool_call"]
    id: str
    name: str
    args: dict[str, Any]
    index: NotRequired[int | str]
    extras: NotRequired[dict[str, Any]]

class ServerToolCallChunk(TypedDict):
    type: Literal["server_tool_call_chunk"]
    name: NotRequired[str]
    args: NotRequired[str]
    id: NotRequired[str]
    index: NotRequired[int | str]
    extras: NotRequired[dict[str, Any]]

ServerToolCall/ServerToolCallChunk通常与MCP或远程工具服务相关,用于描述发送给远程工具服务器的请求。承载模型的服务端可以向独立运行的“工具服务器”发送一个 RPC 指令来远程执行指定的工具。比如在使用LangGraph的ToolNode时,如果是连接到托管的 MCP 服务器(如数据库查询服务),系统会将模型的生成的“服务调用意图”转化为发往该服务器的指令。

服务端驱动的工具调用的结果可以用一个ServerToolResult对象表示,它对应的专属类型为“server_tool_result”,我们可以利用它的tool_call_idstatusoutput字段得到工具调用的标识、状态和输出。

class ServerToolResult(TypedDict):
    type: Literal["server_tool_result"]
    id: NotRequired[str]
    tool_call_id: str
    status: Literal["success", "error"]
    output: NotRequired[Any]
    index: NotRequired[int | str]
    extras: NotRequired[dict[str, Any]]
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐