跳转至

消息与上下文

本页定义 Context、消息接口、内容块、构造器和序列化契约。多轮对话、图片输入、持久化和模型切换的完整实现分别放在对应的使用指南中。

消息与内容模型

一段历史就是一个 []llm.MessageMessage 是一个接口,有三个实现,每个角色一个。每个实现持有一组内容块,且角色限定了允许哪些块类型:

消息 角色 允许的内容块
UserMessage 用户输入 TextContentImageContent
AssistantMessage 模型输出 TextContentThinkingContentToolCall
ToolResultMessage 工具结果 TextContentImageContent

内容块是实际读写的叶子类型:

承载内容
TextContent 纯文本(任意消息中均可)
ImageContent base64 图像数据加 MIME 类型
ThinkingContent 推理文本及其 provider 签名(仅 assistant)
ToolCall 工具名、ID 与解码后的参数(仅 assistant)

由于消息和块都是带类型的,已存对话可无需手动分派地通过 JSON 往返——见JSON 序列化

对于常见的“只发文本”场景,请使用下面的便捷构造器。仅当需要构造器覆盖不到的内容时才手写结构体字面量,例如在一条用户消息里混合文本与图像,或预置一条携带工具调用的 assistant 轮次。完整图片输入见发送图片

构建消息

ContextMessage 以及内容块都是完全通用的,但多数调用只是发送一些文本。便捷构造器为这种场景省去了嵌套:

llm.Prompt("Explain Go channels briefly.")        // 含一条用户文本消息的 Context
llm.PromptWithSystem("Be concise.", "Explain...") // ……外加一个 system 提示
llm.UserText("hello")                             // *UserMessage
llm.AssistantText("hi there")                     // *AssistantMessage(用于预置历史)
llm.UserImage(data, "image/png")                  // 含一张图像的 *UserMessage
llm.ToolResult(callID, name, "result text")       // *ToolResultMessage
llm.NewContext(msg1, msg2, ...)                   // 由若干消息构成的 Context

AssistantMessage 上对应的访问器读回响应:

response.Text()      // 拼接所有文本块
response.ToolCalls() // 按顺序返回每一个工具调用

下面这种完整的结构体字面量写法仍然有效;当需要构造器未覆盖的内容时(例如在一条消息中混合文本和图像),再使用它。

历史与模型转换

llm 不保存会话状态。调用方维护 []llm.Message,每轮依次追加 *AssistantMessage 和新的用户消息,再放回 Context.MessagesSystemPrompt 是请求上下文的一部分,不会自动写入消息切片。完整的并发控制、存储边界和恢复程序见保存与恢复对话

请求发出前,TransformMessages 会创建面向目标模型的历史副本:

已存内容 转换行为
图片发送给纯文本模型 替换为文本占位符
同一模型产生的推理内容 保留兼容的推理内容和签名
其他模型产生的推理内容 删除模型服务专有的推理内容
工具调用 ID 按目标协议规范化,并同步更新对应结果
失败或取消的 assistant 消息 从重放副本中删除
没有结果的工具调用 插入合成错误结果

“同一模型”要求 provider、协议和模型 ID 均一致。转换不会修改调用方传入的历史;未转换的消息对象可能与原切片共享,调用方应把输入历史视为不可变值。

跨模型使用的完整流程与兼容性检查见对话中更换模型

JSON 序列化

Context 实现 JSON 往返。消息在 JSON 中携带角色,内容块携带类型,反序列化后会恢复为具体的消息和内容实现。按记录保存单条消息时,使用 MarshalMessageUnmarshalMessage

data, err := llm.MarshalMessage(messages[0])
if err != nil {
    log.Fatal(err)
}

message, err := llm.UnmarshalMessage(data)
if err != nil {
    log.Fatal(err)
}
messages = append(messages, message)

遇到未知角色、未知内容类型或畸形 JSON 时,UnmarshalMessage 返回错误,不会把不支持的结构静默转换为其他类型。完整的文件与数据库示例、并发写入和版本字段建议见保存与恢复对话。图片的编码、输入能力检查和安全边界见发送图片

序列化的历史是敏感数据

序列化后的 Context 可能包含用户输入、工具结果(其中可能嵌入抓取到的文档或凭证)以及提供方的推理签名。请把这份 JSON 当作敏感数据:不要整体打日志,存储或传输时应与其中的底层数据同等对待。