messages: list[dict[str, Any]] = field(default_factory=list) 核心对话历史:Anthropic 格式的消息列表

在 Python(特别是使用dataclassesPydantic)中,这行代码的设计非常地道且考究。它完美平衡了Python 语言特性Anthropic API 的架构规范

我们可以从Python 代码设计Anthropic 协议设计两个维度拆解为什么要这样设计:

1. 为什么用field(default_factory=list)而不是default=[]

这是 Pythondataclass的核心机制与避坑指南。

  • 陷阱(Mutable Default Argument):如果直接写messages: list = [],Python 会在加载类定义时只创建一个列表对象。后续该类所有的实例,只要未显式传参,都会共享同一个列表!用户 A 的对话记录会直接漏给用户 B。

  • 解决方案:default_factory=list是一个工厂函数。它告诉dataclass:“每次创建一个新实例时,调用一次list()(即[]),生成一个全新的、独立的列表。”

2. 为什么类型注解是list[dict[str, Any]]

Anthropic API 的消息结构在 JSON 层面上天然对应 Python 的字典列表:

JSON

[ {"role": "user", "content": "Hello!"}, {"role": "assistant", "content": "Hi there!"} ]
  • list[...]对话历史是一个严格有序的时间序列,列表能够保持消息的先后顺序。

  • dict[str, Any]

    • 键(Key)一定是字符串(如"role","content")。

    • 值(Value)用Any是因为content不仅可以传字符串,还可以传复合结构(如多模态图片、Tool Use / Function Calling 结构):

      Python
      # 多模态/工具调用的 content 往往是一个 list[dict] "content": [ {"type": "text", "text": "What is in this image?"}, {"type": "image", "source": {...}} ]

      因此,Any灵活地容纳了纯文本、多模态以及工具调用(Tool Calls)的复杂数据。

3. 为什么是 Anthropic 格式(与 OpenAI 有何区别)?

Anthropic 的 Messages API 设计强调了严格的交替对话逻辑职责分离

① 角色严格限定为userassistant

不同于 OpenAI 把system消息直接混在messages列表中(如{"role": "system", ...}),Anthropic 强制规定messages中只能出现userassistant

  • system提示词必须作为 API 的顶层单独参数传递(例如client.messages.create(system="...", messages=...))。

  • 因此,这里的messages列表是极其纯粹的对话历史

② 严格交替(Strict Alternation)

Anthropic 要求messages中的角色必须交替出现user->assistant->user...),且第一条消息通常必须是user

总结

设计细节解决的核心问题
default_factory=list隔离状态:防止多会话共享同一列表引发数据污染。
dict[str, Any]支持多模态 & 工具:兼容文本、图片、Tool Call 等复杂数据结构。
Anthropic 专属逻辑职责分离:剥离system设定,专注于严格交替的user/assistant上下文。