OpenAI 结构化模型输出
JSON是应用交换数据的常用格式。结构化输出(Structured Outputs)让模型遵循提供的JSON Schema,避免遗漏必需键或生成非法枚举。主要好处是可靠类型结构、可编程检测安全拒绝,以及无需强硬提示来维持格式。格式符合Schema不代表内容事实正确,仍需处理后文的拒绝、截断和内容错误。
REST支持JSON Schema;Python和JavaScript SDK分别可用pydantic.BaseModel与z.object定义对象,Ruby可用Sorbet T::Struct取得类型化解析结果。下面从“Alice和Bob星期五去科学展”抽取活动信息,name、date、participants分别为名称、日期和参与者;程序指令是“抽取活动信息”。
下列实现的结果读取方式不同:JavaScript与Python通过SDK的parse及output_parsed读取解析结果;Ruby检查状态与文本项后读取parsed。Go、Java、C#则提交Schema后直接输出文本,没有将其转换成活动类型对象。服务端遵循Schema与客户端完成类型化解析是两个步骤。
结构化模型输出(来源示例1,javascript)
// [中文] 定义活动名称、日期及参与者Schema,并要求从Alice/Bob科学展文本抽取信息。
// [中文] 使用Zod定义Schema并调用responses.parse,从output_parsed读取已解析的活动结果。
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI();
const CalendarEvent = z.object({
name: z.string(),
date: z.string(),
participants: z.array(z.string()),
});
const response = await openai.responses.parse({
model: "gpt-6-astra",
input: [
{ role: "system", content: "Extract the event information." },
{
role: "user",
content: "Alice and Bob are going to a science fair on Friday.",
},
],
text: {
format: zodTextFormat(CalendarEvent, "event"),
},
});
const event = response.output_parsed;
结构化模型输出(来源示例2,python)
## [中文] 定义活动名称、日期及参与者Schema,并要求从Alice/Bob科学展文本抽取信息。
## [中文] 使用Pydantic定义Schema并调用responses.parse,从output_parsed读取已解析的活动结果。
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
response = client.responses.parse(
model="gpt-6-astra",
input=[
{"role": "system", "content": "Extract the event information."},
{
"role": "user",
"content": "Alice and Bob are going to a science fair on Friday.",
},
],
text_format=CalendarEvent,
)
event = response.output_parsed
结构化模型输出(来源示例3,go)
// [中文] 定义活动名称、日期及参与者Schema,并要求从Alice/Bob科学展文本抽取信息。
// [中文] 手写JSON Schema约束服务端输出,再用OutputText输出文本;本段没有把文本解析成Go活动对象。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
schema := map[string]any{
"type": "object",
"properties": map[string]any{
"name": map[string]any{"type": "string"},
"date": map[string]any{"type": "string"},
"participants": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
},
"required": []string{"name", "date", "participants"},
"additionalProperties": false,
}
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Extract the event information.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Alice and Bob are going to a science fair on Friday.")},
responses.EasyInputMessageRoleUser,
),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "event", Schema: schema, Strict: openai.Bool(true)},
}},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
结构化模型输出(来源示例4,java)
// [中文] 定义活动名称、日期及参与者Schema,并要求从Alice/Bob科学展文本抽取信息。
// [中文] 提交JSON Schema后遍历消息中的outputText并打印;本段没有解析为Java活动对象。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
Map.of(
"name", Map.of("type", "string"),
"date", Map.of("type", "string"),
"participants", Map.of("type", "array", "items", Map.of("type", "string"))),
"required",
List.of("name", "date", "participants"),
"additionalProperties",
false);
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content("Extract the event information.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("Alice and Bob are going to a science fair on Friday.")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("event")
.strict(true)
.schema(
JsonValue.from(schema)
.convert(ResponseFormatTextJsonSchemaConfig.Schema.class))
.build())
.build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
结构化模型输出(来源示例5,csharp)
// [中文] 定义活动名称、日期及参与者Schema,并要求从Alice/Bob科学展文本抽取信息。
// [中文] 提交JSON Schema后用GetOutputText读取并打印文本;本段没有将文本反序列化为C#活动对象。
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"name": { "type": "string" },
"date": { "type": "string" },
"participants": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["name", "date", "participants"],
"additionalProperties": false
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"event",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(
ResponseItem.CreateSystemMessageItem("Extract the event information.")
);
options.InputItems.Add(
ResponseItem.CreateUserMessageItem(
"Alice and Bob are going to a science fair on Friday."
)
);
ResponseResult response = await client.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
结构化模型输出(来源示例6,ruby)
## [中文] 定义活动名称、日期及参与者Schema,并要求从Alice/Bob科学展文本抽取信息。
## [中文] 用Sorbet结构定义输出,检查完成状态及文本项存在后,读取parsed并转换为CalendarEvent。
## gem install openai sorbet-runtime
require "openai"
require "openai/helpers/sorbet"
class CalendarEvent < T::Struct
const :name, String
const :date, String
const :participants, T::Array[String]
end
client = OpenAI::Client.new
schema = OpenAI::StructuredOutput.from_sorbet(CalendarEvent)
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "Extract the event information."
},
{
role: :user,
content: "Alice and Bob are going to a science fair on Friday."
}
],
text: schema
)
raise "Response ended with status: #{response.status}" unless response.status == OpenAI::Responses::ResponseStatus::COMPLETED
message = response.output.grep(OpenAI::Responses::ResponseOutputMessage).fetch(0)
output_text = message.content.grep(OpenAI::Responses::ResponseOutputText).first
raise "No structured output returned (the model may have refused)" unless output_text
event = T.cast(output_text.parsed, CalendarEvent)
puts(event.name, event.date, event.participants.join(", "))
<a id="supported-models"></a>
支持模型
从GPT-4o起的较新模型支持结构化输出,新项目可从gpt-6-astra开始;来源以gpt-4-turbo等较早模型说明JSON模式的历史兼容范围。
生命周期补注(2026年10月23日核对):官方弃用记录将gpt-4-turbo、gpt-4-turbo-2024-04-09及gpt-4-turbo-completions的关闭日期列为2026年10月23日。下表中的GPT-3.5和GPT-4名称用于忠实呈现来源的历史兼容说明,不是当前可调用模型推荐;gpt-3.5-turbo-0125与gpt-4-0613也在该日期关闭列表中。GPT-4o和GPT-4o-mini的具体模型、快照还需核对2027年1月14日关闭计划。保留示例中的原模型ID,不等于已验证账户可调用。
<a id="when-to-use-structured-outputs-via-function-calling-vs-via-textformat"></a>
函数调用与text.format如何选择
结构化输出有两种形式:使用函数调用,或使用json_schema响应格式。模型需要连接系统功能,例如查数据库协助订单、操作UI时,使用函数调用;要让回复用户的内容遵循特定结构,例如数学教学界面分开展示步骤和答案时,使用结构化text.format。本页后续针对Responses非函数调用,函数严格模式见函数指南。其他端点文档可能用response_format命名,不能原样当作Responses字段。
<a id="structured-outputs-vs-json-mode"></a>
与JSON模式的区别
两者都能生成有效JSON,只有结构化输出保证符合支持的Schema。文档列出Responses、Chat Completions、Assistants、Fine-tuning和Batch支持这两类用法,具体仍须核对端点、模型及生命周期;不是说各端点请求字段相同。能用时优先结构化输出。json_schema支持始于gpt-4o-mini、gpt-4o-mini-2024-07-18、gpt-4o-2024-08-06及后续快照。
| 项目 | 结构化输出 | JSON模式 |
|---|---|---|
| 有效JSON | 是 | 是 |
| 符合Schema | 是,限支持子集 | 不保证 |
| 来源列举的兼容范围(含历史模型) | gpt-4o-mini、gpt-4o-2024-08-06及以后 | gpt-3.5-turbo、gpt-4-、gpt-4o-及兼容GPT-5模型 |
| Responses启用 | text.format的type为json_schema,指定strict:true与schema |
type为json_object |
<a id="examples"></a>
示例
<a id="chain-of-thought"></a>
逐步解题
要求以结构化步骤引导用户,不是读取模型隐藏内部推理。程序内指令译为“你是乐于助人的数学导师,逐步引导用户解决问题”,用户问如何解8x + 7 = -23。steps中包含每步explanation及output,最后给final_answer。
逐步解题(来源示例7,javascript)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI();
const Step = z.object({
explanation: z.string(),
output: z.string(),
});
const MathReasoning = z.object({
steps: z.array(Step),
final_answer: z.string(),
});
const response = await openai.responses.parse({
model: "gpt-6-astra",
input: [
{
role: "system",
content:
"You are a helpful math tutor. Guide the user through the solution step by step.",
},
{ role: "user", content: "how can I solve 8x + 7 = -23" },
],
text: {
format: zodTextFormat(MathReasoning, "math_reasoning"),
},
});
const math_reasoning = response.output_parsed;
逐步解题(来源示例8,python)
## [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
## [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
class Step(BaseModel):
explanation: str
output: str
class MathReasoning(BaseModel):
steps: list[Step]
final_answer: str
response = client.responses.parse(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "You are a helpful math tutor. Guide the user through the solution step by step.",
},
{"role": "user", "content": "how can I solve 8x + 7 = -23"},
],
text_format=MathReasoning,
)
math_reasoning = response.output_parsed
逐步解题(来源示例9,go)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
step := map[string]any{
"type": "object",
"properties": map[string]any{
"explanation": map[string]any{"type": "string"},
"output": map[string]any{"type": "string"},
},
"required": []string{"explanation", "output"},
"additionalProperties": false,
}
schema := map[string]any{
"type": "object",
"properties": map[string]any{
"steps": map[string]any{"type": "array", "items": step},
"final_answer": map[string]any{"type": "string"},
},
"required": []string{"steps", "final_answer"},
"additionalProperties": false,
}
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},
responses.EasyInputMessageRoleUser,
),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_reasoning", Schema: schema, Strict: openai.Bool(true)},
}},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
逐步解题(来源示例10,java)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps",
Map.of(
"type",
"array",
"items",
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false)),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("How can I solve 8x + 7 = -23?")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("math_reasoning")
.strict(true)
.schema(
JsonValue.from(schema)
.convert(ResponseFormatTextJsonSchemaConfig.Schema.class))
.build())
.build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
逐步解题(来源示例11,csharp)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
using System.Text.Json;
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));
options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));
ResponseResult response = await client.CreateResponseAsync(options);
using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());
Console.WriteLine(parsed.RootElement);
逐步解题(来源示例12,ruby)
## [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
## [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
require "openai"
client = OpenAI::Client.new
step_schema = {
type: :object,
properties: {
explanation: { type: :string },
output: { type: :string }
},
required: %w[explanation output],
additionalProperties: false
}
math_schema = {
type: :object,
properties: {
steps: {
type: :array,
items: step_schema
},
final_answer: { type: :string }
},
required: %w[steps final_answer],
additionalProperties: false
}
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "You are a helpful math tutor. Guide the user through the solution step by step."
},
{
role: :user,
content: "How can I solve 8x + 7 = -23?"
}
],
text: {
format: {
type: :json_schema,
name: "math_reasoning",
strict: true,
schema: math_schema
}
}
)
puts(response.output_text)
逐步解题(来源示例13,bash)
## [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
## [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"input": [
{
"role": "system",
"content": "You are a helpful math tutor. Guide the user through the solution step by step."
},
{
"role": "user",
"content": "how can I solve 8x + 7 = -23"
}
],
"text": {
"format": {
"type": "json_schema",
"name": "math_reasoning",
"schema": {
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
},
"strict": true
}
}
}'
<a id="example-response"></a>
响应示例
响应示例(来源示例14,json)
{
"steps": [
{
"explanation": "Start with the equation 8x + 7 = -23.",
"output": "8x + 7 = -23"
},
{
"explanation": "Subtract 7 from both sides to isolate the term with the variable.",
"output": "8x = -23 - 7"
},
{
"explanation": "Simplify the right side of the equation.",
"output": "8x = -30"
},
{
"explanation": "Divide both sides by 8 to solve for x.",
"output": "x = -30 / 8"
},
{
"explanation": "Simplify the fraction.",
"output": "x = -15 / 4"
}
],
"final_answer": "x = -15 / 4"
}
steps.explanation按顺序完整译为:
- 从方程
8x + 7 = -23开始。 - 等式两边同时减去7,将含变量的项单独留在一边。
- 化简等式右边。
- 等式两边同时除以8,解出x。
- 将分数约分。
对应output依次为8x + 7 = -23、8x = -23 - 7、8x = -30、x = -30 / 8、x = -15 / 4;最终答案final_answer为x = -15 / 4。
<a id="structured-data-extraction"></a>
结构化数据抽取
可定义从论文等非结构化文本抽取的字段。原任务译为“你是结构化抽取专家,将给定论文非结构化文字转换为指定结构”,字段为标题、作者、摘要、关键词。来源各语言的输入并不完全相同:JavaScript和cURL正文使用占位...;Python、Go、Java、C#、Ruby则给出Transformer论文文字。后者完整译为:“《Attention Is All You Need》(《注意力就是你所需要的一切》),作者为Ashish Vaswani、Noam Shazeer、Niki Parmar、Jakob Uszkoreit、Llion Jones、Aidan N. Gomez、Łukasz Kaiser及Illia Polosukhin。我们提出Transformer,一种完全基于注意力机制的序列转换架构。关键词:Transformer、注意力、序列转换。”C#任务明确要求抽取标题、作者、摘要及关键词,Ruby任务要求从所提供论文文本抽取结构化数据。
结构化数据抽取(来源示例15,javascript)
// [中文] 定义title、authors、abstract、keywords,要求把论文文本抽取为这些字段。
// [中文] 按该语言来源实际输入发送请求;占位文本与Transformer文本不是同一份论文输入。
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI();
const ResearchPaperExtraction = z.object({
title: z.string(),
authors: z.array(z.string()),
abstract: z.string(),
keywords: z.array(z.string()),
});
const response = await openai.responses.parse({
model: "gpt-6-astra",
input: [
{
role: "system",
content:
"You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure.",
},
{ role: "user", content: "..." },
],
text: {
format: zodTextFormat(ResearchPaperExtraction, "research_paper_extraction"),
},
});
const research_paper = response.output_parsed;
结构化数据抽取(来源示例16,python)
## [中文] 定义title、authors、abstract、keywords,要求把论文文本抽取为这些字段。
## [中文] 按该语言来源实际输入发送请求;占位文本与Transformer文本不是同一份论文输入。
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
class ResearchPaperExtraction(BaseModel):
title: str
authors: list[str]
abstract: str
keywords: list[str]
response = client.responses.parse(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure.",
},
{
"role": "user",
"content": (
"Attention Is All You Need by Ashish Vaswani, Noam Shazeer, "
"Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, "
"Łukasz Kaiser, and Illia Polosukhin. We propose the "
"Transformer, a sequence transduction architecture based "
"entirely on attention. Keywords: transformers, attention, "
"sequence transduction."
),
},
],
text_format=ResearchPaperExtraction,
)
research_paper = response.output_parsed
结构化数据抽取(来源示例17,go)
// [中文] 定义title、authors、abstract、keywords,要求把论文文本抽取为这些字段。
// [中文] 按该语言来源实际输入发送请求;占位文本与Transformer文本不是同一份论文输入。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
const researchPaperText = "Attention Is All You Need by Ashish Vaswani, Noam Shazeer, " +
"Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, " +
"Łukasz Kaiser, and Illia Polosukhin. We propose the Transformer, " +
"a sequence transduction architecture based entirely on attention. " +
"Keywords: transformers, attention, sequence transduction."
func main() {
client := openai.NewClient()
schema := map[string]any{
"type": "object",
"properties": map[string]any{
"title": map[string]any{"type": "string"},
"authors": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
"abstract": map[string]any{"type": "string"},
"keywords": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
},
"required": []string{"title", "authors", "abstract", "keywords"},
"additionalProperties": false,
}
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText(researchPaperText)},
responses.EasyInputMessageRoleUser,
),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "research_paper_extraction", Schema: schema, Strict: openai.Bool(true)},
}},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
结构化数据抽取(来源示例18,java)
// [中文] 定义title、authors、abstract、keywords,要求把论文文本抽取为这些字段。
// [中文] 按该语言来源实际输入发送请求;占位文本与Transformer文本不是同一份论文输入。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
Map.of(
"title", Map.of("type", "string"),
"authors", Map.of("type", "array", "items", Map.of("type", "string")),
"abstract", Map.of("type", "string"),
"keywords", Map.of("type", "array", "items", Map.of("type", "string"))),
"required",
List.of("title", "authors", "abstract", "keywords"),
"additionalProperties",
false);
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content(
"You are an expert at structured data extraction. You will be given"
+ " unstructured text from a research paper and should convert"
+ " it into the given structure.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content(
"Attention Is All You Need by Ashish Vaswani, Noam Shazeer,"
+ " Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez,"
+ " Łukasz Kaiser, and Illia Polosukhin. We propose the"
+ " Transformer, a"
+ " sequence transduction architecture based entirely on"
+ " attention. Keywords: transformers, attention, sequence"
+ " transduction.")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("research_paper_extraction")
.strict(true)
.schema(
JsonValue.from(schema)
.convert(ResponseFormatTextJsonSchemaConfig.Schema.class))
.build())
.build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
结构化数据抽取(来源示例19,csharp)
// [中文] 定义title、authors、abstract、keywords,要求把论文文本抽取为这些字段。
// [中文] 按该语言来源实际输入发送请求;占位文本与Transformer文本不是同一份论文输入。
using System.Text.Json;
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"title": { "type": "string" },
"authors": { "type": "array", "items": { "type": "string" } },
"abstract": { "type": "string" },
"keywords": { "type": "array", "items": { "type": "string" } }
},
"required": ["title", "authors", "abstract", "keywords"],
"additionalProperties": false
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"research_paper",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("Extract the title, authors, abstract, and keywords from the research paper."));
options.InputItems.Add(
ResponseItem.CreateUserMessageItem(
"""
Attention Is All You Need by Ashish Vaswani, Noam Shazeer,
Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez,
Łukasz Kaiser, and Illia Polosukhin. We propose the
Transformer, a sequence transduction architecture based
entirely on attention. Keywords: transformers, attention,
sequence transduction.
"""
)
);
ResponseResult response = await client.CreateResponseAsync(options);
using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());
Console.WriteLine(parsed.RootElement);
结构化数据抽取(来源示例20,ruby)
## [中文] 定义title、authors、abstract、keywords,要求把论文文本抽取为这些字段。
## [中文] 按该语言来源实际输入发送请求;占位文本与Transformer文本不是同一份论文输入。
require "openai"
client = OpenAI::Client.new
research_paper = <<~TEXT
Attention Is All You Need by Ashish Vaswani, Noam Shazeer, Niki Parmar,
Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Łukasz Kaiser, and Illia
Polosukhin. We propose the Transformer, a sequence transduction architecture
based entirely on attention. Keywords: transformers, attention, sequence
transduction.
TEXT
paper_schema = {
type: :object,
properties: {
title: { type: :string },
authors: {
type: :array,
items: { type: :string }
},
abstract: { type: :string },
keywords: {
type: :array,
items: { type: :string }
}
},
required: %w[title authors abstract keywords],
additionalProperties: false
}
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "Extract structured data from the supplied research paper text."
},
{
role: :user,
content: research_paper
}
],
text: {
format: {
type: :json_schema,
name: "research_paper_extraction",
strict: true,
schema: paper_schema
}
}
)
puts(response.output_text)
结构化数据抽取(来源示例21,bash)
## [中文] 定义title、authors、abstract、keywords,要求把论文文本抽取为这些字段。
## [中文] 按该语言来源实际输入发送请求;占位文本与Transformer文本不是同一份论文输入。
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"input": [
{
"role": "system",
"content": "You are an expert at structured data extraction. You will be given unstructured text from a research paper and should convert it into the given structure."
},
{
"role": "user",
"content": "..."
}
],
"text": {
"format": {
"type": "json_schema",
"name": "research_paper_extraction",
"schema": {
"type": "object",
"properties": {
"title": { "type": "string" },
"authors": {
"type": "array",
"items": { "type": "string" }
},
"abstract": { "type": "string" },
"keywords": {
"type": "array",
"items": { "type": "string" }
}
},
"required": ["title", "authors", "abstract", "keywords"],
"additionalProperties": false
},
"strict": true
}
}
}'
<a id="example-response-1"></a>
响应示例
响应示例(来源示例22,json)
{
"title": "Application of Quantum Algorithms in Interstellar Navigation: A New Frontier",
"authors": ["Dr. Stella Voyager", "Dr. Nova Star", "Dr. Lyra Hunter"],
"abstract": "This paper investigates the utilization of quantum algorithms to improve interstellar navigation systems. By leveraging quantum superposition and entanglement, our proposed navigation system can calculate optimal travel paths through space-time anomalies more efficiently than classical methods. Experimental simulations suggest a significant reduction in travel time and fuel consumption for interstellar missions.",
"keywords": [
"Quantum algorithms",
"interstellar navigation",
"space-time anomalies",
"quantum superposition",
"quantum entanglement",
"space travel"
]
}
这份响应是来源提供的独立示意,标题与上面部分语言的Transformer论文输入不同,不能当作这些请求的对应抽取结果,也不作为真实科研结论。其自然语言内容完整译为:
title:“量子算法在星际导航中的应用:新前沿”。authors:Stella Voyager博士、Nova Star博士、Lyra Hunter博士(保留来源示例人名)。abstract:“本文研究利用量子算法改进星际导航系统。借助量子叠加与量子纠缠,我们提出的导航系统能够比经典方法更高效地计算穿越时空异常区域的最优航行路径。实验模拟表明,星际任务的航行时间和燃料消耗可显著减少。”keywords:量子算法、星际导航、时空异常、量子叠加、量子纠缠、太空旅行。
<a id="ui-generation"></a>
生成UI
用递归结构和枚举表示有效HTML。任务是“你是UI生成AI,把用户输入转换为UI”,用户要求“制作用户资料表单”。保留type、label、children、attributes等字段与枚举,不将数据直接当作已经安全渲染的界面。
UI字段与说明中文对照:type为UI组件类型;枚举div为通用容器、button为按钮、header为页头、section为区段、field为字段、form为表单。label是组件标签,用于按钮或表单字段;children是嵌套UI组件;attributes是适用于任意元素的组件属性条目;其中name为属性名,例如onClick或className,value为属性值。description中的“Dynamically generated UI”及其同义变体译为“动态生成的用户界面”。Java/Ruby任务“把用户请求转换为UI定义”、C#任务“把用户请求转换为组件树”与前述UI生成任务相对应。
生成UI(来源示例23,javascript)
// [中文] 使用递归组件树表示UI,type限定组件类型,children引用子组件结构。
// [中文] 请求用户资料表单并读取结构化定义;渲染时还需校验属性,不能直接信任任意生成内容。
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI();
const UI = z.lazy(() =>
z.object({
type: z.enum(["div", "button", "header", "section", "field", "form"]),
label: z.string(),
children: z.array(UI),
attributes: z.array(
z.object({
name: z.string(),
value: z.string(),
})
),
})
);
const response = await openai.responses.parse({
model: "gpt-6-astra",
input: [
{
role: "system",
content: "You are a UI generator AI. Convert the user input into a UI.",
},
{
role: "user",
content: "Make a User Profile Form",
},
],
text: {
format: zodTextFormat(UI, "ui"),
},
});
const ui = response.output_parsed;
生成UI(来源示例24,python)
## [中文] 使用递归组件树表示UI,type限定组件类型,children引用子组件结构。
## [中文] 请求用户资料表单并读取结构化定义;渲染时还需校验属性,不能直接信任任意生成内容。
from enum import Enum
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
class UIType(str, Enum):
div = "div"
button = "button"
header = "header"
section = "section"
field = "field"
form = "form"
class Attribute(BaseModel):
name: str
value: str
class UI(BaseModel):
type: UIType
label: str
children: list["UI"]
attributes: list[Attribute]
## [中文] 此调用用于启用递归类型。
UI.model_rebuild() # This is required to enable recursive types
class Response(BaseModel):
ui: UI
response = client.responses.parse(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "You are a UI generator AI. Convert the user input into a UI.",
},
{"role": "user", "content": "Make a User Profile Form"},
],
text_format=Response,
)
ui = response.output_parsed
生成UI(来源示例25,go)
// [中文] 使用递归组件树表示UI,type限定组件类型,children引用子组件结构。
// [中文] 请求用户资料表单并读取结构化定义;渲染时还需校验属性,不能直接信任任意生成内容。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
schema := map[string]any{
"type": "object",
"properties": map[string]any{
"type": map[string]any{"type": "string", "enum": []string{"div", "button", "header", "section", "field", "form"}},
"label": map[string]any{"type": "string"},
"children": map[string]any{"type": "array", "items": map[string]any{"$ref": "#"}},
"attributes": map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"name": map[string]any{"type": "string"}, "value": map[string]any{"type": "string"}}, "required": []string{"name", "value"}, "additionalProperties": false}},
},
"required": []string{"type", "label", "children", "attributes"},
"additionalProperties": false,
}
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a UI generator AI. Convert the user input into a UI.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Make a User Profile Form")},
responses.EasyInputMessageRoleUser,
),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "ui", Description: openai.String("Dynamically generated UI"), Schema: schema, Strict: openai.Bool(true)},
}},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
生成UI(来源示例26,java)
// [中文] 使用递归组件树表示UI,type限定组件类型,children引用子组件结构。
// [中文] 请求用户资料表单并读取结构化定义;渲染时还需校验属性,不能直接信任任意生成内容。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content("Convert the user request into a UI definition.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("Make a user profile form.")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("ui")
.description("A dynamically generated UI")
.strict(true)
.schema(
ResponseFormatTextJsonSchemaConfig.Schema.builder()
.putAdditionalProperty("type", JsonValue.from("object"))
.putAdditionalProperty(
"properties",
JsonValue.from(
Map.of(
"type",
Map.of(
"type",
"string",
"enum",
List.of(
"div", "button", "header", "section",
"field", "form")),
"label", Map.of("type", "string"),
"children",
Map.of(
"type",
"array",
"items",
Map.of("$ref", "#")),
"attributes",
Map.of(
"type",
"array",
"items",
Map.of(
"type",
"object",
"properties",
Map.of(
"name", Map.of("type", "string"),
"value", Map.of("type", "string")),
"required",
List.of("name", "value"),
"additionalProperties",
false)))))
.putAdditionalProperty(
"required",
JsonValue.from(
List.of("type", "label", "children", "attributes")))
.putAdditionalProperty(
"additionalProperties", JsonValue.from(false))
.build())
.build())
.build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
生成UI(来源示例27,csharp)
// [中文] 使用递归组件树表示UI,type限定组件类型,children引用子组件结构。
// [中文] 请求用户资料表单并读取结构化定义;渲染时还需校验属性,不能直接信任任意生成内容。
using System.Text.Json;
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"ui": { "$ref": "#/$defs/component" }
},
"required": ["ui"],
"additionalProperties": false,
"$defs": {
"component": {
"type": "object",
"properties": {
"type": { "type": "string", "enum": ["div", "button", "header", "section", "field", "form"] },
"label": { "type": "string" },
"children": { "type": "array", "items": { "$ref": "#/$defs/component" } },
"attributes": {
"type": "array",
"items": {
"type": "object",
"properties": { "name": { "type": "string" }, "value": { "type": "string" } },
"required": ["name", "value"],
"additionalProperties": false
}
}
},
"required": ["type", "label", "children", "attributes"],
"additionalProperties": false
}
}
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"ui",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a UI generator. Convert the user request into a component tree."));
options.InputItems.Add(ResponseItem.CreateUserMessageItem("Make a User Profile Form"));
ResponseResult response = await client.CreateResponseAsync(options);
using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());
Console.WriteLine(parsed.RootElement);
生成UI(来源示例28,ruby)
## [中文] 使用递归组件树表示UI,type限定组件类型,children引用子组件结构。
## [中文] 请求用户资料表单并读取结构化定义;渲染时还需校验属性,不能直接信任任意生成内容。
require "openai"
client = OpenAI::Client.new
ui_schema = {
type: :object,
properties: {
type: {
type: :string,
enum: %w[div button header section field form]
},
label: { type: :string },
children: {
type: :array,
items: { "$ref" => "#" }
},
attributes: {
type: :array,
items: {
type: :object,
properties: {
name: { type: :string },
value: { type: :string }
},
required: %w[name value],
additionalProperties: false
}
}
},
required: %w[type label children attributes],
additionalProperties: false
}
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "Convert the user request into a UI definition."
},
{
role: :user,
content: "Make a user profile form."
}
],
text: {
format: {
type: :json_schema,
name: "ui",
description: "A dynamically generated UI",
strict: true,
schema: ui_schema
}
}
)
puts(response.output_text)
生成UI(来源示例29,bash)
## [中文] 使用递归组件树表示UI,type限定组件类型,children引用子组件结构。
## [中文] 请求用户资料表单并读取结构化定义;渲染时还需校验属性,不能直接信任任意生成内容。
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"input": [
{
"role": "system",
"content": "You are a UI generator AI. Convert the user input into a UI."
},
{
"role": "user",
"content": "Make a User Profile Form"
}
],
"text": {
"format": {
"type": "json_schema",
"name": "ui",
"description": "Dynamically generated UI",
"schema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The type of the UI component",
"enum": ["div", "button", "header", "section", "field", "form"]
},
"label": {
"type": "string",
"description": "The label of the UI component, used for buttons or form fields"
},
"children": {
"type": "array",
"description": "Nested UI components",
"items": {"$ref": "#"}
},
"attributes": {
"type": "array",
"description": "Arbitrary attributes for the UI component, suitable for any element",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the attribute, for example onClick or className"
},
"value": {
"type": "string",
"description": "The value of the attribute"
}
},
"required": ["name", "value"],
"additionalProperties": false
}
}
},
"required": ["type", "label", "children", "attributes"],
"additionalProperties": false
},
"strict": true
}
}
}'
<a id="example-response-2"></a>
响应示例
响应示例(来源示例30,json)
{
"type": "form",
"label": "User Profile Form",
"children": [
{
"type": "div",
"label": "",
"children": [
{
"type": "field",
"label": "First Name",
"children": [],
"attributes": [
{
"name": "type",
"value": "text"
},
{
"name": "name",
"value": "firstName"
},
{
"name": "placeholder",
"value": "Enter your first name"
}
]
},
{
"type": "field",
"label": "Last Name",
"children": [],
"attributes": [
{
"name": "type",
"value": "text"
},
{
"name": "name",
"value": "lastName"
},
{
"name": "placeholder",
"value": "Enter your last name"
}
]
}
],
"attributes": []
},
{
"type": "button",
"label": "Submit",
"children": [],
"attributes": [
{
"name": "type",
"value": "submit"
}
]
}
],
"attributes": [
{
"name": "method",
"value": "post"
},
{
"name": "action",
"value": "/submit-profile"
}
]
}
界面文字逐项译为:User Profile Form为“用户资料表单”,First Name为“名”,Last Name为“姓”,Enter your first name为“请输入您的名”,Enter your last name为“请输入您的姓”,Submit为“提交”。空label仍为空;协议属性type=text、name=firstName/lastName保持原值,表单以method=post提交到示例路径/submit-profile,按钮type=submit表示提交按钮。
<a id="moderation"></a>
内容审核
多类别分类是常用审核方法。原任务是“判断用户输入是否违反指定指南,若违反则解释”,输入为“如何准备求职面试?”。字段is_violating判断违规,category为violence、sexual、self_harm或null,explanation_if_violating为解释或null。
description的中文含义为:此结构“判断内容是否违反具体审核规则”;is_violating“指示内容是否违反指南”;category“若违反指南,给出违规类型,否则为null”;explanation_if_violating“说明内容为什么违规,否则为null”。枚举violence、sexual、self_harm分别对应暴力、性内容、自我伤害,程序值不翻译。
内容审核(来源示例31,javascript)
// [中文] 以is_violating、category和explanation_if_violating表达审核结论及可空解释。
// [中文] 提交求职面试问题;category保留violence/sexual/self_harm等协议枚举。
import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI();
const ContentCompliance = z.object({
is_violating: z.boolean(),
category: z.enum(["violence", "sexual", "self_harm"]).nullable(),
explanation_if_violating: z.string().nullable(),
});
const response = await openai.responses.parse({
model: "gpt-6-astra",
input: [
{
role: "system",
content:
"Determine if the user input violates specific guidelines and explain if they do.",
},
{
role: "user",
content: "How do I prepare for a job interview?",
},
],
text: {
format: zodTextFormat(ContentCompliance, "content_compliance"),
},
});
const compliance = response.output_parsed;
内容审核(来源示例32,python)
## [中文] 以is_violating、category和explanation_if_violating表达审核结论及可空解释。
## [中文] 提交求职面试问题;category保留violence/sexual/self_harm等协议枚举。
from enum import Enum
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI()
class Category(str, Enum):
violence = "violence"
sexual = "sexual"
self_harm = "self_harm"
class ContentCompliance(BaseModel):
is_violating: bool
category: Category | None
explanation_if_violating: str | None
response = client.responses.parse(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "Determine if the user input violates specific guidelines and explain if they do.",
},
{"role": "user", "content": "How do I prepare for a job interview?"},
],
text_format=ContentCompliance,
)
compliance = response.output_parsed
内容审核(来源示例33,go)
// [中文] 以is_violating、category和explanation_if_violating表达审核结论及可空解释。
// [中文] 提交求职面试问题;category保留violence/sexual/self_harm等协议枚举。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
schema := contentComplianceSchema()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage("Determine if the user input violates specific guidelines and explain if they do.", responses.EasyInputMessageRoleSystem),
responses.ResponseInputItemParamOfMessage("How do I prepare for a job interview?", responses.EasyInputMessageRoleUser),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{
Name: "content_compliance", Description: openai.String("Determines if content is violating specific moderation rules"), Schema: schema, Strict: openai.Bool(true),
},
}},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
func contentComplianceSchema() map[string]any {
return map[string]any{
"type": "object",
"properties": map[string]any{
"is_violating": map[string]any{"type": "boolean", "description": "Indicates if the content is violating guidelines"},
"category": map[string]any{"type": []string{"string", "null"}, "description": "Type of violation, if the content is violating guidelines. Null otherwise.", "enum": []any{"violence", "sexual", "self_harm", nil}},
"explanation_if_violating": map[string]any{"type": []string{"string", "null"}, "description": "Explanation of why the content is violating"},
},
"required": []string{"is_violating", "category", "explanation_if_violating"},
"additionalProperties": false,
}
}
内容审核(来源示例34,java)
// [中文] 以is_violating、category和explanation_if_violating表达审核结论及可空解释。
// [中文] 提交求职面试问题;category保留violence/sexual/self_harm等协议枚举。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseTextConfig;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
Map.of(
"is_violating",
Map.of(
"type", "boolean",
"description", "Whether the content violates the guidelines"),
"category",
Map.of(
"type", List.of("string", "null"),
"enum", Arrays.asList("violence", "sexual", "self_harm", null),
"description", "The violation category, or null when content is allowed"),
"explanation_if_violating",
Map.of(
"type",
List.of("string", "null"),
"description",
"Why the content violates the guidelines, or null")),
"required",
List.of("is_violating", "category", "explanation_if_violating"),
"additionalProperties",
false);
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content(
"Determine whether the user input violates the guidelines and explain any violation.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("How do I prepare for a job interview?")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("content_compliance")
.description("Determines whether content violates moderation rules")
.strict(true)
.schema(
JsonValue.from(schema)
.convert(ResponseFormatTextJsonSchemaConfig.Schema.class))
.build())
.build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
内容审核(来源示例35,csharp)
// [中文] 以is_violating、category和explanation_if_violating表达审核结论及可空解释。
// [中文] 提交求职面试问题;category保留violence/sexual/self_harm等协议枚举。
using System.Text.Json;
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"is_violating": { "type": "boolean" },
"category": {
"type": ["string", "null"],
"enum": ["violence", "sexual", "self_harm", null]
},
"explanation_if_violating": { "type": ["string", "null"] }
},
"required": ["is_violating", "category", "explanation_if_violating"],
"additionalProperties": false
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"content_compliance",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("Determine whether the user input violates content guidelines."));
options.InputItems.Add(ResponseItem.CreateUserMessageItem("How do I prepare for a job interview?"));
ResponseResult response = await client.CreateResponseAsync(options);
using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());
Console.WriteLine(parsed.RootElement);
内容审核(来源示例36,ruby)
## [中文] 以is_violating、category和explanation_if_violating表达审核结论及可空解释。
## [中文] 提交求职面试问题;category保留violence/sexual/self_harm等协议枚举。
require "openai"
client = OpenAI::Client.new
compliance_schema = {
type: :object,
properties: {
is_violating: {
type: :boolean,
description: "Whether the content violates the guidelines"
},
category: {
type: %i[string null],
enum: ["violence", "sexual", "self_harm", nil],
description: "The violation category, or null when the content is allowed"
},
explanation_if_violating: {
type: %i[string null],
description: "Why the content violates the guidelines, or null"
}
},
required: %w[is_violating category explanation_if_violating],
additionalProperties: false
}
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "Determine whether the user input violates the guidelines and explain any violation."
},
{
role: :user,
content: "How do I prepare for a job interview?"
}
],
text: {
format: {
type: :json_schema,
name: "content_compliance",
description: "Determines whether content violates moderation rules",
strict: true,
schema: compliance_schema
}
}
)
puts(response.output_text)
内容审核(来源示例37,bash)
## [中文] 以is_violating、category和explanation_if_violating表达审核结论及可空解释。
## [中文] 提交求职面试问题;category保留violence/sexual/self_harm等协议枚举。
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"input": [
{
"role": "system",
"content": "Determine if the user input violates specific guidelines and explain if they do."
},
{
"role": "user",
"content": "How do I prepare for a job interview?"
}
],
"text": {
"format": {
"type": "json_schema",
"name": "content_compliance",
"description": "Determines if content is violating specific moderation rules",
"schema": {
"type": "object",
"properties": {
"is_violating": {
"type": "boolean",
"description": "Indicates if the content is violating guidelines"
},
"category": {
"type": ["string", "null"],
"description": "Type of violation, if the content is violating guidelines. Null otherwise.",
"enum": ["violence", "sexual", "self_harm"]
},
"explanation_if_violating": {
"type": ["string", "null"],
"description": "Explanation of why the content is violating"
}
},
"required": ["is_violating", "category", "explanation_if_violating"],
"additionalProperties": false
},
"strict": true
}
}
}'
<a id="example-response-3"></a>
响应示例
响应示例(来源示例38,json)
{
"is_violating": false,
"category": null,
"explanation_if_violating": null
}
该响应表示“未违反指南”,因此违规类别与违规解释都为null;false和null保持JSON字面值。
<a id="step-1-define-your-schema"></a>
第一步:定义Schema
设计模型必须遵循的JSON Schema,参考上例。出于性能或技术原因,并非全部JSON Schema特性可用,见支持子集。
<a id="tips-for-your-json-schema"></a>
Schema设计建议
键名清楚直观;重要键提供明确标题和说明;用评测确定最适合用例的结构。
<a id="step-2-supply-your-schema-in-the-api-call"></a>
第二步:在API调用中提供Schema
按下列结构设置:
第二步:在API调用中提供Schema(来源示例39,json)
此处沿用来源的JSON结构片段或响应示意,不是可独立解析的完整JSON载荷。
text: { format: { type: "json_schema", "strict": true, "schema": … } }
完整请求:
第二步:在API调用中提供Schema(来源示例40,javascript)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
const response = await openai.responses.create({
model: "gpt-6-astra",
input: [
{
role: "system",
content:
"You are a helpful math tutor. Guide the user through the solution step by step.",
},
{ role: "user", content: "how can I solve 8x + 7 = -23" },
],
text: {
format: {
type: "json_schema",
name: "math_response",
schema: {
type: "object",
properties: {
steps: {
type: "array",
items: {
type: "object",
properties: {
explanation: { type: "string" },
output: { type: "string" },
},
required: ["explanation", "output"],
additionalProperties: false,
},
},
final_answer: { type: "string" },
},
required: ["steps", "final_answer"],
additionalProperties: false,
},
strict: true,
},
},
});
console.log(response.output_text);
第二步:在API调用中提供Schema(来源示例41,python)
## [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
## [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
response = client.responses.create(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "You are a helpful math tutor. Guide the user through the solution step by step.",
},
{"role": "user", "content": "how can I solve 8x + 7 = -23"},
],
text={
"format": {
"type": "json_schema",
"name": "math_response",
"schema": {
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": {"type": "string"},
"output": {"type": "string"},
},
"required": ["explanation", "output"],
"additionalProperties": False,
},
},
"final_answer": {"type": "string"},
},
"required": ["steps", "final_answer"],
"additionalProperties": False,
},
"strict": True,
},
},
)
print(response.output_text)
第二步:在API调用中提供Schema(来源示例42,go)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},
responses.EasyInputMessageRoleUser,
),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true)},
}},
})
if err != nil {
panic(err)
}
fmt.Println(response.OutputText())
}
func mathSchema() map[string]any {
return map[string]any{
"type": "object",
"properties": map[string]any{
"steps": map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"explanation": map[string]any{"type": "string"}, "output": map[string]any{"type": "string"}}, "required": []string{"explanation", "output"}, "additionalProperties": false}},
"final_answer": map[string]any{"type": "string"},
},
"required": []string{"steps", "final_answer"},
"additionalProperties": false,
}
}
第二步:在API调用中提供Schema(来源示例43,java)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps",
Map.of(
"type",
"array",
"items",
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false)),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("How can I solve 8x + 7 = -23?")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("math_response")
.strict(true)
.schema(
JsonValue.from(schema)
.convert(ResponseFormatTextJsonSchemaConfig.Schema.class))
.build())
.build())
.build();
client.responses().create(params).output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));
第二步:在API调用中提供Schema(来源示例44,csharp)
// [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
// [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
using System.Text.Json;
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));
options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));
ResponseResult response = await client.CreateResponseAsync(options);
using JsonDocument parsed = JsonDocument.Parse(response.GetOutputText());
Console.WriteLine(parsed.RootElement);
第二步:在API调用中提供Schema(来源示例45,ruby)
## [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
## [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
require "openai"
client = OpenAI::Client.new
math_schema = {
type: :object,
properties: {
steps: {
type: :array,
items: {
type: :object,
properties: {
explanation: { type: :string },
output: { type: :string }
},
required: %w[explanation output],
additionalProperties: false
}
},
final_answer: { type: :string }
},
required: %w[steps final_answer],
additionalProperties: false
}
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "You are a helpful math tutor. Guide the user through the solution step by step."
},
{
role: :user,
content: "How can I solve 8x + 7 = -23?"
}
],
text: {
format: {
type: :json_schema,
name: "math_response",
strict: true,
schema: math_schema
}
}
)
puts(response.output_text)
第二步:在API调用中提供Schema(来源示例46,bash)
## [中文] 以steps数组和final_answer定义数学解题Schema,每步含explanation与output。
## [中文] 向Responses提交方程及Schema;SDK原生类型辅助或text.format约束响应,再读取结果。
curl https://api.openai.com/v1/responses \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"input": [
{
"role": "system",
"content": "You are a helpful math tutor. Guide the user through the solution step by step."
},
{
"role": "user",
"content": "how can I solve 8x + 7 = -23"
}
],
"text": {
"format": {
"type": "json_schema",
"name": "math_response",
"schema": {
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
},
"strict": true
}
}
}'
首次使用某Schema时,API处理Schema会增加延迟;后续相同Schema不再承担这部分额外延迟。
<a id="step-3-handle-edge-cases"></a>
第三步:处理边界情况
安全拒绝或达到最大词元限制导致截断时,模型可能不给出符合Schema的完整响应。下面分别检查未完成状态和拒绝,不能只假设解析成功。
错误消息的中文对照:Incomplete response及其大小写变体为“响应不完整”;No response content为“没有响应内容”;No response message为“没有响应消息”;The structured response was incomplete.为“结构化响应不完整”;The structured response was interrupted by the content filter.为“结构化响应被内容过滤中断”;The response did not include an output message/content.分别为“响应不包含输出消息/输出内容”。这些是程序抛出的诊断字符串,保留原文以便排错。
第三步:处理边界情况(来源示例47,javascript)
// [中文] 先检测未完成状态,再定位message与content,分别处理refusal和output_text。
// [中文] 缺少内容、词元截断、内容过滤及调用异常均需单独处理,不能直接把所有响应解析为业务JSON。
try {
const response = await openai.responses.create({
model: "gpt-6-astra",
input: [
{
role: "system",
content:
"You are a helpful math tutor. Guide the user through the solution step by step.",
},
{
role: "user",
content: "how can I solve 8x + 7 = -23",
},
],
max_output_tokens: 50,
text: {
format: {
type: "json_schema",
name: "math_response",
schema: {
type: "object",
properties: {
steps: {
type: "array",
items: {
type: "object",
properties: {
explanation: {
type: "string",
},
output: {
type: "string",
},
},
required: ["explanation", "output"],
additionalProperties: false,
},
},
final_answer: {
type: "string",
},
},
required: ["steps", "final_answer"],
additionalProperties: false,
},
strict: true,
},
},
});
if (
response.status === "incomplete" &&
response.incomplete_details.reason === "max_output_tokens"
) {
// [中文] 先处理模型没有返回完整响应的情况。
// Handle the case where the model did not return a complete response
throw new Error("Incomplete response");
}
const message = response.output.find((item) => item.type === "message");
const math_response = message?.content[0];
if (!math_response) {
throw new Error("No response content");
}
if (math_response.type === "refusal") {
// [中文] 单独处理安全拒绝,不能按正常业务结构解析。
// handle refusal
console.log(math_response.refusal);
} else if (math_response.type === "output_text") {
console.log(math_response.text);
} else {
throw new Error("No response content");
}
} catch (e) {
// [中文] 在此处理边界情况及异常。
// Handle edge cases
console.error(e);
}
第三步:处理边界情况(来源示例48,python)
## [中文] 先检测未完成状态,再定位message与content,分别处理refusal和output_text。
## [中文] 缺少内容、词元截断、内容过滤及调用异常均需单独处理,不能直接把所有响应解析为业务JSON。
try:
response = client.responses.create(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "You are a helpful math tutor. Guide the user through the solution step by step.",
},
{"role": "user", "content": "how can I solve 8x + 7 = -23"},
],
text={
"format": {
"type": "json_schema",
"name": "math_response",
"strict": True,
"schema": {
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": {"type": "string"},
"output": {"type": "string"},
},
"required": ["explanation", "output"],
"additionalProperties": False,
},
},
"final_answer": {"type": "string"},
},
"required": ["steps", "final_answer"],
"additionalProperties": False,
},
},
},
max_output_tokens=50,
)
if (
response.status == "incomplete"
and response.incomplete_details.reason == "max_output_tokens"
):
raise Exception("Incomplete response")
message = next((item for item in response.output if item.type == "message"), None)
math_response = message.content[0] if message and message.content else None
if not math_response:
raise Exception("No response content")
if math_response.type == "refusal":
print(math_response.refusal)
elif math_response.type == "output_text":
print(math_response.text)
else:
raise Exception("No response content")
except Exception as e:
# [中文] 处理结束原因、拒绝、内容过滤等错误;具体字段以当前端点为准。
# handle errors like finish_reason, refusal, content_filter, etc.
print(e)
第三步:处理边界情况(来源示例49,go)
// [中文] 先检测未完成状态,再定位message与content,分别处理refusal和output_text。
// [中文] 缺少内容、词元截断、内容过滤及调用异常均需单独处理,不能直接把所有响应解析为业务JSON。
package main
import (
"context"
"errors"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},
responses.EasyInputMessageRoleUser,
),
}},
MaxOutputTokens: openai.Int(1024),
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true)},
}},
})
if err != nil {
panic(err)
}
if response.Status == "incomplete" {
panic(errors.New("incomplete response"))
}
for _, output := range response.Output {
if output.Type != "message" {
continue
}
for _, content := range output.AsMessage().Content {
if content.Type == "refusal" {
fmt.Println(content.AsRefusal().Refusal)
return
}
if content.Type == "output_text" {
fmt.Println(content.AsOutputText().Text)
return
}
}
}
panic(errors.New("no response content"))
}
func mathSchema() map[string]any {
return map[string]any{
"type": "object",
"properties": map[string]any{
"steps": map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"explanation": map[string]any{"type": "string"}, "output": map[string]any{"type": "string"}}, "required": []string{"explanation", "output"}, "additionalProperties": false}},
"final_answer": map[string]any{"type": "string"},
},
"required": []string{"steps", "final_answer"},
"additionalProperties": false,
}
}
第三步:处理边界情况(来源示例50,java)
// [中文] 先检测未完成状态,再定位message与content,分别处理refusal和output_text。
// [中文] 缺少内容、词元截断、内容过滤及调用异常均需单独处理,不能直接把所有响应解析为业务JSON。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseStatus;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("How can I solve 8x + 7 = -23?")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("math_response")
.strict(true)
.schema(
ResponseFormatTextJsonSchemaConfig.Schema.builder()
.putAdditionalProperty("type", JsonValue.from("object"))
.putAdditionalProperty(
"properties",
JsonValue.from(
Map.of(
"steps",
Map.of(
"type",
"array",
"items",
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation",
Map.of("type", "string"),
"output",
Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false)),
"final_answer",
Map.of("type", "string"))))
.putAdditionalProperty(
"required",
JsonValue.from(List.of("steps", "final_answer")))
.putAdditionalProperty(
"additionalProperties", JsonValue.from(false))
.build())
.build())
.build())
.maxOutputTokens(1_024L)
.build();
var response = client.responses().create(params);
if (response.status().filter(ResponseStatus.INCOMPLETE::equals).isPresent()) {
throw new IllegalStateException("Incomplete response");
}
var content =
response.output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.findFirst()
.orElseThrow(() -> new IllegalStateException("No response content"));
if (content.refusal().isPresent()) {
System.out.println(content.refusal().orElseThrow().refusal());
} else {
System.out.println(
content
.outputText()
.orElseThrow(() -> new IllegalStateException("No response content"))
.text());
}
第三步:处理边界情况(来源示例51,csharp)
// [中文] 先检测未完成状态,再定位message与content,分别处理refusal和output_text。
// [中文] 缺少内容、词元截断、内容过滤及调用异常均需单独处理,不能直接把所有响应解析为业务JSON。
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
MaxOutputTokenCount = 300,
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));
options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));
ResponseResult response = await client.CreateResponseAsync(options);
if (
response.Status == ResponseStatus.Incomplete
&& response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.MaxOutputTokens
)
{
throw new InvalidOperationException("The structured response was incomplete.");
}
if (
response.Status == ResponseStatus.Incomplete
&& response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.ContentFilter
)
{
throw new InvalidOperationException("The structured response was interrupted by the content filter.");
}
MessageResponseItem message = response.OutputItems.OfType<MessageResponseItem>().FirstOrDefault()
?? throw new InvalidOperationException("The response did not include an output message.");
ResponseContentPart content = message.Content.FirstOrDefault()
?? throw new InvalidOperationException("The response did not include output content.");
Console.WriteLine(
content.Kind == ResponseContentPartKind.Refusal ? content.Refusal : content.Text
);
第三步:处理边界情况(来源示例52,ruby)
## [中文] 先检测未完成状态,再定位message与content,分别处理refusal和output_text。
## [中文] 缺少内容、词元截断、内容过滤及调用异常均需单独处理,不能直接把所有响应解析为业务JSON。
require "openai"
client = OpenAI::Client.new
step_schema = {
type: :object,
properties: {
explanation: { type: :string },
output: { type: :string }
},
required: %w[explanation output],
additionalProperties: false
}
math_schema = {
type: :object,
properties: {
steps: {
type: :array,
items: step_schema
},
final_answer: { type: :string }
},
required: %w[steps final_answer],
additionalProperties: false
}
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "You are a helpful math tutor. Guide the user through the solution step by step."
},
{
role: :user,
content: "How can I solve 8x + 7 = -23?"
}
],
max_output_tokens: 1_024,
text: {
format: {
type: :json_schema,
name: "math_response",
strict: true,
schema: math_schema
}
}
)
if response.status == OpenAI::Responses::ResponseStatus::INCOMPLETE
raise "Incomplete response"
end
message = response.output.find do |item|
item.is_a?(OpenAI::Models::Responses::ResponseOutputMessage)
end
unless message.is_a?(OpenAI::Models::Responses::ResponseOutputMessage)
raise "No response message"
end
content = message.content.fetch(0)
if content.is_a?(OpenAI::Models::Responses::ResponseOutputRefusal)
puts(content.refusal)
else
puts(content.text)
end
<a id="refusals-with-structured-outputs"></a>
结构化输出的拒绝
用户输入可能因安全原因被拒绝。拒绝不一定遵循业务Schema,API用refusal表示。界面可展示拒绝,也可在消费响应的代码中分支处理。
Could not parse response译为“无法解析响应”。Ruby开头示例的Response ended with status: ...表示“响应结束时状态为……”;No structured output returned (the model may have refused)表示“未返回结构化输出(模型可能已拒绝)”。
结构化输出的拒绝(来源示例53,javascript)
// [中文] 遍历输出消息及内容项,遇到refusal先展示或处理拒绝。
// [中文] 正常项检查parsed后输出,缺少解析结果时抛出异常。
const Step = z.object({
explanation: z.string(),
output: z.string(),
});
const MathReasoning = z.object({
steps: z.array(Step),
final_answer: z.string(),
});
const response = await openai.responses.parse({
model: "gpt-6-astra",
input: [
{
role: "system",
content:
"You are a helpful math tutor. Guide the user through the solution step by step.",
},
{ role: "user", content: "how can I solve 8x + 7 = -23" },
],
text: {
format: zodTextFormat(MathReasoning, "math_response"),
},
});
for (const output of response.output) {
if (output.type !== "message") {
continue;
}
for (const item of output.content) {
if (item.type == "refusal") {
// [中文] 模型拒绝回答时会返回拒绝消息。
// If the model refuses to respond, you will get a refusal message
console.log(item.refusal);
continue;
}
if (!item.parsed) {
throw new Error("Could not parse response");
}
console.log(item.parsed);
}
}
结构化输出的拒绝(来源示例54,python)
## [中文] 遍历输出消息及内容项,遇到refusal先展示或处理拒绝。
## [中文] 正常项检查parsed后输出,缺少解析结果时抛出异常。
class Step(BaseModel):
explanation: str
output: str
class MathReasoning(BaseModel):
steps: list[Step]
final_answer: str
response = client.responses.parse(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "You are a helpful math tutor. Guide the user through the solution step by step.",
},
{"role": "user", "content": "how can I solve 8x + 7 = -23"},
],
text_format=MathReasoning,
)
for output in response.output:
if output.type != "message":
continue
for item in output.content:
if item.type == "refusal":
# [中文] 模型拒绝回答时会返回拒绝消息。
# If the model refuses to respond, you will get a refusal message
print(item.refusal)
continue
if not item.parsed:
raise Exception("Could not parse response")
print(item.parsed)
结构化输出的拒绝(来源示例55,go)
// [中文] 遍历输出消息及内容项,遇到refusal先展示或处理拒绝。
// [中文] 正常项直接输出文本;本段没有把正常文本解析为业务对象,应用可在读取后补充解析与错误处理。
package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful math tutor. Guide the user through the solution step by step.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("how can I solve 8x + 7 = -23")},
responses.EasyInputMessageRoleUser,
),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONSchema: &responses.ResponseFormatTextJSONSchemaConfigParam{Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true)},
}},
})
if err != nil {
panic(err)
}
for _, output := range response.Output {
if output.Type != "message" {
continue
}
for _, content := range output.AsMessage().Content {
if content.Type == "refusal" {
fmt.Println(content.AsRefusal().Refusal)
continue
}
fmt.Println(content.AsOutputText().Text)
}
}
}
func mathSchema() map[string]any {
return map[string]any{
"type": "object",
"properties": map[string]any{
"steps": map[string]any{"type": "array", "items": map[string]any{"type": "object", "properties": map[string]any{"explanation": map[string]any{"type": "string"}, "output": map[string]any{"type": "string"}}, "required": []string{"explanation", "output"}, "additionalProperties": false}},
"final_answer": map[string]any{"type": "string"},
},
"required": []string{"steps", "final_answer"},
"additionalProperties": false,
}
}
结构化输出的拒绝(来源示例56,java)
// [中文] 遍历输出消息及内容项,遇到refusal先展示或处理拒绝。
// [中文] 正常项直接输出文本;本段没有把正常文本解析为业务对象,应用可在读取后补充解析与错误处理。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps",
Map.of(
"type",
"array",
"items",
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false)),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("How can I solve 8x + 7 = -23?")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("math_reasoning")
.strict(true)
.schema(
JsonValue.from(schema)
.convert(ResponseFormatTextJsonSchemaConfig.Schema.class))
.build())
.build())
.build();
var response = client.responses().create(params);
for (var output : response.output()) {
if (output.message().isEmpty()) continue;
for (var content : output.message().orElseThrow().content()) {
if (content.refusal().isPresent()) {
System.out.println(content.refusal().orElseThrow().refusal());
} else {
content.outputText().ifPresent(text -> System.out.println(text.text()));
}
}
}
结构化输出的拒绝(来源示例57,csharp)
// [中文] 遍历输出消息及内容项,遇到refusal先展示或处理拒绝。
// [中文] 正常项直接输出文本;本段没有把正常文本解析为业务对象,应用可在读取后补充解析与错误处理。
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
BinaryData schema = BinaryData.FromString(
"""
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful math tutor. Guide the user through the solution step by step."));
options.InputItems.Add(ResponseItem.CreateUserMessageItem("How can I solve 8x + 7 = -23?"));
ResponseResult response = await client.CreateResponseAsync(options);
foreach (MessageResponseItem message in response.OutputItems.OfType<MessageResponseItem>())
{
foreach (ResponseContentPart content in message.Content)
{
Console.WriteLine(
content.Kind == ResponseContentPartKind.Refusal ? content.Refusal : content.Text
);
}
}
结构化输出的拒绝(来源示例58,ruby)
## [中文] 遍历输出消息及内容项,遇到refusal先展示或处理拒绝。
## [中文] 正常项直接输出文本;本段没有把正常文本解析为业务对象,应用可在读取后补充解析与错误处理。
require "openai"
client = OpenAI::Client.new
math_schema = {
type: :object,
properties: {
steps: {
type: :array,
items: {
type: :object,
properties: {
explanation: { type: :string },
output: { type: :string }
},
required: %w[explanation output],
additionalProperties: false
}
},
final_answer: { type: :string }
},
required: %w[steps final_answer],
additionalProperties: false
}
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "You are a helpful math tutor. Guide the user through the solution step by step."
},
{
role: :user,
content: "How can I solve 8x + 7 = -23?"
}
],
text: {
format: {
type: :json_schema,
name: "math_response",
strict: true,
schema: math_schema
}
}
)
response.output.each do |item|
next unless item.is_a?(OpenAI::Models::Responses::ResponseOutputMessage)
item.content.each do |content|
case content
when OpenAI::Models::Responses::ResponseOutputRefusal
puts(content.refusal)
when OpenAI::Models::Responses::ResponseOutputText
puts(content.text)
end
end
end
拒绝响应示例:
结构化输出的拒绝(来源示例59,json)
此处沿用来源的JSON结构片段或响应示意,不是可独立解析的完整JSON载荷。
{
"id": "resp_1234567890",
"object": "response",
"created_at": 1721596428,
"status": "completed",
"completed_at": 1721596429,
"error": null,
"incomplete_details": null,
"input": [],
"instructions": null,
"max_output_tokens": null,
"model": "gpt-4o-2024-08-06",
"output": [{
"id": "msg_1234567890",
"type": "message",
"role": "assistant",
"content": [
// highlight-start
{
"type": "refusal",
"refusal": "I'm sorry, I cannot assist with that request."
}
// highlight-end
]
}],
"usage": {
"input_tokens": 81,
"output_tokens": 11,
"total_tokens": 92,
"output_tokens_details": {
"reasoning_tokens": 0,
}
},
}
refusal中的完整文字译为:“抱歉,我无法协助处理这个请求。”外层status: completed表示响应生成已结束,不表示业务任务成功或已经返回数学解题Schema。
<a id="tips-and-best-practices"></a>
提示与最佳实践
<a id="handling-user-generated-input"></a>
用户生成的输入
提示词应说明输入无法产生有效结果时如何处理。模型会尝试满足Schema,输入完全无关时可能因此幻觉。可规定不适用时返回空参数或特定句子,但该返回约定也应与Schema一致。
<a id="handling-mistakes"></a>
内容错误
结构化输出仍可能出错。可调整指令、在system中提供示例,或拆成更简单子任务,见提示词工程。
<a id="avoid-json-schema-divergence"></a>
避免Schema与类型分歧
优先用SDK原生Schema辅助函数。直接手写Schema时,可用CI在Schema或数据对象变化时提示,或自动从类型生成Schema、反向生成类型,避免两套定义漂移。
<a id="streaming"></a>
流式处理
可边生成边处理响应或函数参数,解析为结构化数据,无需等完整响应,适合逐字段展示或及时处理参数。推荐SDK处理结构化流。
程序按attributes(特征)、colors(颜色)、animals(动物)三个数组解析。JavaScript来源示例60的用户输入是“巴黎今天天气如何?”,与实体抽取Schema的搭配存在局限,不能据此暗示天气问题适合该结构。Python示例61、Java示例62和Ruby示例63的任务则为“从输入文本中抽取实体”,输入为“一只敏捷的棕色狐狸跃过那只有着锐利蓝眼睛的懒狗。”后面三种语言没有使用天气问题。此处保留各自的来源代码,不将四种输入描述为等价。
流结束处理也依语言而异:JavaScript调用finalResponse(),Python在循环后调用get_final_response();Java在completed事件回调中打印completed.response();Ruby只打印完成提示,并未取得最终响应对象。Completed的中文为“已完成”,它是一条程序提示,不等于已读取业务结果。
流式处理(来源示例60,javascript)
// [中文] 定义attributes、colors、animals三组实体字段,以流式事件逐步读取内容。
// [中文] 监听拒绝增量、文本增量、文本结束和SDK错误;await finalResponse()等待并取得最终响应。
// [中文] JavaScript来源输入为天气问题;其他三种语言输入为狐狸与狗句子,不能当作等价输入。
import { OpenAI } from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const EntitiesSchema = z.object({
attributes: z.array(z.string()),
colors: z.array(z.string()),
animals: z.array(z.string()),
});
const openai = new OpenAI();
const stream = openai.responses
.stream({
model: "gpt-6-astra",
input: [
{ role: "user", content: "What's the weather like in Paris today?" },
],
text: {
format: zodTextFormat(EntitiesSchema, "entities"),
},
})
.on("response.refusal.delta", (event) => {
process.stdout.write(event.delta);
})
.on("response.output_text.delta", (event) => {
process.stdout.write(event.delta);
})
.on("response.output_text.done", () => {
process.stdout.write("\n");
})
.on("error", (error) => {
console.error(error);
});
const result = await stream.finalResponse();
console.log(result);
流式处理(来源示例61,python)
## [中文] 定义attributes、colors、animals三组实体字段,以流式事件逐步读取内容。
## [中文] 遍历拒绝增量、文本增量、错误及完成事件;循环后调用get_final_response()取得最终响应。
## [中文] JavaScript来源输入为天气问题;其他三种语言输入为狐狸与狗句子,不能当作等价输入。
from openai import OpenAI
from pydantic import BaseModel
class EntitiesModel(BaseModel):
attributes: list[str]
colors: list[str]
animals: list[str]
client = OpenAI()
with client.responses.stream(
model="gpt-6-astra",
input=[
{"role": "system", "content": "Extract entities from the input text"},
{
"role": "user",
"content": "The quick brown fox jumps over the lazy dog with piercing blue eyes",
},
],
text_format=EntitiesModel,
) as stream:
for event in stream:
if event.type == "response.refusal.delta":
print(event.delta, end="")
elif event.type == "response.output_text.delta":
print(event.delta, end="")
elif event.type == "response.error":
print(event.error, end="")
elif event.type == "response.completed":
print("Completed") # print(event.response.output)
final_response = stream.get_final_response()
print(final_response)
流式处理(来源示例62,java)
// [中文] 定义attributes、colors、animals三组实体字段,以流式事件逐步读取内容。
// [中文] 在事件流回调中输出文本/拒绝增量和错误;completed事件中读取并打印completed.response()。
// [中文] JavaScript来源输入为天气问题;其他三种语言输入为狐狸与狗句子,不能当作等价输入。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.core.http.StreamResponse;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseStreamEvent;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
import java.util.Map;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content("Extract entities from the input text")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content(
"The quick brown fox jumps over the lazy dog with piercing blue eyes")
.build())))
.text(
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("entities")
.strict(true)
.schema(
ResponseFormatTextJsonSchemaConfig.Schema.builder()
.putAdditionalProperty("type", JsonValue.from("object"))
.putAdditionalProperty(
"properties",
JsonValue.from(
Map.of(
"attributes",
Map.of(
"type",
"array",
"items",
Map.of("type", "string")),
"colors",
Map.of(
"type",
"array",
"items",
Map.of("type", "string")),
"animals",
Map.of(
"type",
"array",
"items",
Map.of("type", "string")))))
.putAdditionalProperty(
"required",
JsonValue.from(List.of("attributes", "colors", "animals")))
.putAdditionalProperty(
"additionalProperties", JsonValue.from(false))
.build())
.build())
.build())
.build();
try (StreamResponse<ResponseStreamEvent> stream = client.responses().createStreaming(params)) {
stream.stream()
.forEach(
event -> {
event.outputTextDelta().ifPresent(delta -> System.out.print(delta.delta()));
event.refusalDelta().ifPresent(refusal -> System.out.print(refusal.delta()));
event.error().ifPresent(error -> System.out.println(error.message()));
event
.completed()
.ifPresent(
completed -> {
System.out.println("Completed");
System.out.println(completed.response());
});
});
}
流式处理(来源示例63,ruby)
## [中文] 定义attributes、colors、animals三组实体字段,以流式事件逐步读取内容。
## [中文] 逐个处理增量、错误及完成事件;完成时仅打印Completed,本段没有获取最终响应对象。
## [中文] JavaScript来源输入为天气问题;其他三种语言输入为狐狸与狗句子,不能当作等价输入。
require "openai"
client = OpenAI::Client.new
entities_schema = {
type: :object,
properties: {
attributes: {
type: :array,
items: { type: :string }
},
colors: {
type: :array,
items: { type: :string }
},
animals: {
type: :array,
items: { type: :string }
}
},
required: %w[attributes colors animals],
additionalProperties: false
}
stream = client.responses.stream(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "Extract entities from the input text."
},
{
role: :user,
content: "The quick brown fox jumps over the lazy dog with piercing blue eyes."
}
],
text: {
format: {
type: :json_schema,
name: "entities",
strict: true,
schema: entities_schema
}
}
)
stream.each do |event|
case event
when OpenAI::Models::Responses::ResponseRefusalDeltaEvent,
OpenAI::Models::Responses::ResponseTextDeltaEvent
print(event.delta)
when OpenAI::Models::Responses::ResponseErrorEvent
warn(event.message)
when OpenAI::Models::Responses::ResponseCompletedEvent
puts("\nCompleted")
end
end
<a id="supported-schemas"></a>
支持的Schema
支持JSON Schema子集。
<a id="supported-types"></a>
支持类型
字符串、数字、布尔、整数、对象、数组、枚举及anyOf。
<a id="supported-properties"></a>
支持属性
字符串支持pattern(正则)和format,格式包括date-time、time、date、duration、email、hostname、ipv4、ipv6、uuid。
数字支持multipleOf(倍数)、maximum(≤)、exclusiveMaximum(<)、minimum(≥)、exclusiveMinimum(>);数组支持minItems及maxItems。
字符串限制:
支持属性(来源示例64,json)
此处沿用来源的JSON结构片段或响应示意,不是可独立解析的完整JSON载荷。
{
"name": "user_data",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the user"
},
"username": {
"type": "string",
"description": "The username of the user. Must start with @",
// highlight-start
"pattern": "^@[a-zA-Z0-9_]+$"
// highlight-end
},
"email": {
"type": "string",
"description": "The email of the user",
// highlight-start
"format": "email"
// highlight-end
}
},
"additionalProperties": false,
"required": [
"name", "username", "email"
]
}
}
字段说明逐项译为:name“用户的姓名”;username“用户的用户名,必须以@开头”;email“用户的电子邮箱”。正则^@[a-zA-Z0-9_]+$及format: email保持原值。
数字限制:
支持属性(来源示例65,json)
此处沿用来源的JSON结构片段或响应示意,不是可独立解析的完整JSON载荷。
{
"name": "weather_data",
"strict": true,
"schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The location to get the weather for"
},
"unit": {
"type": ["string", "null"],
"description": "The unit to return the temperature in",
"enum": ["F", "C"]
},
"value": {
"type": "number",
"description": "The actual temperature value in the location",
// highlight-start
"minimum": -130,
"maximum": 130
// highlight-end
}
},
"additionalProperties": false,
"required": [
"location", "unit", "value"
]
}
}
字段说明逐项译为:location“要查询天气的地点”;unit“返回温度时使用的单位”;value“该地点的实际温度值”。F、C分别表示华氏与摄氏单位;数值最小-130、最大130。
这些约束尚不适用于下述微调模型范围。
<a id="root-objects-must-not-be-anyof-and-must-be-an-object"></a>
根对象必须为object,不能为anyOf
例如Zod的判别联合可能产生顶层anyOf,下面这种写法不支持:
根对象必须为object,不能为anyOf(来源示例66,javascript)
// [中文] 此判别联合生成顶层anyOf,违反结构化输出根对象须为object的要求,是反例。
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
const BaseResponseSchema = z.object({
/* ... */
});
const UnsuccessfulResponseSchema = z.object({
/* ... */
});
const finalSchema = z.discriminatedUnion("status", [
BaseResponseSchema,
UnsuccessfulResponseSchema,
]);
// [中文] 该Schema不符合结构化输出要求。
// Invalid JSON Schema for Structured Outputs
const json = zodResponseFormat(finalSchema, "final_schema");
<a id="all-fields-must-be-required"></a>
所有字段都必须required
所有对象字段或函数参数必须列入required:
所有字段都必须required(来源示例67,json)
此处沿用来源的JSON结构片段或响应示意,不是可独立解析的完整JSON载荷。
{
"name": "get_weather",
"description": "Fetches the weather in the given location",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The location to get the weather for"
},
"unit": {
"type": "string",
"description": "The unit to return the temperature in",
"enum": ["F", "C"]
}
},
"additionalProperties": false,
// highlight-start
"required": ["location", "unit"]
// highlight-end
}
}
get_weather说明为“获取指定地点的天气”,location说明为“要查询天气的地点”,unit说明为“返回温度时使用的单位”;F为华氏、C为摄氏。下面两个变体沿用相同英文说明与中文含义,不重复修改协议字段。
可用与null的联合模拟可选值,但字段本身仍必须返回:
所有字段都必须required(来源示例68,json)
此处沿用来源的JSON结构片段或响应示意,不是可独立解析的完整JSON载荷。
{
"name": "get_weather",
"description": "Fetches the weather in the given location",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The location to get the weather for"
},
"unit": {
// highlight-start
"type": ["string", "null"],
// highlight-end
"description": "The unit to return the temperature in",
"enum": ["F", "C"]
}
},
"additionalProperties": false,
"required": [
"location", "unit"
]
}
}
<a id="objects-have-limitations-on-nesting-depth-and-size"></a>
对象层级与大小限制
最多5,000个对象属性,总嵌套最多10层。
<a id="limitations-on-total-string-size"></a>
总字符串大小限制
所有属性名、定义名、枚举值和const值的字符串总长度不能超过120,000字符。
<a id="limitations-on-enum-size"></a>
枚举大小限制
所有枚举属性合计最多1,000个值。单个字符串枚举超过250个值时,该枚举全部值的总字符串长度不能超过15,000字符。
<a id="additionalproperties-false-must-always-be-set-in-objects"></a>
对象始终设置additionalProperties:false
该参数控制是否允许Schema未定义的额外键。结构化输出只生成指定键值,因此要求设false。
对象始终设置additionalProperties:false(来源示例69,json)
此处沿用来源的JSON结构片段或响应示意,不是可独立解析的完整JSON载荷。
{
"name": "get_weather",
"description": "Fetches the weather in the given location",
"strict": true,
"schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The location to get the weather for"
},
"unit": {
"type": "string",
"description": "The unit to return the temperature in",
"enum": ["F", "C"]
}
},
// highlight-start
"additionalProperties": false,
// highlight-end
"required": [
"location", "unit"
]
}
}
<a id="key-ordering"></a>
键顺序
输出按Schema中键的顺序生成。
<a id="some-type-specific-keywords-are-not-yet-supported"></a>
尚不支持的特定关键词
组合类:allOf、not、dependentRequired、dependentSchemas、if、then、else。微调模型额外不支持:字符串minLength、maxLength、pattern、format;数字minimum、maximum、multipleOf;对象patternProperties;数组minItems、maxItems。strict:true配合不支持Schema会报错。
<a id="for-anyof-the-nested-schemas-must-each-be-a-valid-json-schema-per-this-subset"></a>
anyOf的各嵌套Schema也必须符合子集
支持的示例:
anyOf的各嵌套Schema也必须符合子集(来源示例70,json)
{
"type": "object",
"properties": {
"item": {
"anyOf": [
{
"type": "object",
"description": "The user object to insert into the database",
"properties": {
"name": {
"type": "string",
"description": "The name of the user"
},
"age": {
"type": "number",
"description": "The age of the user"
}
},
"additionalProperties": false,
"required": [
"name",
"age"
]
},
{
"type": "object",
"description": "The address object to insert into the database",
"properties": {
"number": {
"type": "string",
"description": "The number of the address. Eg. for 123 main st, this would be 123"
},
"street": {
"type": "string",
"description": "The street name. Eg. for 123 main st, this would be main st"
},
"city": {
"type": "string",
"description": "The city of the address"
}
},
"additionalProperties": false,
"required": [
"number",
"street",
"city"
]
}
]
}
},
"additionalProperties": false,
"required": [
"item"
]
}
两个分支的完整说明:用户分支是“将插入数据库的用户对象”,name为“用户的姓名”,age为“用户的年龄”;地址分支是“将插入数据库的地址对象”,number为“地址中的门牌号,例如123 main st中的123”,street为“街道名,例如123 main st中的main st”,city为“地址所在城市”。
<a id="definitions-are-supported"></a>
支持定义
可定义子Schema并在多处引用:
支持定义(来源示例71,json)
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"$ref": "#/$defs/step"
}
},
"final_answer": {
"type": "string"
}
},
"$defs": {
"step": {
"type": "object",
"properties": {
"explanation": {
"type": "string"
},
"output": {
"type": "string"
}
},
"required": [
"explanation",
"output"
],
"additionalProperties": false
}
},
"required": [
"steps",
"final_answer"
],
"additionalProperties": false
}
$defs.step定义可复用步骤:explanation为步骤解释、output为步骤结果;steps.items.$ref引用它,final_answer为最终答案。
<a id="recursive-schemas-are-supported"></a>
支持递归
用#指向根递归:
支持递归(来源示例72,json)
{
"name": "ui",
"description": "Dynamically generated UI",
"strict": true,
"schema": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "The type of the UI component",
"enum": ["div", "button", "header", "section", "field", "form"]
},
"label": {
"type": "string",
"description": "The label of the UI component, used for buttons or form fields"
},
"children": {
"type": "array",
"description": "Nested UI components",
"items": {
"$ref": "#"
}
},
"attributes": {
"type": "array",
"description": "Arbitrary attributes for the UI component, suitable for any element",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the attribute, for example onClick or className"
},
"value": {
"type": "string",
"description": "The value of the attribute"
}
},
"additionalProperties": false,
"required": ["name", "value"]
}
}
},
"required": ["type", "label", "children", "attributes"],
"additionalProperties": false
}
}
本例的动态UI及各字段description与前面“UI字段与说明中文对照”逐项相同;children.items.$ref: "#"引用整个根Schema,从而嵌套同结构组件,字段与枚举含义保持一致。
显式递归:
支持递归(来源示例73,json)
{
"type": "object",
"properties": {
"linked_list": {
"$ref": "#/$defs/linked_list_node"
}
},
"$defs": {
"linked_list_node": {
"type": "object",
"properties": {
"value": {
"type": "number"
},
"next": {
"anyOf": [
{
"$ref": "#/$defs/linked_list_node"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false,
"required": [
"next",
"value"
]
}
},
"additionalProperties": false,
"required": [
"linked_list"
]
}
此链表中linked_list是表头,linked_list_node定义节点;value保存数值,next引用下一个同类节点,末节点用null结束。两个字段均必须存在。
<a id="json-mode"></a>
JSON模式
JSON模式较基础,只保证有效JSON,不保证符合指定Schema;适用时优先结构化输出。仍有应检测处理的少数边界情况。Responses设置text.format: { "type": "json_object" }启用,函数调用时JSON模式默认开启。
- 对话必须明确要求生成JSON,例如system消息。否则可能不断输出空白,直到词元上限。为避免遗漏,API会在上下文不存在字符串“JSON”时报错。
- 不保证特定Schema,只保证可解析。无法用结构化输出时,采用验证库,并在需要时重试以满足业务Schema。
- 应检测并处理未返回完整JSON对象的情况。
<a id="handling-edge-cases"></a>
边界处理
程序内完整任务是:“你是一个乐于助人、被设计为输出JSON的助手。谁赢得了2020年世界大赛?请按{winner: ...}格式回答。”Python将格式具体写成{"winner": "team name"}(team name即队名),C#要求以JSON给出获胜者。来源注释期望Los Angeles Dodgers,中文为“洛杉矶道奇队”。
诊断文字对照:“The response was truncated before the JSON completed.”为“JSON完成前响应已被截断”;“The response was interrupted by the content filter.”为“响应被内容过滤中断”;“The JSON response is incomplete.”为“JSON响应不完整”;“Reason:”为“原因”;“Request failed:”为“请求失败”。The response ended with status: ...为“响应结束时状态为……”。原注释有“上下文过长”或“符合Schema”等表述,中文注释按实际分支补充了限定:max_output_tokens检查输出截断,JSON模式不保证符合业务Schema;停止词讨论也不能直接推断当前Responses参数支持。
各语言的边界处理和解析并不完全相同。JavaScript包含JSON解析与错误处理占位;Python只打印完成后的文本,没有调用json.loads;Go完成后调用json.Unmarshal;Java读取未完成原因或拒绝并输出正常文本,没有JSON解析;C#区分输出截断和内容过滤,再输出拒绝或文本,没有JSON反序列化;Ruby在完成后调用JSON.parse。Go、Java、Ruby没有按两类截断原因分别实现处理。应用应根据所选实现补齐解析、验证和异常处理,不能把这一组示例视为已实现相同的流程。
边界处理(来源示例74,javascript)
// [中文] 以text.format.type=json_object启用JSON模式,提示中明确出现JSON。
// [中文] 分别检查输出截断、拒绝和内容过滤;错误分支含待实现占位,完成且未设置停止词时调用JSON.parse,异常由catch接收。
// [中文] JSON模式不校验业务Schema;应用仍需补充本示例未实现的验证和错误处理。
const we_did_not_specify_stop_tokens = true;
try {
const response = await openai.responses.create({
model: "gpt-6-astra",
input: [
{
role: "system",
content: "You are a helpful assistant designed to output JSON.",
},
{
role: "user",
content:
"Who won the world series in 2020? Please respond in the format {winner: ...}",
},
],
text: { format: { type: "json_object" } },
});
const message = response.output.find((item) => item.type === "message");
const messageContent = message?.content[0];
// [中文] 原注释将截断归于上下文过长;实际分支检测max_output_tokens输出上限,不能据此断定上下文溢出。
// Check if the conversation was too long for the context window, resulting in incomplete JSON
if (
response.status === "incomplete" &&
response.incomplete_details.reason === "max_output_tokens"
) {
// [中文] 应用需在此补充错误处理。
// your code should handle this error case
}
// [中文] 检查安全系统是否拒绝请求,并改为生成拒绝消息。
// Check if the OpenAI safety system refused the request and generated a refusal instead
if (messageContent?.type === "refusal") {
// [中文] 应用需在此补充错误处理。
// your code should handle this error case
// [中文] 拒绝内容包含模型提供的原因(若有);当前示例读取refusal字段。
// In this case, the .content field will contain the explanation (if any) that the model generated for why it is refusing
console.log(messageContent.refusal);
}
// [中文] 检查内容过滤是否中止JSON生成,导致内容不完整。
// Check if the model's output included restricted content, so the generation of JSON was halted and may be partial
if (
response.status === "incomplete" &&
response.incomplete_details.reason === "content_filter"
) {
// [中文] 应用需在此补充错误处理。
// your code should handle this error case
}
if (response.status === "completed") {
// [中文] 原注释讨论JSON已生成或遇到停止词;JSON模式本身不保证符合Schema,且停止词只适用于支持该参数的接口。
// In this case the model has either successfully finished generating the JSON object according to your schema, or the model generated one of the tokens you provided as a "stop token"
if (we_did_not_specify_stop_tokens) {
// [中文] 未使用停止词时,确认完成后读取序列化JSON;本段代码实际读取output_text。
// If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object
// [中文] 来源预期解析结果为winner等于Los Angeles Dodgers,即洛杉矶道奇队;运行时仍须处理解析失败。
// This will parse successfully and should now contain {"winner": "Los Angeles Dodgers"}
console.log(JSON.parse(response.output_text));
} else {
// [中文] 若使用支持停止词的接口,检查文本是否以指定停止词结束并作相应处理。
// Check if the response.output_text ends with one of your stop tokens and handle appropriately
}
}
} catch (e) {
// [中文] 在此处理API调用的网络错误等异常。
// Your code should handle errors here, for example a network error calling the API
console.error(e);
}
边界处理(来源示例75,python)
## [中文] 以text.format.type=json_object启用JSON模式,提示中明确出现JSON。
## [中文] 检查输出截断、拒绝及内容过滤;已完成时只打印output_text,本段没有调用json.loads,应用仍需解析及校验。
## [中文] JSON模式不校验业务Schema;应用仍需补充本示例未实现的验证和错误处理。
we_did_not_specify_stop_tokens = True
try:
response = client.responses.create(
model="gpt-6-astra",
input=[
{
"role": "system",
"content": "You are a helpful assistant designed to output JSON.",
},
{
"role": "user",
"content": 'Who won the World Series in 2020? Respond as {"winner": "team name"}.',
},
],
text={"format": {"type": "json_object"}},
)
message = next((item for item in response.output if item.type == "message"), None)
message_content = message.content[0] if message and message.content else None
# [中文] 原注释将截断归于上下文过长;实际分支检测max_output_tokens输出上限,不能据此断定上下文溢出。
# Check if the conversation was too long for the context window, resulting in incomplete JSON
if (
response.status == "incomplete"
and response.incomplete_details.reason == "max_output_tokens"
):
raise RuntimeError("The response was truncated before the JSON completed.")
# [中文] 检查安全系统是否拒绝请求,并改为生成拒绝消息。
# Check if the OpenAI safety system refused the request and generated a refusal instead
if message_content and message_content.type == "refusal":
# [中文] 应用需在此补充错误处理。
# your code should handle this error case
# [中文] 拒绝内容包含模型提供的原因(若有);当前示例读取refusal字段。
# In this case, the .content field will contain the explanation (if any) that the model generated for why it is refusing
print(message_content.refusal)
# [中文] 检查内容过滤是否中止JSON生成,导致内容不完整。
# Check if the model's output included restricted content, so the generation of JSON was halted and may be partial
if (
response.status == "incomplete"
and response.incomplete_details.reason == "content_filter"
):
raise RuntimeError("The response was interrupted by the content filter.")
if response.status == "completed":
# [中文] 原注释讨论JSON已生成或遇到停止词;JSON模式本身不保证符合Schema,且停止词只适用于支持该参数的接口。
# In this case the model has either successfully finished generating the JSON object according to your schema, or the model generated one of the tokens you provided as a "stop token"
if we_did_not_specify_stop_tokens:
# [中文] 未使用停止词时,确认完成后读取序列化JSON;本段代码实际读取output_text。
# If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object
# [中文] 来源注释期望winner为Los Angeles Dodgers(洛杉矶道奇队);本段Python仅打印文本,没有执行JSON解析。
# This will parse successfully and should now contain "{"winner": "Los Angeles Dodgers"}"
print(response.output_text)
except Exception as e:
# [中文] 在此处理API调用的网络错误等异常。
# Your code should handle errors here, for example a network error calling the API
print(e)
边界处理(来源示例76,go)
// [中文] 以text.format.type=json_object启用JSON模式,提示中明确出现JSON。
// [中文] 未完成时返回,拒绝时输出拒绝并返回;完成后用json.Unmarshal解析文本,未按不同截断原因分别处理。
// [中文] JSON模式不校验业务Schema;应用仍需补充本示例未实现的验证和错误处理。
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("You are a helpful assistant designed to output JSON.")},
responses.EasyInputMessageRoleSystem,
),
responses.ResponseInputItemParamOfMessage(
responses.ResponseInputMessageContentListParam{responses.ResponseInputContentParamOfInputText("Who won the world series in 2020? Please respond in the format {winner: ...}")},
responses.EasyInputMessageRoleUser,
),
}},
Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{
OfJSONObject: &shared.ResponseFormatJSONObjectParam{},
}},
})
if err != nil {
panic(err)
}
if response.Status == "incomplete" {
fmt.Println("The JSON response is incomplete.")
return
}
for _, output := range response.Output {
if output.Type != "message" {
continue
}
for _, content := range output.AsMessage().Content {
if content.Type == "refusal" {
fmt.Println(content.AsRefusal().Refusal)
return
}
}
}
if response.Status == "completed" {
var value map[string]any
if err := json.Unmarshal([]byte(response.OutputText()), &value); err != nil {
panic(err)
}
fmt.Println(value)
}
}
边界处理(来源示例77,java)
// [中文] 以text.format.type=json_object启用JSON模式,提示中明确出现JSON。
// [中文] 未完成时读取并打印reason后返回,拒绝时输出并返回;已完成时仅打印文本,没有JSON解析,也未分别实现两种截断原因的处理。
// [中文] JSON模式不校验业务Schema;应用仍需补充本示例未实现的验证和错误处理。
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.errors.OpenAIServiceException;
import com.openai.models.ResponseFormatJsonObject;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseStatus;
import com.openai.models.responses.ResponseTextConfig;
import java.util.List;
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(
List.of(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.SYSTEM)
.content("You are a helpful assistant designed to output JSON.")
.build()),
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content(
"Who won the World Series in 2020? Respond in the format {winner: ...}.")
.build())))
.text(
ResponseTextConfig.builder()
.format(ResponseFormatJsonObject.builder().build())
.build())
.build();
try {
var response = client.responses().create(params);
if (response.status().filter(ResponseStatus.INCOMPLETE::equals).isPresent()) {
String reason =
response
.incompleteDetails()
.flatMap(details -> details.reason())
.map(Object::toString)
.orElse("unknown");
System.out.println("The JSON response is incomplete. Reason: " + reason);
return;
}
for (var output : response.output()) {
if (output.message().isEmpty()) continue;
for (var content : output.message().orElseThrow().content()) {
if (content.refusal().isPresent()) {
System.out.println(content.refusal().orElseThrow().refusal());
return;
}
if (response.status().filter(ResponseStatus.COMPLETED::equals).isPresent()) {
content.outputText().ifPresent(text -> System.out.println(text.text()));
}
}
}
} catch (OpenAIServiceException error) {
System.out.println("Request failed: " + error.getMessage());
}
边界处理(来源示例78,csharp)
// [中文] 以text.format.type=json_object启用JSON模式,提示中明确出现JSON。
// [中文] 区分MaxOutputTokens和ContentFilter,完成后输出拒绝或文本;本段没有JSON反序列化。
// [中文] JSON模式不校验业务Schema;应用仍需补充本示例未实现的验证和错误处理。
using OpenAI.Responses;
#pragma warning disable OPENAI001
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
ResponsesClient client = new(key);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
TextOptions = new ResponseTextOptions
{
TextFormat = ResponseTextFormat.CreateJsonObjectFormat(),
},
};
options.InputItems.Add(ResponseItem.CreateSystemMessageItem("You are a helpful assistant designed to output JSON."));
options.InputItems.Add(ResponseItem.CreateUserMessageItem("Who won the World Series in 2020? Respond with the winner in JSON."));
ResponseResult response = await client.CreateResponseAsync(options);
if (
response.Status == ResponseStatus.Incomplete
&& response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.MaxOutputTokens
)
{
Console.WriteLine("The response was truncated before the JSON completed.");
}
else if (
response.Status == ResponseStatus.Incomplete
&& response.IncompleteStatusDetails?.Reason == ResponseIncompleteStatusReason.ContentFilter
)
{
Console.WriteLine("The response was interrupted by the content filter.");
}
else if (response.Status == ResponseStatus.Completed)
{
MessageResponseItem message = response.OutputItems.OfType<MessageResponseItem>().FirstOrDefault()
?? throw new InvalidOperationException("The response did not include an output message.");
ResponseContentPart content = message.Content.FirstOrDefault()
?? throw new InvalidOperationException("The response did not include output content.");
Console.WriteLine(
content.Kind == ResponseContentPartKind.Refusal ? content.Refusal : content.Text
);
}
else
{
throw new InvalidOperationException($"The response ended with status: {response.Status}");
}
边界处理(来源示例79,ruby)
## [中文] 以text.format.type=json_object启用JSON模式,提示中明确出现JSON。
## [中文] 未完成时警告,拒绝时输出拒绝;完成后调用JSON.parse,再格式化打印,未按不同截断原因分别处理。
## [中文] JSON模式不校验业务Schema;应用仍需补充本示例未实现的验证和错误处理。
require "json"
require "openai"
client = OpenAI::Client.new
response = client.responses.create(
model: "gpt-6-astra",
input: [
{
role: :system,
content: "You are a helpful assistant designed to output JSON."
},
{
role: :user,
content: "Who won the World Series in 2020? Respond in the format {winner: ...}."
}
],
text: { format: { type: :json_object } }
)
if response.status == OpenAI::Responses::ResponseStatus::INCOMPLETE
warn("The JSON response is incomplete.")
else
refusal = response.output
.grep(OpenAI::Models::Responses::ResponseOutputMessage)
.flat_map(&:content)
.find { |content| content.is_a?(OpenAI::Models::Responses::ResponseOutputRefusal) }
if refusal.is_a?(OpenAI::Models::Responses::ResponseOutputRefusal)
puts(refusal.refusal)
elsif response.status == OpenAI::Responses::ResponseStatus::COMPLETED
puts(JSON.pretty_generate(JSON.parse(response.output_text)))
end
end
<a id="resources"></a>

TRAE-AI编程


更多建议: