docs(comments): 注释中文化 · internal/runtime/model + internal/services/backthink(54 文件,纯替换)
- 只翻注释/文档字符串:`go/scanner` 剥注释后按 token 序列+literal 逐 token 比对,**54/54 文件 SAME**;
改动文件总行数与 HEAD 漂移 = 0(严格 1:1,无合并/拆行)
- 裁决编号与 design 节号逐字保留(03.4.1/03.4.2/03.4.3/14.4.1/14.4.5/07.4.2-4、design/04 §3.1/§3.2 等);
`chat_template_kwargs` / `enable_thinking` / `reasoning_effort` / `thinking:{type}` 字段名与形状说明未动
- 存疑译法(已登记):`persona` 在叙事语境用「角色」、标识符语境保留 `persona`(仓库既有模块本身混用);
`rung`→「级」;`provider` 存在「提供商/提供者」两种落笔(可按需一键统一)
- 复核:build/vet 绿 + 两包测试绿;gofmt 干净;残留英文注释 0 条
- 既有存量(未修,只报告):`model/anthropic_test.go` 612 行 >500;`applyAnthropicEvent` 115 行 >80
This commit is contained in:
1 parent
f5cf117482
commit
3dc1232bc2
54 files changed
+1923
-1923
No files matched your search
+149
-149
@@ -1,102 +1,102 @@
|
||||
// Package model provides a vendor-agnostic LLM adapter layer for Cyrene v2.
|
||||
// model 包为 Cyrene v2 提供与厂商无关的 LLM 适配层。
|
||||
//
|
||||
// It defines a normalized Message/Request/Response vocabulary, a single
|
||||
// Adapter interface implemented by OpenAIChatAdapter (which speaks the
|
||||
// OpenAI-compatible /chat/completions protocol used by OpenAI, DashScope/百炼,
|
||||
// local gateways and proxies), a per-role Router, an automatic fallback Chain,
|
||||
// multimodal (vision) detection, and per-call CallRecord accounting.
|
||||
// 它定义了归一化的 Message/Request/Response 词汇、单个
|
||||
// 由 OpenAIChatAdapter 实现的 Adapter 接口(该适配器说
|
||||
// OpenAI、DashScope/百炼等使用的 OpenAI 兼容 /chat/completions 协议、
|
||||
// 本地网关与代理),还有按角色的 Router、自动降级 Chain、
|
||||
// 多模态(视觉)检测与按调用的 CallRecord 计账。
|
||||
//
|
||||
// The full tool loop (schema registration, argument binding, result re-feed) is
|
||||
// deferred to M2; this package only carries interface-level placeholders
|
||||
// (ToolSpec) so the wire contract is ready without executing any loop.
|
||||
// 完整的工具循环(schema 注册、参数绑定、结果回喂)
|
||||
// 推迟到 M2;本包只携带接口级占位
|
||||
// (ToolSpec),让线格式契约先就绪,而不执行任何循环。
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// Role identifies who authored a message. The values are vendor-agnostic and
|
||||
// translated to each provider's own role vocabulary by the adapter.
|
||||
// Role 标识消息的作者。取值与厂商无关,
|
||||
// 由适配器翻译成各提供商自己的角色词汇。
|
||||
type Role string
|
||||
|
||||
const (
|
||||
// RoleSystem is a system/instruction message.
|
||||
// RoleSystem 是系统/指令消息。
|
||||
RoleSystem Role = "system"
|
||||
// RoleUser is an end-user message.
|
||||
// RoleUser 是终端用户消息。
|
||||
RoleUser Role = "user"
|
||||
// RoleAssistant is an assistant (model) message.
|
||||
// RoleAssistant 是助手(模型)消息。
|
||||
RoleAssistant Role = "assistant"
|
||||
// RoleTool is a tool-result message (reserved for the M2 tool loop).
|
||||
// RoleTool 是工具结果消息(保留给 M2 工具循环)。
|
||||
RoleTool Role = "tool"
|
||||
)
|
||||
|
||||
// ContentType describes the kind of payload inside a Content part.
|
||||
// ContentType 描述 Content 片段内负载的种类。
|
||||
type ContentType string
|
||||
|
||||
const (
|
||||
// ContentTypeText is a plain-text content part.
|
||||
// ContentTypeText 是纯文本内容片段。
|
||||
ContentTypeText ContentType = "text"
|
||||
// ContentTypeImage is an image content part.
|
||||
// ContentTypeImage 是图片内容片段。
|
||||
ContentTypeImage ContentType = "image_url"
|
||||
// ContentTypeToolCall is an assistant-originated tool invocation part
|
||||
// (Anthropic tool_use / OpenAI tool_calls), carried on a RoleAssistant turn.
|
||||
// ContentTypeToolCall 是助手发起的工具调用片段
|
||||
// (Anthropic tool_use / OpenAI tool_calls),挂在 RoleAssistant 回合上。
|
||||
ContentTypeToolCall ContentType = "tool_call"
|
||||
// ContentTypeToolResult is a tool execution result part, carried on a RoleTool
|
||||
// turn and encoded natively (Anthropic tool_result / OpenAI tool message).
|
||||
// ContentTypeToolResult 是工具执行结果片段,挂在 RoleTool
|
||||
// 回合上并按原生方式编码(Anthropic tool_result / OpenAI tool message)。
|
||||
ContentTypeToolResult ContentType = "tool_result"
|
||||
)
|
||||
|
||||
// Content is a single, possibly multimodal, part of a message.
|
||||
// Content 是消息的单个片段,可能是多模态的一部分。
|
||||
type Content struct {
|
||||
// Type distinguishes a text part from an image / tool part.
|
||||
// Type 区分文本片段与图片 / 工具片段。
|
||||
Type ContentType
|
||||
// Text is the text payload when Type == ContentTypeText, or the result body
|
||||
// when Type == ContentTypeToolResult.
|
||||
// Text 是 Type == ContentTypeText 时的文本负载,
|
||||
// 或 Type == ContentTypeToolResult 时的结果正文。
|
||||
Text string
|
||||
// ImageURL is the image source when Type == ContentTypeImage. It may be a
|
||||
// data: URI or an http(s):// URL.
|
||||
// ImageURL 是 Type == ContentTypeImage 时的图片来源。它可以是
|
||||
// data: URI 或 http(s):// URL。
|
||||
ImageURL string
|
||||
// ToolCallID correlates the part to a provider tool_use/tool_call id: the call
|
||||
// id for ContentTypeToolCall, or the tool_use_id being answered for
|
||||
// ContentTypeToolResult.
|
||||
// ToolCallID 把片段关联到提供商的 tool_use/tool_call id:
|
||||
// ContentTypeToolCall 对应调用 id,
|
||||
// ContentTypeToolResult 对应被应答的 tool_use_id。
|
||||
ToolCallID string
|
||||
// ToolCallName is the invoked tool name when Type == ContentTypeToolCall.
|
||||
// ToolCallName 是 Type == ContentTypeToolCall 时被调用的工具名。
|
||||
ToolCallName string
|
||||
// ToolArgs is the structured argument object when Type == ContentTypeToolCall.
|
||||
// It is never a JSON-encoded string.
|
||||
// ToolArgs 是 Type == ContentTypeToolCall 时的结构化参数对象。
|
||||
// 它绝不是 JSON 编码的字符串。
|
||||
ToolArgs map[string]any
|
||||
// IsError marks a ContentTypeToolResult part as an execution failure so the
|
||||
// provider's tool_result.is_error / error flag is set natively.
|
||||
// IsError 把 ContentTypeToolResult 片段标记为执行失败,
|
||||
// 以便原生设置提供商的 tool_result.is_error / error 标志。
|
||||
IsError bool
|
||||
}
|
||||
|
||||
// Message is a single conversation turn, normalized across providers.
|
||||
// Message 是单个会话回合,已跨提供商归一化。
|
||||
type Message struct {
|
||||
Role Role
|
||||
// Content carries one or more parts. A text-only message uses a single
|
||||
// ContentTypeText part.
|
||||
// Content 携带一个或多个片段。仅文本的消息使用单个
|
||||
// ContentTypeText 片段。
|
||||
Content []Content
|
||||
// SenderName is the human-readable display name of the message's sender
|
||||
// (design/16 §4.6). It is transport metadata used by the context-assembly
|
||||
// layer to label third-party messages for the model (e.g. "[第三方 · 昵称]"),
|
||||
// never a substitute for the strongly typed sender identity carried on the
|
||||
// channel layer. Empty means the sender is unlabeled (the owner, or an
|
||||
// unknown/unresolved sender), and callers may leave it unset.
|
||||
// SenderName 是消息发送者可读的显示名
|
||||
// (design/16 §4.6)。它是上下文组装层用来给模型
|
||||
// 标注第三方消息(如 "[第三方 · 昵称]")的传输元数据,
|
||||
// 绝不是 channel 层强类型发送者身份的替代品。
|
||||
// 为空表示发送者未标注(主人,或未识别/未解析的发送者),
|
||||
// 调用方可以留着不设置。
|
||||
SenderName string
|
||||
// ToolCallID correlates a RoleTool turn to the provider tool_use/tool_call id
|
||||
// it answers, and ToolCallName is the invoked tool name carried as a
|
||||
// convenience for callers that render the result. Both are set by the tool
|
||||
// loop when it feeds a result back, and consumed by the adapters to emit
|
||||
// native tool_result / tool-message blocks.
|
||||
// ToolCallID 把 RoleTool 回合关联到它所应答的提供商
|
||||
// tool_use/tool_call id,而 ToolCallName 是同时携带的
|
||||
// 被调用工具名,方便渲染结果的调用方使用。两者都由工具
|
||||
// 循环在回喂结果时设置,并被适配器消费以发出
|
||||
// 原生 tool_result / tool-message 块。
|
||||
ToolCallID string
|
||||
ToolCallName string
|
||||
}
|
||||
|
||||
// TextMessage builds a text-only message.
|
||||
// TextMessage 构建仅文本的消息。
|
||||
func TextMessage(role Role, text string) Message {
|
||||
return Message{Role: role, Content: []Content{{Type: ContentTypeText, Text: text}}}
|
||||
}
|
||||
|
||||
// ImageMessage builds a message carrying optional text plus an image. imageURL
|
||||
// may be a data: URI or an http(s):// URL. An empty text omits the text part.
|
||||
// ImageMessage 构建携带可选文本加一张图片的消息。imageURL
|
||||
// 可以是 data: URI 或 http(s):// URL。文本为空则省略文本片段。
|
||||
func ImageMessage(role Role, text, imageURL string) Message {
|
||||
parts := make([]Content, 0, 2)
|
||||
if text != "" {
|
||||
@@ -106,17 +106,17 @@ func ImageMessage(role Role, text, imageURL string) Message {
|
||||
return Message{Role: role, Content: parts}
|
||||
}
|
||||
|
||||
// ToolResultMessage builds a RoleTool turn carrying the native result of one tool
|
||||
// call. toolUseID must equal the provider id of the tool_use block this result
|
||||
// answers; isError marks an execution failure; text is the result body.
|
||||
// ToolResultMessage 构建一个 RoleTool 回合,携带某次工具调用的
|
||||
// 原生结果。toolUseID 必须等于该结果所应答的 tool_use 块的
|
||||
// 提供商 id;isError 标记执行失败;text 是结果正文。
|
||||
func ToolResultMessage(toolUseID, text string, isError bool) Message {
|
||||
return Message{Role: RoleTool, ToolCallID: toolUseID,
|
||||
Content: []Content{{Type: ContentTypeToolResult, Text: text, ToolCallID: toolUseID, IsError: isError}}}
|
||||
}
|
||||
|
||||
// AssistantToolCallMessage builds a RoleAssistant turn advertising the tool calls
|
||||
// the model requested, so a subsequent RoleTool turn can be correlated to them by
|
||||
// the provider (OpenAI tool_call_id / Anthropic tool_use_id).
|
||||
// AssistantToolCallMessage 构建一个 RoleAssistant 回合,声明模型
|
||||
// 请求过的工具调用,好让随后一个 RoleTool 回合能被提供商
|
||||
// 关联回来(OpenAI tool_call_id / Anthropic tool_use_id)。
|
||||
func AssistantToolCallMessage(calls []ToolCall) Message {
|
||||
parts := make([]Content, 0, len(calls))
|
||||
for _, c := range calls {
|
||||
@@ -125,148 +125,148 @@ func AssistantToolCallMessage(calls []ToolCall) Message {
|
||||
return Message{Role: RoleAssistant, Content: parts}
|
||||
}
|
||||
|
||||
// ToolSpec is an interface-level placeholder for a tool/function schema. The
|
||||
// full tool loop (registration, argument binding, result re-feed) is M2; here
|
||||
// it only lets a request advertise tools to the provider in the wire contract.
|
||||
// ToolSpec 是工具/函数 schema 的接口级占位。完整
|
||||
// 工具循环(注册、参数绑定、结果回喂)属于 M2;这里
|
||||
// 只让请求能在线格式契约里向提供商声明工具。
|
||||
type ToolSpec struct {
|
||||
Name string
|
||||
Description string
|
||||
// Parameters is the JSON Schema for the tool arguments. Populated from M2.
|
||||
// Parameters 是工具参数的 JSON Schema。M2 起填入。
|
||||
Parameters any
|
||||
}
|
||||
|
||||
// ToolCall is a single assistant-originated tool invocation parsed from a
|
||||
// provider's tool_use content block. Args is the structured argument object
|
||||
// (never a serialized JSON string), so a tool loop can bind it directly without
|
||||
// re-parsing.
|
||||
// ToolCall 是从提供商的 tool_use 内容块解析出的单个
|
||||
// 助手发起的工具调用。Args 是结构化参数对象
|
||||
// (绝不是序列化后的 JSON 字符串),因此工具循环可以直接绑定它,
|
||||
// 无需重新解析。
|
||||
type ToolCall struct {
|
||||
// ID is the provider tool_use/tool_call id, so a tool loop can correlate the
|
||||
// resulting RoleTool message to the exact call (Anthropic tool_use_id / OpenAI
|
||||
// tool_call_id). Empty when the provider emitted no id.
|
||||
// ID 是提供商的 tool_use/tool_call id,工具循环因此能把
|
||||
// 产生的 RoleTool 消息关联到确切的那次调用(Anthropic tool_use_id /
|
||||
// OpenAI tool_call_id)。提供商未发出 id 时为空。
|
||||
ID string
|
||||
// Name is the tool being invoked.
|
||||
// Name 是被调用的工具。
|
||||
Name string
|
||||
// Args are the tool arguments, decoded from the provider's structured
|
||||
// tool_use.input object. It is never a JSON-encoded string.
|
||||
// Args 是工具参数,由提供商的结构化
|
||||
// tool_use.input 对象解码而来。它绝不是 JSON 编码的字符串。
|
||||
Args map[string]any
|
||||
}
|
||||
|
||||
// Request is a completion request, normalized across providers.
|
||||
// Request 是一次补全请求,已跨提供商归一化。
|
||||
type Request struct {
|
||||
// Model overrides the adapter's configured default model. Empty means the
|
||||
// adapter default (or the chain step model) applies.
|
||||
// Model 覆盖适配器已配置的默认模型。为空表示
|
||||
// 使用适配器默认值(或链步骤模型)。
|
||||
Model string
|
||||
Messages []Message
|
||||
// Temperature is the sampling temperature. nil means the provider default.
|
||||
// Temperature 是采样温度。nil 表示提供商默认值。
|
||||
//
|
||||
// DeepSeek notes (design/04 §3.2 facts 3 and 4): temperature takes no effect
|
||||
// while thinking is on. frequency_penalty and presence_penalty are deprecated
|
||||
// at the API level — "传入该参数将不会产生任何效果" — in every mode, which is
|
||||
// why Request has no field for them. top_p is deliberately not exposed
|
||||
// either: it only applies while thinking is on and is clamped to >= 0.95
|
||||
// there, is always 1.0 otherwise, so sending a configured value would be
|
||||
// silently ineffective on one side of the switch and a hard floor on the
|
||||
// other.
|
||||
// DeepSeek 说明(design/04 §3.2 事实 3 与 4):思考开启期间
|
||||
// temperature 不生效。frequency_penalty 与 presence_penalty 已被弃用
|
||||
// ——「传入该参数将不会产生任何效果」——在任何模式下都是如此,
|
||||
// 这就是 Request 没有对应字段的原因。top_p 同样被刻意不暴露:
|
||||
// 它只在思考开启时生效,且在那里被夹到 >= 0.95,
|
||||
// 其它情况下恒为 1.0,所以发送一个配置好的值
|
||||
// 会在开关的一侧静默失效,
|
||||
// 在另一侧则成为硬性下限。
|
||||
Temperature *float64
|
||||
// MaxTokens caps the generated tokens. Zero means the provider default.
|
||||
// MaxTokens 限制生成的 token 数。为零表示提供商默认值。
|
||||
MaxTokens int
|
||||
// Purpose labels the call for CallRecord accounting (e.g. "chat").
|
||||
// Purpose 为该次调用打标签,用于 CallRecord 计账(如 "chat")。
|
||||
Purpose string
|
||||
// PersonaID is the persona this turn answers as — the persona-level routing
|
||||
// key of 裁决 03.4.1, as opposed to the LLM message role. RuntimeLLM reads it
|
||||
// to pick the persona's provider chain (models.json personaProviders, i.e. a
|
||||
// cross-protocol per-persona route). Empty means "no persona binding": the
|
||||
// active group's default chain serves the request, so every pre-existing
|
||||
// caller behaves exactly as before.
|
||||
// PersonaID 是本回合以哪个角色作答——即
|
||||
// 裁决 03.4.1 所说的按角色路由的「角色」,与 LLM 消息角色不同。RuntimeLLM
|
||||
// 读它来挑出该角色的提供商链(models.json 的 personaProviders,即
|
||||
// 跨协议的按角色路由)。为空表示「无角色绑定」:
|
||||
// 由生效组的默认链服务该请求,因此所有既有
|
||||
// 调用方的行为与之前完全一致。
|
||||
//
|
||||
// Why a request field and not a context key: the decision happens at the
|
||||
// adapter boundary that already carries the Request, and the value is
|
||||
// per-call metadata of the same kind as Model/Purpose. The persona lives in
|
||||
// the loop's private session-env context key, which the model package cannot
|
||||
// read (model must not import loop), so a ctx carrier would have needed the
|
||||
// same write anyway — with the decision hidden behind an invisible key and
|
||||
// hard to assert across packages.
|
||||
// 为什么是请求字段而不是 context 键:该决策发生在
|
||||
// 本就携带 Request 的适配器边界上,而且这个值是
|
||||
// 与 Model/Purpose 同类的按调用元数据。角色存在于
|
||||
// loop 私有的会话环境 context 键里,而 model 包读不到
|
||||
// 它(model 不得 import loop),所以用 ctx 载体反正也得
|
||||
// 做同样的写入——只是决策被藏在一个看不见的键后面,
|
||||
// 且难以跨包断言。
|
||||
PersonaID string
|
||||
// Tools is the interface-level placeholder for M2 function calling.
|
||||
// Tools 是 M2 函数调用的接口级占位。
|
||||
Tools []ToolSpec
|
||||
// ToolChoice optionally directs how the provider selects a tool. It is an
|
||||
// opaque provider-agnostic directive (e.g. {"type":"auto"} or {"type":"tool",
|
||||
// "name":"x"}); empty means the provider default. Passed through verbatim to
|
||||
// protocols that support it (Anthropic's tool_choice).
|
||||
// ToolChoice 可选地指示提供商如何选择工具。它是一个
|
||||
// 提供商无关的不透明指令(如 {"type":"auto"} 或 {"type":"tool",
|
||||
// "name":"x"});为空表示提供商默认值。会原样传给
|
||||
// 支持它的协议(Anthropic 的 tool_choice)。
|
||||
//
|
||||
// DeepSeek red line (design/04 §3.2 fact 5): with thinking on — its default —
|
||||
// a forcing directive ("required" / "any" / a named tool) is rejected with a
|
||||
// 400, so thinking must be switched off explicitly first. The adapters only
|
||||
// WARN about that combination; they never switch thinking off on their own.
|
||||
// DeepSeek 红线(design/04 §3.2 事实 5):思考开启时——即其默认——
|
||||
// 强制型指令("required" / "any" / 具名工具)会被 400
|
||||
// 拒绝,因此必须先把思考显式关掉。适配器只对这种组合
|
||||
// 发 WARN;它们绝不会自行关掉思考。
|
||||
ToolChoice any
|
||||
// Thinking controls the provider's reasoning budget/switch (design/04 §3.2).
|
||||
// nil means "do not intervene" and uses the provider default. A provider
|
||||
// whose protocol has no mapping for it logs a WARN rather than silently
|
||||
// ignoring it.
|
||||
// Thinking 控制提供商的推理预算/开关(design/04 §3.2)。
|
||||
// nil 表示「不干预」,使用提供商默认值。协议中
|
||||
// 没有对应映射的提供商会记一条 WARN,而不是静默
|
||||
// 忽略它。
|
||||
//
|
||||
// "Do not intervene" is not the same as "off": DeepSeek's thinking defaults to
|
||||
// enabled, so Enable=false is what closes it there (sent as
|
||||
// {"thinking":{"type":"disabled"}}).
|
||||
// 「不干预」不等于「关闭」:DeepSeek 的思考默认
|
||||
// 开启,所以在那里要靠 Enable=false 来关(发送为
|
||||
// {"thinking":{"type":"disabled"}})。
|
||||
Thinking *Thinking
|
||||
// ReasoningEffort is the OpenAI-compatible reasoning strength knob
|
||||
// (reasoning_effort). Empty means "do not intervene". The value is validated
|
||||
// against the detected provider's whitelist; an unrecognized value is dropped
|
||||
// with a WARN and never replaced by a different tier (design/04 §3.2 fact 1).
|
||||
// DeepSeek additionally documents compatibility aliases (minimal→low,
|
||||
// medium/xhigh→high, ultra→max), which are normalized to the tier the service
|
||||
// applies.
|
||||
// ReasoningEffort 是 OpenAI 兼容的推理强度旋钮
|
||||
// (reasoning_effort)。为空表示「不干预」。该值会针对
|
||||
// 已识别提供商的白名单校验;无法识别的值会带着 WARN
|
||||
// 被丢弃,绝不会被换成别的档位(design/04 §3.2 事实 1)。
|
||||
// DeepSeek 另外记录了兼容别名(minimal→low、
|
||||
// medium/xhigh→high、ultra→max),它们会被归一化为服务
|
||||
// 实际采用的档位。
|
||||
ReasoningEffort string
|
||||
}
|
||||
|
||||
// Thinking carries the reasoning knobs a caller wants applied (design/04 §3.2).
|
||||
// Providers map the fields they actually support and report the rest; it only
|
||||
// controls budget/switch, never the thought content (design/01 §2.1 red line).
|
||||
// Thinking 携带调用方希望生效的推理旋钮(design/04 §3.2)。
|
||||
// 提供商映射它们真正支持的字段、并上报其余字段;它只
|
||||
// 控制预算/开关,绝不控制思考内容(design/01 §2.1 红线)。
|
||||
type Thinking struct {
|
||||
// BudgetTokens is the Anthropic thinking.budget_tokens target (the official
|
||||
// semantic is a target, not a hard cap). Zero selects the adapter default.
|
||||
// BudgetTokens 是 Anthropic thinking.budget_tokens 的目标值(官方
|
||||
// 语义是目标,不是硬上限)。为零则选用适配器默认值。
|
||||
BudgetTokens int
|
||||
// Enable is an explicit on/off switch for providers that expose a boolean
|
||||
// thinking flag. nil = no explicit switch.
|
||||
// Enable 是显式的开/关开关,供暴露布尔
|
||||
// thinking 标志的提供商使用。nil = 无显式开关。
|
||||
Enable *bool
|
||||
}
|
||||
|
||||
// Response is a normalized completion result.
|
||||
// Response 是归一化的补全结果。
|
||||
type Response struct {
|
||||
// Model is the model that produced the response.
|
||||
// Model 是产出该响应的模型。
|
||||
Model string
|
||||
Content string
|
||||
// Message is the normalized assistant message.
|
||||
// Message 是归一化的助手消息。
|
||||
Message Message
|
||||
// ToolCalls carries any tool_use blocks the assistant emitted. Empty when the
|
||||
// response is pure text.
|
||||
// ToolCalls 携带助手发出的任何 tool_use 块。响应是纯文本时为
|
||||
// 空。
|
||||
ToolCalls []ToolCall
|
||||
// StopReason is the provider's raw stop/finish reason (Anthropic stop_reason:
|
||||
// end_turn / max_tokens / tool_use; OpenAI finish_reason: stop / length /
|
||||
// tool_calls), so callers can distinguish a token-budget truncation from a
|
||||
// normal end. Empty when the provider reports none.
|
||||
// StopReason 是提供商原始的停止/结束原因(Anthropic stop_reason:
|
||||
// end_turn / max_tokens / tool_use;OpenAI finish_reason:stop / length /
|
||||
// tool_calls),因此调用方能区分 token 预算截断与
|
||||
// 正常结束。提供商未上报时为空。
|
||||
StopReason string
|
||||
// PromptTokens, CompletionTokens and TotalTokens report provider usage when
|
||||
// available; zero when the provider does not return it.
|
||||
// PromptTokens、CompletionTokens 与 TotalTokens 在可用时上报
|
||||
// 提供商用量;提供商未返回时为零。
|
||||
PromptTokens int
|
||||
CompletionTokens int
|
||||
TotalTokens int
|
||||
}
|
||||
|
||||
// CallRecord describes a single successfully completed LLM call, for the M9
|
||||
// monitor/frontend. A failed attempt emits no record.
|
||||
// CallRecord 描述一次成功完成的 LLM 调用,供 M9
|
||||
// 监控/前端使用。失败的尝试不产生记录。
|
||||
type CallRecord struct {
|
||||
// Model is the model that served the request.
|
||||
// Model 是服务该请求的模型。
|
||||
Model string
|
||||
// Purpose labels what the call was for.
|
||||
// Purpose 标注该次调用的用途。
|
||||
Purpose string
|
||||
// Tokens is the total token consumption reported by the provider.
|
||||
// Tokens 是提供商上报的总 token 消耗。
|
||||
Tokens int
|
||||
// TookMs is the end-to-end call latency in milliseconds.
|
||||
// TookMs 是端到端调用延迟,单位毫秒。
|
||||
TookMs int64
|
||||
}
|
||||
|
||||
// Options carries per-call knobs layered on top of the Request.
|
||||
// Options 携带叠加在 Request 之上的按调用旋钮。
|
||||
type Options struct {
|
||||
// Timeout bounds a single HTTP call. Zero uses the adapter client timeout.
|
||||
// Timeout 约束单次 HTTP 调用。为零则用适配器客户端的超时。
|
||||
Timeout time.Duration
|
||||
}
|
||||
Reference in new issue
Block a user