跳转至

推理与思考

StreamOptions.Reasoning 是一个与厂商无关的推理强度。每个适配器会将它映射到目标提供方的原生形式(Anthropic 的自适应或预算思考,或 OpenAI 兼容的推理字段),并将其限制在所选模型支持的级别范围内。非推理模型会忽略它,因此这个选项可以安全地设在任何模型上。

options := llm.StreamOptions{Reasoning: llm.ModelThinkingHigh}
response, err := llm.Complete(ctx, model, llm.Prompt("..."), options)

速览

用途 API
设置推理强度 StreamOptions.ReasoningModelThinkingLevel
可选级别 ModelThinkingOff / Minimal / Low / Medium / High / XHigh
查询模型支持的级别 SupportedThinkingLevels(model)ClampThinkingLevel(model, level)
是否具备推理能力 Model.Reasoning(bool)
流式读回思考 EventThinkingStart / Delta / End
从最终消息读回思考 ThinkingContentThinkingThinkingSignatureRedacted
控制思考如何返回(Anthropic) AnthropicStreamOptions.ThinkingDisplay

强度只决定"思考多少"。思考文本是否随响应返回则是另一个正交的旋钮:在 Anthropic 上由 ThinkingDisplay 控制(见 Anthropic 思考显示)。

推理强度

级别越高,模型在作答前可用于思考的 token 越多,以延迟和成本换取在难题上的质量。Reasoning 留空则使用模型自身的默认值。

级别 效果 何时使用
ModelThinkingOff 完全关闭思考 简单任务,或对延迟/成本敏感的路径
ModelThinkingMinimal 最小思考预算 只需一点点推理
ModelThinkingLow 轻量推理 大多数日常任务
ModelThinkingMedium 均衡推理 稳妥的默认选择
ModelThinkingHigh 面向难题的扩展推理 数学、规划、多步推理
ModelThinkingXHigh 最大思考预算 最难的问题,不计成本

在底层,该级别会映射到各提供方自己的控制:在 Anthropic 上是思考 token 预算(或自适应思考),在 OpenAI 兼容提供方上是 reasoning_effort 字段。中立的级别让代码在两者之间保持一致。

思考消耗的 token 计入 Usage.Output,与生成文本按同一输出费率计价,因此级别越高、单次请求越贵。用量与成本详见读取响应

检查模型支持哪些级别

并非每个模型都接受每个级别。SupportedThinkingLevels 返回某个模型支持的级别,ClampThinkingLevel 会把请求的级别贴合到最接近的受支持级别。StreamComplete 会自动贴合,但自行调用它有助于驱动 UI,或在模型不能推理时直接跳过该选项。

levels := llm.SupportedThinkingLevels(model)
if len(levels) == 0 {
    // 模型不支持推理;不要提供该控件。
}

// 把用户的选择贴合到模型能接受的级别。
requested := llm.ModelThinkingXHigh
effective := llm.ClampThinkingLevel(model, requested)
if effective != requested {
    log.Printf("model caps thinking at %s", effective)
}

response, err := llm.Complete(ctx, model, input, llm.StreamOptions{
    Reasoning: effective,
})

Model.Reasoning 是一个快速判断模型是否具备推理能力的布尔值。

读取思考内容

流式过程中,推理会在答案文本之前以独立的块到达(EventThinkingStartEventThinkingDeltaEventThinkingEnd),因此可将其与最终回复分开渲染。

for event := range events {
    switch event.Type {
    case llm.EventThinkingDelta:
        fmt.Fprint(thinkingPane, event.Delta)
    case llm.EventTextDelta:
        fmt.Fprint(answerPane, event.Delta)
    }
}

对于已完成的消息,推理是 response.Content 中的一个 ThinkingContent 块。Thinking 保存文本;ThinkingSignature 携带在后续轮次重放的提供方签名;Redacted 标记被提供方隐去的思考。

for _, block := range response.Content {
    if t, ok := block.(*llm.ThinkingContent); ok && !t.Redacted {
        fmt.Println("reasoning:", t.Thinking)
    }
}

Anthropic 思考显示

在 Anthropic 协议上,ThinkingDisplay 控制推理内容如何返回,但不改变模型是否进行推理。留空时默认为摘要化思考。

options := llm.StreamOptions{
    Reasoning: llm.ModelThinkingHigh,
    ProtocolOptions: &llm.AnthropicStreamOptions{
        ThinkingDisplay: llm.ThinkingDisplaySummarized,
    },
}

ThinkingDisplayOmitted 会隐去思考文本,同时保留多轮工具调用所需的签名。当应用不能展示推理内容、但后续请求仍需有效历史时使用它。

options := llm.StreamOptions{
    Reasoning: llm.ModelThinkingHigh,
    ProtocolOptions: &llm.AnthropicStreamOptions{
        ThinkingDisplay: llm.ThinkingDisplayOmitted,
    },
}

使用 ThinkingDisplayOmitted 时,不会有 EventThinkingDelta 事件到达,且 ThinkingContent 块会被标记为 Redacted

对话连续性

提供方所需的推理元数据(例如 Anthropic 签名和 OpenRouter 加密推理)会保留在 assistant 消息中,并在后续工具调用需要时重放。这一点对带思考的工具调用尤为重要:一些提供方要求把带签名的思考块原样回传,才会接受下一次工具调用,丢失它可能导致该轮失败。即使用 ThinkingDisplayOmitted 隐去了文本,本库仍保留该块,以保证历史有效。当目标模型发生变化时,本库会依据兼容性保留、降级或省略推理内容。模型切换与持久化详见对话