Skip to content

Responses

sungaowei edited this page Oct 16, 2026 · 2 revisions

响应结果处理 (Responses)

English Version | 简体中文


调用 client.SystemOne 成功后将返回一个 *SystemOneResponse 对象:

response.Model             // 实际执行评估的模型标识(可能与请求时传入的模型别名不同)
response.Usage             // Usage{InputTokens, OutputTokens *int} —— 包含可空的 Token 计数指针
response.Answers           // map[string]Answer,以问题名称为键的所有答案字典
response.Nouls()           // map[string]*NoulAnswer,过滤出所有 Noul 答案
response.Choices()         // map[string]*ChoiceAnswer,过滤出所有 Choice 答案
response.Scores()          // map[string]*ScoreAnswer,过滤出所有 Score 答案
response.Boxes()           // map[string]*BoxAnswer,过滤出所有 Box 目标定位答案
response.RawRequestID()    // 返回 x-typesafe-request-id 响应标头字符串,若无则返回空字符串 ""
response.RequestID()       // 返回 (string, error),若无该标头则返回显式错误
response.RawBody()         // 服务端返回的未经修改的原始字节流
response.RawHTTPResponse() // 返回底层 (*http.Response, error)

答案数据结构

每种原语对应具体的答案结构体:

答案结构体 包含字段 说明
NoulAnswer Type, Noul float64 Noul 为 0.0 ~ 1.0 的 Yes 概率
ChoiceAnswer Type, Choice string, Confidence float64, Probabilities map[string]float64 Choice 为胜出选项,Confidence 为该选项的置信度
ScoreAnswer Type, Score float64, Confidence float64, Legend map[int]any, Probabilities map[int]float64 Score 为期望分值,Legend 为各整数级别的图例,Probabilities 为各级别的概率
BoxAnswer Type, Box BoxCoordinates, Confidence *float64 Box 包含 Top, Bottom, Left, Right 归一化浮点坐标,Confidence 为可选置信度

Box 边界框坐标 (BoxCoordinates)

BoxCoordinates 的各个字段表示目标物体边界相对于整张图像高宽的比例,取值区间在 [0, 1] 之间:

type BoxCoordinates struct {
	Top    float64 `json:"top"`    // 上边缘距离图像顶部比例
	Bottom float64 `json:"bottom"` // 下边缘距离图像顶部比例
	Left   float64 `json:"left"`   // 左边缘距离图像左侧比例
	Right  float64 `json:"right"`  // 右边缘距离图像左侧比例
}

可空 Token 统计 (Usage)

在某些特定调用或底层模型下,服务端可能不返回 Token 消耗量,因此 Usage 中的字段被建模为指针类型:

type Usage struct {
	InputTokens  *int `json:"input_tokens"`
	OutputTokens *int `json:"output_tokens"`
}

Usage 实现了 fmt.Stringer,打印时会自动处理 nil:

fmt.Println(response.Usage)
// 输出: Usage{input_tokens: 492, output_tokens: 72}
// 若为空则输出: Usage{input_tokens: null, output_tokens: null}

分组访问器 (Grouped Accessors)

response.Answers 包含了所有问题的答案(以 Answer 接口形式存储)。 为了方便调用,SDK 提供了四个具体原语的类型化分组访问器:Nouls()、Choices()、Scores() 和 Boxes()。 访问器返回的指针与 Answers 内部存储的指针完全一致:

response.Answers["queue"] == response.Choices()["queue"] // 指向同一个内存地址

解码与校验规则

  1. 强字段校验:model 和 usage 是必需字段。若成功的 HTTP 响应中缺失这些字段,或类型不符(包括字段被显式设为 null 且非可空),SDK 会返回 *typesafe.APIResponseValidationError,并通过 FieldPath(如 answers.urgency.legend)精确标出出错位置。
  2. 答案集合默认容错:answers 字段是可选的,默认为空 Map。
  3. 前向兼容与未知类型过滤:若未来服务端引入了除 noul、choice、score、box 之外的新答案类型,旧版 SDK 不会发生解码崩溃,而是将未知类型的答案从类型化访问器中过滤并输出 Warn 级别日志;该原始数据依然可以通过 response.RawBody() 获取。
  4. 拒绝静默类型回退:SDK 绝不会将损坏或缺失的数字静默反序列化为 0 或空字符串,防止业务逻辑产生致命误判(例如将缺失的概率当作“确定为 0”)。任何数据异常均会显式抛出校验错误:
_, err := client.SystemOne(ctx, state, questions)
var validationErr *typesafe.APIResponseValidationError
if errors.As(err, &validationErr) {
	log.Printf("响应字段异常: %s", validationErr.FieldPath)
}

HTTP 元数据

// 提取请求追踪 ID
requestID := response.RawRequestID()   // 若标头不存在则返回 ""
requestID, err = response.RequestID() // 若标头不存在则返回显式 error

// 获取底层网络响应信息
rawHTTP, err := response.RawHTTPResponse() // *http.Response
rawBytes := response.RawBody()             // 服务端返回的原始字节流

response.MarshalJSON() 只会重新序列化 API 业务负载(model、usage 和 answers),底层 HTTP 网络标头和内部元数据绝不会泄露到序列化输出中。

Clone this wiki locally