Skip to content

Questions

sungaowei edited this page Oct 16, 2026 · 2 revisions

问题原语 (Questions)

English Version | 简体中文


TypeSafe 支持四种确定性原子问题原语:Noul(二元)、Choice(多分类)、Score(序数评分)和 Box(目标定位)。

所有问题均接受 instructions(指示模型应该判定或寻找的内容)——可以是字符串、JSON 对象或数组,并且均输出可供业务代码直接进行阈值门禁的概率分布或坐标。

在调用时,问题以 Map 形式组织(typesafe.Questions),因为问题的键名由调用方自由决定:这些键名用于在响应中提取对应答案,不能硬编码为结构体字段。Map 的值类型限定为 typesafe.Question 接口,若传入非法类型将在编译阶段报错。若需要使用 SDK 尚未建模的扩展字段,可使用 typesafe.RawQuestion。如果调用方持有无类型的 map[string]any,可直接传给客户端;SystemOne 内部会调用 typesafe.NormalizeQuestions 在运行时校验并规范化。


Noul — 二元 Yes/No 判断

返回一个命题为真(Yes/True)的校准概率,取值区间为 [0, 1]。

  • 接近 1 表示肯定或为真;
  • 接近 0 表示否定或为假;
  • 接近 0.5 表示内容信息不足或无法裁决。
// 基础用法:仅传入问题指令
typesafe.NewNoul("该内容是否包含垃圾营销广告?")

// 高级用法:传入明确的 True / False 判定准则
typesafe.NewNoul("该内容是否为垃圾营销?", typesafe.WithNoulCriteria(typesafe.NoulCriteria{
	True:  "未经请求的促销、诈骗或钓鱼信息",
	False: "用户之间正常的业务或技术沟通",
}))

NewNoul(instructions any, opts ...QuestionOption) *NoulQuestion:

  • instructions 可以是字符串、Map 或切片;当仅凭准则即可充分描述问题时,也可以传空字符串 ""。
  • 判定准则形式自由:可直接使用简要字符串,或在需要提供样例时传入结构化对象:
typesafe.NewNoul("", typesafe.WithNoulCriteria(typesafe.NoulCriteria{
	True: map[string]any{
		"meaning": "涉及支付、扣费或发票问题",
		"examples": []any{"扣了两次款", "申请退款", "开具发票"},
	},
}))

在业务逻辑中根据所需严格程度设置概率阈值:

if response.Nouls()["is_spam"].Noul > 0.90 {
	quarantineMessage(msg)
}

Choice — 互斥多分类

返回最匹配的选项标签(Choice)、模型对其的置信度(Confidence)以及每个备选项的完整概率分布(Probabilities)。 当备选项提前已知且属于互斥单选(单选一)时,使用 Choice。

typesafe.NewChoice(
	map[string]any{
		"billing":   "扣费、退款或发票申请",
		"technical": "系统故障、崩溃或 API 错误",
		"account":   "登录、权限或密码重置",
		"other":     nil, // nil 表示该选项名称已具备足够描述,无需额外说明
	},
	typesafe.WithInstructions("该工单应分流至哪个部门?"),
)

NewChoice(criteria map[string]any, opts ...QuestionOption) *ChoiceQuestion:

  • criteria 中的每个键为选项名称,值为该选项的判定准则(字符串、结构化对象或 nil)。
  • 最多支持 255 个选项。
  • 若 criteria 为空,SDK 会在发起网络请求前直接报错拦截。
answer := response.Choices()["category"]
fmt.Println(answer.Choice)         // "billing"
fmt.Println(answer.Confidence)     // 0.87
fmt.Println(answer.Probabilities)  // map[billing:0.87 technical:0.09 account:0.02 other:0.02]

Score — 序数评分准则

返回一个按照有序阶梯评分准则(从 0 级开始)计算得出的期望加权分值。 适用于评定优先级、质量、紧急程度或风险等级等“程度深浅”重于“所属类别”的场景。

typesafe.NewScore(
	[]any{"日常咨询", "中等重要(48小时内)", "紧急事件(立即响应)"},
	typesafe.WithInstructions("评估该技术故障的严重程度"),
)

NewScore(criteria []any, opts ...QuestionOption) *ScoreQuestion:

  • criteria 是按严重度或等级从小到大排列的切片,级数必须在 2 至 10 级 之间。
  • 返回的 Score 是各等级概率加权的数学期望,因此通常是带小数的值(例如 1.7 介于等级 1 与等级 2 之间)。
  • 答案中还包含 Confidence(置信度)、Legend(等级图例字典)和 Probabilities(每个整数级别的概率)。
  • 若评分准则少于 2 级或为空,将在客户端校验时触发 *typesafe.ScoreError。
answer := response.Scores()["urgency"]
fmt.Println(answer.Score)            // 1.7
fmt.Println(answer.Confidence)       // 0.85
fmt.Println(answer.Legend[2])        // "紧急事件(立即响应)"
fmt.Println(answer.Probabilities[2]) // 0.75

Box — 图像目标定位

在图像中检测并定位特定目标物体,返回物体的归一化边界框坐标(BoxCoordinates)。

注意:使用 Box 问题时,请求必须开启图片能力(通过 WithImages(true) 或 WithCallImages(true) 附带 x-typesafe-images: true 标头),且需指定兼容多模态定位的模型(如 jev-preview)。

typesafe.NewBox("定位图片中的咖啡杯")
typesafe.NewBox("state.photo 中佩戴眼镜的人物面部")

NewBox(instructions any, opts ...QuestionOption) *BoxQuestion:

  • instructions 描述需要在图像中定位的目标物体。
  • Box 问题不接受 criteria 判定准则(因为定位属于连续空间坐标回归,而非离散选项)。
  • 答案包含归一化边界框([0, 1] 范围):
    • Top:上边界距离图像顶部比例;
    • Bottom:下边界距离图像顶部比例;
    • Left:左边界距离图像左侧比例;
    • Right:右边界距离图像左侧比例;
    • Confidence:可选的模型置信度。
answer := response.Boxes()["cup_box"]
fmt.Printf("Top=%.2f, Bottom=%.2f, Left=%.2f, Right=%.2f\n",
	answer.Box.Top, answer.Box.Bottom, answer.Box.Left, answer.Box.Right)

问题配置选项 (QuestionOption)

选项 作用
WithInstructions(any) 设置或覆盖问题指令。可以是字符串、JSON 对象或数组。
WithNoulCriteria(NoulCriteria) 设置 Noul 问题的 Yes (True) 与 No (False) 详细准则。
WithQuestionField(key string, value any) 为请求体的问题字典添加任意未建模的底层自定义字段。若与现有字段重名则直接覆盖。

若 instructions 为 nil 或空字符串,序列化时不会输出该字段;若传入结构化对象(即便为空对象或空切片),SDK 会严格按原样序列化输出。


自定义原始问题 (RawQuestion)

对于未来新版本 API 引入的、当前 SDK 尚未提供类型化封装的问题结构,可以使用 RawQuestion 直接以普通 Map 形式传递:

typesafe.Questions{
	"billing": typesafe.RawQuestion{
		"type":         "noul",
		"instructions": "Is this about billing?",
	},
	"segment": typesafe.RawQuestion{
		"type":       "choice",
		"criteria":   map[string]any{"enterprise": nil, "smb": nil},
		"weight":     3, // 假设未来服务端支持权重字段
	},
}

NormalizeQuestions(questions) 封装了与客户端完全一致的校验逻辑。它接受 Questions、map[string]Question、强类型 Map(如 map[string]*NoulQuestion)、map[string]any 或 RawQuestion,若传入空问题集则抛出 At least one question is required. 错误。


校验时机与防护

错误输入 捕获时机 报错形式
在 typesafe.Questions 中传入非合法问题值 编译阶段 Go 编译器类型不匹配
NewChoice 未提供任何选项(criteria 为空) 发送请求前 客户端返回错误,不产生网络调用
NewScore 评分阶梯少于 2 级或为空 发送请求前 *typesafe.ScoreError
map[string]any 中缺少必要字段 发送请求前 由 NormalizeQuestions 校验拦截
服务端拒收的业务数据错误 服务端返回 映射为 HTTP 400 / 422 强类型错误

所有前端可判定的校验均在构建请求体前完成,任何非法的问题定义绝不会白白浪费网络带宽或 API 额度。

Clone this wiki locally