JSON é um dos formatos mais usados no mundo para a troca de dados entre aplicativos.
Saídas estruturadas é um recurso que garante que o modelo sempre gere respostas que sigam o JSON Schema fornecido por você, para que você não precise se preocupar com o modelo omitindo uma chave obrigatória ou inventando um valor inválido para uma enumeração.
Alguns benefícios das saídas estruturadas incluem:
- Segurança de tipos confiável: Não é necessário validar respostas com formatação incorreta nem repetir solicitações para corrigi-las
- Recusas explícitas: Agora é possível detectar programaticamente as recusas do modelo por motivos de segurança
- Criação de prompts mais simples: Não é necessário usar prompts enfáticos para obter uma formatação consistente
Além de oferecer suporte a JSON Schema na API REST, as bibliotecas da OpenAI para Python e JavaScript também permitem definir esquemas de objetos usando pydantic.BaseModel e z.object, respectivamente. A seguir, veja como extrair informações de um texto não estruturado e organizá-las conforme um esquema definido em código.
O SDK Ruby oferece suporte a esquemas definidos com T::Struct do Sorbet e retorna resultados tipados da análise sintática.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import OpenAI from "openai";
import { zodResponseFormat } 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 completion = await openai.chat.completions.parse({
model: "gpt-6-astra",
messages: [
{ role: "system", content: "Extract the event information." },
{
role: "user",
content: "Alice and Bob are going to a science fair on Friday.",
},
],
response_format: zodResponseFormat(CalendarEvent, "event"),
});
const event = completion.choices[0].message.parsed;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25from pydantic import BaseModel
from openai import OpenAI
client = OpenAI()
class CalendarEvent(BaseModel):
name: str
date: str
participants: list[str]
completion = client.chat.completions.parse(
model="gpt-6-astra",
messages=[
{"role": "system", "content": "Extract the event information."},
{
"role": "user",
"content": "Alice and Bob are going to a science fair on Friday.",
},
],
response_format=CalendarEvent,
)
event = completion.choices[0].message.parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
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,
}
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("Extract the event information."),
openai.UserMessage("Alice and Bob are going to a science fair on Friday."),
},
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "event", Schema: schema, Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
fmt.Println(completion.Choices[0].Message.Content)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
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);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage("Extract the event information.")
.addUserMessage("Alice and Bob are going to a science fair on Friday.")
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "event", "strict", true, "schema", schema))))
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(System.out::println);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"event",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[
new SystemChatMessage("Extract the event information."),
new UserChatMessage(
"Alice and Bob are going to a science fair on Friday."
),
],
options
);
Console.WriteLine(completion.Content[0].Text);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34# 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)
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
role: :system,
content: "Extract the event information."
},
{
role: :user,
content: "Alice and Bob are going to a science fair on Friday."
}
],
response_format: schema
)
choice = completion.choices.fetch(0)
raise "Completion ended with reason: #{choice.finish_reason}" unless choice.finish_reason.to_s == "stop"
raise "The model refused the request" if choice.message.refusal
event = T.cast(choice.message.parsed, CalendarEvent)
puts(event.name, event.date, event.participants.join(", "))1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import 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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25from 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_parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45package 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())
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58import 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()));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47using 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());1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36# 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(", "))Modelos compatíveis
O recurso de saídas estruturadas está disponível em nossos modelos de linguagem de grande porte mais recentes, a partir do GPT-4o. Para novos projetos, comece com gpt-6-astra. Modelos mais antigos, como gpt-4-turbo e anteriores, podem usar o modo JSON como alternativa.
Quando usar saídas estruturadas via chamada de função ou via response_format
Quando usar saídas estruturadas via chamada de função ou via text.format
O recurso de saídas estruturadas está disponível de duas formas na API da OpenAI:
- Ao usar chamada de função
- Ao usar um formato de resposta
json_schema
A chamada de função é útil quando você está desenvolvendo um aplicativo que conecta os modelos às funcionalidades do próprio aplicativo.
Por exemplo, você pode dar ao modelo acesso a funções que consultam um banco de dados para criar um assistente de IA que ajude os usuários com seus pedidos, ou a funções que interagem com a interface.
Já as saídas estruturadas via response_format são mais adequadas quando você quer especificar um esquema estruturado para as respostas do modelo ao usuário, em vez de usá-lo nas chamadas do modelo a ferramentas.
Por exemplo, se você estiver desenvolvendo um aplicativo de tutoria de matemática, talvez queira que o assistente responda ao usuário usando um JSON Schema específico, para que você possa gerar uma interface que exiba diferentes partes da saída do modelo de maneiras distintas.
Na prática:
- Se você está conectando o modelo a ferramentas, funções, dados etc. no seu
sistema, deve usar chamada de função - Se quiser estruturar a
saída do modelo quando ele responde ao usuário, deve usar
response_formatcom um formato estruturado
- Se você está conectando o modelo a ferramentas, funções, dados etc. no seu
sistema, deve usar chamada de função - Se quiser estruturar a
saída do modelo quando ele responde ao usuário, deve usar
text.formatcom um formato estruturado
O restante deste guia se concentra em casos de uso sem chamada de função na API chat completions. Para saber mais sobre como usar saídas estruturadas com chamada de função, consulte
Chamada de função
no guia.
O restante deste guia se concentra em casos de uso sem chamada de função na Responses API. Para saber mais sobre como usar saídas estruturadas com chamada de função, consulte
Chamada de função
no guia.
Saídas estruturadas versus modo JSON
O recurso de saídas estruturadas é a evolução do modo JSON. Embora ambos garantam a geração de JSON válido, apenas as saídas estruturadas garantem a conformidade com o esquema. Tanto as saídas estruturadas quanto o modo JSON são compatíveis com a Responses API, a API chat completions, a API Assistants, a API de ajuste fino e a API de processamento em lote.
Recomendamos usar sempre saídas estruturadas em vez do modo JSON, quando possível.
No entanto, as saídas estruturadas com response_format: {type: "json_schema", ...} só são compatíveis com as versões dos modelos gpt-4o-mini, gpt-4o-mini-2024-07-18, gpt-4o-2024-08-06 e posteriores.
| Saídas estruturadas | Modo JSON | |
|---|---|---|
| Gera JSON válido | Sim | Sim |
| Segue o esquema | Sim (veja os esquemas compatíveis) | Não |
| Modelos compatíveis | gpt-4o-mini, gpt-4o-2024-08-06 e posteriores | gpt-3.5-turbo, gpt-4-*, gpt-4o-* e modelos GPT-5 compatíveis |
| Ativação | response_format: { type: "json_schema", json_schema: {"strict": true, "schema": ...} } | response_format: { type: "json_object" } |
| Saídas estruturadas | Modo JSON | |
|---|---|---|
| Gera JSON válido | Sim | Sim |
| Segue o esquema | Sim (veja os esquemas compatíveis) | Não |
| Modelos compatíveis | gpt-4o-mini, gpt-4o-2024-08-06 e posteriores | gpt-3.5-turbo, gpt-4-*, gpt-4o-* e modelos GPT-5 compatíveis |
| Ativação | text: { format: { type: "json_schema", "strict": true, "schema": ... } } | text: { format: { type: "json_object" } } |
Exemplos
Cadeia de pensamento
Você pode pedir ao modelo que apresente uma resposta estruturada, passo a passo, para guiar o usuário pela solução.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import OpenAI from "openai";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/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 completion = await openai.chat.completions.parse({
model: "gpt-6-astra",
messages: [
{
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" },
],
response_format: zodResponseFormat(MathReasoning, "math_reasoning"),
});
const math_reasoning = completion.choices[0].message.parsed;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29from pydantic import BaseModel
from openai import OpenAI
client = OpenAI()
class Step(BaseModel):
explanation: str
output: str
class MathReasoning(BaseModel):
steps: list[Step]
final_answer: str
completion = client.chat.completions.parse(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format=MathReasoning,
)
math_reasoning = completion.choices[0].message.parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
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,
}
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful math tutor. Guide the user through the solution step by step."),
openai.UserMessage("how can I solve 8x + 7 = -23"),
},
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "math_reasoning", Schema: schema, Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
fmt.Println(completion.Choices[0].Message.Content)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
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);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.addUserMessage("How can I solve 8x + 7 = -23?")
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "math_reasoning", "strict", true, "schema", schema))))
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(System.out::println);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46using System.Text.Json;
using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful math tutor. Guide the user through the solution step by step."), new UserChatMessage("How can I solve 8x + 7 = -23?")],
options
);
using JsonDocument parsed = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(parsed.RootElement);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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?"
}
],
response_format: {
type: :json_schema,
json_schema: {
name: "math_reasoning",
strict: true,
schema: math_schema
}
}
)
puts(completion.choices.fetch(0).message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"messages": [
{
"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"
}
],
"response_format": {
"type": "json_schema",
"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
}
}
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32import 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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29from 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_parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53package 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())
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73import 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()));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49using 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48require "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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43curl 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
}
}
}'Exemplo de resposta
12345678910111213141516171819202122232425{
"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"
}
Extração de dados estruturados
Você pode definir campos estruturados para extrair de dados de entrada não estruturados, como artigos científicos.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import OpenAI from "openai";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/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 completion = await openai.chat.completions.parse({
model: "gpt-6-astra",
messages: [
{
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: "..." },
],
response_format: zodResponseFormat(
ResearchPaperExtraction,
"research_paper_extraction"
),
});
const research_paper = completion.choices[0].message.parsed;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36from pydantic import BaseModel
from openai import OpenAI
client = OpenAI()
class ResearchPaperExtraction(BaseModel):
title: str
authors: list[str]
abstract: str
keywords: list[str]
completion = client.chat.completions.parse(
model="gpt-6-astra",
messages=[
{
"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."
),
},
],
response_format=ResearchPaperExtraction,
)
research_paper = completion.choices[0].message.parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
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,
}
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("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."),
openai.UserMessage(researchPaperText),
},
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "research_paper_extraction", Schema: schema, Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
fmt.Println(completion.Choices[0].Message.Content)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
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);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"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.")
.addUserMessage(
"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.")
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of(
"name",
"research_paper_extraction",
"strict",
true,
"schema",
schema))))
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(System.out::println);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49using System.Text.Json;
using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"research_paper",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[
new SystemChatMessage("Extract the title, authors, abstract, and keywords from the research paper."),
new UserChatMessage(
"""
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.
"""
),
],
options
);
using JsonDocument parsed = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(parsed.RootElement);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
role: :system,
content: "Extract structured data from the supplied research paper text."
},
{
role: :user,
content: research_paper
}
],
response_format: {
type: :json_schema,
json_schema: {
name: "research_paper_extraction",
strict: true,
schema: paper_schema
}
}
)
puts(completion.choices.fetch(0).message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"messages": [
{
"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": "..."
}
],
"response_format": {
"type": "json_schema",
"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
}
}
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29import 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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36from 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_parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52package 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())
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69import 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()));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51using 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51require "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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40curl 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
}
}
}'Exemplo de resposta
12345678910111213{
"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"
]
}
Geração de interfaces
Você pode gerar HTML válido representando-o como estruturas de dados recursivas com restrições, como enumerações.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33import OpenAI from "openai";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/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 completion = await openai.chat.completions.parse({
model: "gpt-6-astra",
messages: [
{
role: "system",
content: "You are a UI generator AI. Convert the user input into a UI.",
},
{ role: "user", content: "Make a User Profile Form" },
],
response_format: zodResponseFormat(UI, "ui"),
});
const ui = completion.choices[0].message.parsed;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49from enum import Enum
from pydantic import BaseModel
from openai import OpenAI
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
completion = client.chat.completions.parse(
model="gpt-6-astra",
messages=[
{
"role": "system",
"content": "You are a UI generator AI. Convert the user input into a UI.",
},
{"role": "user", "content": "Make a User Profile Form"},
],
response_format=Response,
)
ui = completion.choices[0].message.parsed
print(ui)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
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,
}
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a UI generator AI. Convert the user input into a UI."),
openai.UserMessage("Make a User Profile Form"),
},
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "ui", Description: openai.String("Dynamically generated UI"), Schema: schema, Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
fmt.Println(completion.Choices[0].Message.Content)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.List;
import java.util.Map;
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
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))),
"required",
List.of("type", "label", "children", "attributes"),
"additionalProperties",
false);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage("Convert the user request into a UI definition.")
.addUserMessage("Make a user profile form.")
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of(
"name",
"ui",
"description",
"A dynamically generated UI",
"strict",
true,
"schema",
schema))))
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(System.out::println);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55using System.Text.Json;
using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
}
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"ui",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a UI generator. Convert the user request into a component tree."), new UserChatMessage("Make a User Profile Form")],
options
);
using JsonDocument parsed = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(parsed.RootElement);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
role: :system,
content: "Convert the user request into a UI definition."
},
{
role: :user,
content: "Make a user profile form."
}
],
response_format: {
type: :json_schema,
json_schema: {
name: "ui",
description: "A dynamically generated UI",
strict: true,
schema: ui_schema
}
}
)
puts(completion.choices.fetch(0).message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"messages": [
{
"role": "system",
"content": "You are a UI generator AI. Convert the user input into a UI."
},
{
"role": "user",
"content": "Make a User Profile Form"
}
],
"response_format": {
"type": "json_schema",
"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
}
}
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38import 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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49from 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_parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46package 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())
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87import 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()));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58using 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56require "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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64curl 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
}
}
}'Exemplo de resposta
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172{
"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"
}
]
}
Moderação
Você pode classificar entradas em várias categorias, uma prática comum na moderação.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import OpenAI from "openai";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/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 completion = await openai.chat.completions.parse({
model: "gpt-6-astra",
messages: [
{
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?" },
],
response_format: zodResponseFormat(ContentCompliance, "content_compliance"),
});
const compliance = completion.choices[0].message.parsed;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32from enum import Enum
from pydantic import BaseModel
from openai import OpenAI
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
completion = client.chat.completions.parse(
model="gpt-6-astra",
messages=[
{
"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?"},
],
response_format=ContentCompliance,
)
compliance = completion.choices[0].message.parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
schema := contentComplianceSchema()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("Determine if the user input violates specific guidelines and explain if they do."),
openai.UserMessage("How do I prepare for a job interview?"),
},
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
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(completion.Choices[0].Message.Content)
}
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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
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);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"Determine whether the user input violates the guidelines and explain any violation.")
.addUserMessage("How do I prepare for a job interview?")
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of(
"name",
"content_compliance",
"description",
"Determines whether content violates moderation rules",
"strict",
true,
"schema",
schema))))
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(System.out::println);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39using System.Text.Json;
using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"content_compliance",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("Determine whether the user input violates content guidelines."), new UserChatMessage("How do I prepare for a job interview?")],
options
);
using JsonDocument parsed = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(parsed.RootElement);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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?"
}
],
response_format: {
type: :json_schema,
json_schema: {
name: "content_compliance",
description: "Determines whether content violates moderation rules",
strict: true,
schema: compliance_schema
}
}
)
puts(completion.choices.fetch(0).message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"messages": [
{
"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?"
}
],
"response_format": {
"type": "json_schema",
"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
}
}
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import 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;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33from 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_parsed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43package 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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73import 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()));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42using 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48require "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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44curl 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
}
}
}'Exemplo de resposta
12345{
"is_violating": false,
"category": null,
"explanation_if_violating": null
}
Como usar saídas estruturadas com response_format
Você pode usar saídas estruturadas com a nova função auxiliar do SDK para converter a saída do modelo para o formato desejado ou especificar o esquema JSON diretamente.
Observação: para modelos com ajuste fino, a primeira solicitação feita com qualquer esquema terá latência adicional enquanto nossa API processa o esquema, mas as solicitações subsequentes com o mesmo esquema não terão latência adicional. Outros modelos não têm essa limitação.
Primeiro, defina um objeto ou uma estrutura de dados que represente o esquema JSON que o modelo deverá seguir. Consulte os exemplos no início deste guia como referência.
Embora as saídas estruturadas ofereçam suporte a grande parte do JSON Schema, alguns recursos não estão disponíveis por questões de desempenho ou motivos técnicos. Consulte mais detalhes aqui.
Por exemplo, você pode definir um objeto assim:
1
2
3
4
5
6
7
8
9
10
11
12import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
const Step = z.object({
explanation: z.string(),
output: z.string(),
});
const MathResponse = z.object({
steps: z.array(Step),
final_answer: z.string(),
});1
2
3
4
5
6
7
8
9
10
11from pydantic import BaseModel
class Step(BaseModel):
explanation: str
output: str
class MathResponse(BaseModel):
steps: list[Step]
final_answer: strDicas para sua estrutura de dados
Para maximizar a qualidade das respostas geradas pelo modelo, recomendamos o seguinte:
- Dê nomes claros e intuitivos às chaves
- Crie títulos e descrições claros para as chaves importantes da sua estrutura
- Crie e use avaliações para determinar a estrutura mais adequada ao seu caso de uso
Você pode usar o método parse para converter automaticamente a resposta JSON no objeto que você definiu.
Internamente, o SDK fornece o esquema JSON correspondente à sua estrutura de dados e depois converte a resposta em um objeto.
1
2
3
4
5
6
7
8
9
10
11
12const completion = await openai.chat.completions.parse({
model: "gpt-6-astra",
messages: [
{
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" },
],
response_format: zodResponseFormat(MathResponse, "math_response"),
});1
2
3
4
5
6
7
8
9
10
11completion = client.chat.completions.parse(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format=MathResponse,
)Em alguns casos, o modelo pode não gerar uma resposta válida que corresponda ao esquema JSON fornecido.
Isso pode acontecer quando o modelo se recusa a responder por motivos de segurança ou quando, por exemplo, o limite máximo de tokens é atingido e a resposta fica incompleta.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70try {
const completion = await openai.chat.completions.create({
model: "gpt-6-astra",
messages: [
{
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",
},
],
store: true,
response_format: {
type: "json_schema",
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,
},
},
max_completion_tokens: 50,
});
if (completion.choices[0].finish_reason === "length") {
// Handle the case where the model did not return a complete response
throw new Error("Incomplete response");
}
const math_response = completion.choices[0].message;
if (math_response.refusal) {
// handle refusal
console.log(math_response.refusal);
} else if (math_response.content) {
console.log(math_response.content);
} else {
throw new Error("No response content");
}
} catch (e) {
// Handle edge cases
console.error(e);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54try:
response = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format={
"type": "json_schema",
"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_completion_tokens=50,
)
if response.choices[0].finish_reason == "length":
raise Exception("Incomplete response")
math_response = response.choices[0].message
if math_response.refusal:
print(math_response.refusal)
elif math_response.content:
print(math_response.content)
else:
raise Exception("No response content")
except Exception as e:
# handle errors like finish_reason, refusal, content_filter, etc.
print(e)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56package main
import (
"context"
"errors"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful math tutor. Guide the user through the solution step by step."),
openai.UserMessage("how can I solve 8x + 7 = -23"),
},
Store: openai.Bool(true),
MaxCompletionTokens: openai.Int(1024),
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
choice := completion.Choices[0]
if choice.FinishReason == "length" {
panic(errors.New("incomplete response"))
}
if choice.Message.Refusal != "" {
fmt.Println(choice.Message.Refusal)
return
}
if choice.Message.Content == "" {
panic(errors.New("no response content"))
}
fmt.Println(choice.Message.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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.List;
import java.util.Map;
Map<String, Object> stepSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false);
Map<String, Object> mathSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps", Map.of("type", "array", "items", stepSchema),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.addUserMessage("How can I solve 8x + 7 = -23?")
.maxCompletionTokens(1024)
.store(true)
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "math_response", "strict", true, "schema", mathSchema))))
.build();
var choice = client.chat().completions().create(params).choices().get(0);
if (choice.finishReason().equals(ChatCompletion.Choice.FinishReason.LENGTH)) {
System.out.println("Incomplete response");
} else if (choice.message().refusal().isPresent()) {
System.out.println(choice.message().refusal().orElseThrow());
} else {
System.out.println(
choice
.message()
.content()
.orElseThrow(() -> new IllegalStateException("No response content")));
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
MaxOutputTokenCount = 300,
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful math tutor. Guide the user through the solution step by step."), new UserChatMessage("How can I solve 8x + 7 = -23?")],
options
);
if (completion.FinishReason == ChatFinishReason.Length)
{
throw new InvalidOperationException("The structured response was incomplete.");
}
if (completion.FinishReason == ChatFinishReason.ContentFilter)
{
throw new InvalidOperationException("The structured response was interrupted by the content filter.");
}
if (!string.IsNullOrEmpty(completion.Refusal))
{
Console.WriteLine(completion.Refusal);
}
else if (completion.Content.Count > 0)
{
Console.WriteLine(completion.Content[0].Text);
}
else
{
throw new InvalidOperationException("The completion did not contain a response.");
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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_completion_tokens: 1_024,
store: true,
response_format: {
type: :json_schema,
json_schema: {
name: "math_response",
strict: true,
schema: math_schema
}
}
)
choice = completion.choices.fetch(0)
if choice.finish_reason == OpenAI::Chat::ChatCompletion::Choice::FinishReason::LENGTH
raise "Incomplete response"
elsif choice.message.refusal
puts(choice.message.refusal)
else
content = choice.message.content or raise "No response content"
puts(content)
endPrimeiro, você deve definir o JSON Schema que o modelo deverá seguir. Consulte os exemplos no início deste guia como referência.
Embora as saídas estruturadas ofereçam suporte a grande parte do JSON Schema, alguns recursos estão indisponíveis por motivos técnicos ou de desempenho. Veja mais detalhes aqui.
Dicas para seu JSON Schema
Para maximizar a qualidade das respostas geradas pelo modelo, recomendamos o seguinte:
- Dê nomes claros e intuitivos às chaves
- Crie títulos e descrições claros para as chaves importantes da sua estrutura
- Crie e use avaliações para determinar a estrutura mais adequada ao seu caso de uso
Para usar saídas estruturadas, basta especificar
response_format: { "type": "json_schema", "json_schema": … , "strict": true } text: { format: { type: "json_schema", "strict": true, "schema": … } } Por exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41const response = await openai.chat.completions.create({
model: "gpt-6-astra",
messages: [
{
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" },
],
store: true,
response_format: {
type: "json_schema",
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.choices[0].message.content);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39response = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format={
"type": "json_schema",
"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.choices[0].message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
schema := mathSchema()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful math tutor. Guide the user through the solution step by step."),
openai.UserMessage("how can I solve 8x + 7 = -23"),
},
Store: openai.Bool(true),
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "math_response", Schema: schema, Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
fmt.Println(completion.Choices[0].Message.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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.List;
import java.util.Map;
Map<String, Object> stepSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false);
Map<String, Object> mathSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps", Map.of("type", "array", "items", stepSchema),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.addUserMessage("How can I solve 8x + 7 = -23?")
.store(true)
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "math_response", "strict", true, "schema", mathSchema))))
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(System.out::println);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46using System.Text.Json;
using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful math tutor. Guide the user through the solution step by step."), new UserChatMessage("How can I solve 8x + 7 = -23?")],
options
);
using JsonDocument parsed = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(parsed.RootElement);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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?"
}
],
store: true,
response_format: {
type: :json_schema,
json_schema: {
name: "math_response",
strict: true,
schema: math_schema
}
}
)
puts(completion.choices.fetch(0).message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"messages": [
{
"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"
}
],
"response_format": {
"type": "json_schema",
"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
}
}
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40const 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39response = 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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45package 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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73import 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()));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49using 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47require "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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43curl 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
}
}
}'Observação: a primeira solicitação feita com qualquer esquema terá uma latência adicional enquanto nossa API processa o esquema, mas as solicitações seguintes com o mesmo esquema não terão essa latência adicional.
Em alguns casos, o modelo pode não gerar uma resposta válida que corresponda ao esquema JSON fornecido.
Isso pode acontecer quando o modelo se recusa a responder por motivos de segurança ou quando, por exemplo, o limite máximo de tokens é atingido e a resposta fica incompleta.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70try {
const completion = await openai.chat.completions.create({
model: "gpt-6-astra",
messages: [
{
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",
},
],
store: true,
response_format: {
type: "json_schema",
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,
},
},
max_completion_tokens: 50,
});
if (completion.choices[0].finish_reason === "length") {
// Handle the case where the model did not return a complete response
throw new Error("Incomplete response");
}
const math_response = completion.choices[0].message;
if (math_response.refusal) {
// handle refusal
console.log(math_response.refusal);
} else if (math_response.content) {
console.log(math_response.content);
} else {
throw new Error("No response content");
}
} catch (e) {
// Handle edge cases
console.error(e);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54try:
response = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format={
"type": "json_schema",
"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_completion_tokens=50,
)
if response.choices[0].finish_reason == "length":
raise Exception("Incomplete response")
math_response = response.choices[0].message
if math_response.refusal:
print(math_response.refusal)
elif math_response.content:
print(math_response.content)
else:
raise Exception("No response content")
except Exception as e:
# handle errors like finish_reason, refusal, content_filter, etc.
print(e)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56package main
import (
"context"
"errors"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful math tutor. Guide the user through the solution step by step."),
openai.UserMessage("how can I solve 8x + 7 = -23"),
},
Store: openai.Bool(true),
MaxCompletionTokens: openai.Int(1024),
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
choice := completion.Choices[0]
if choice.FinishReason == "length" {
panic(errors.New("incomplete response"))
}
if choice.Message.Refusal != "" {
fmt.Println(choice.Message.Refusal)
return
}
if choice.Message.Content == "" {
panic(errors.New("no response content"))
}
fmt.Println(choice.Message.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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.List;
import java.util.Map;
Map<String, Object> stepSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false);
Map<String, Object> mathSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps", Map.of("type", "array", "items", stepSchema),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.addUserMessage("How can I solve 8x + 7 = -23?")
.maxCompletionTokens(1024)
.store(true)
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "math_response", "strict", true, "schema", mathSchema))))
.build();
var choice = client.chat().completions().create(params).choices().get(0);
if (choice.finishReason().equals(ChatCompletion.Choice.FinishReason.LENGTH)) {
System.out.println("Incomplete response");
} else if (choice.message().refusal().isPresent()) {
System.out.println(choice.message().refusal().orElseThrow());
} else {
System.out.println(
choice
.message()
.content()
.orElseThrow(() -> new IllegalStateException("No response content")));
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
MaxOutputTokenCount = 300,
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful math tutor. Guide the user through the solution step by step."), new UserChatMessage("How can I solve 8x + 7 = -23?")],
options
);
if (completion.FinishReason == ChatFinishReason.Length)
{
throw new InvalidOperationException("The structured response was incomplete.");
}
if (completion.FinishReason == ChatFinishReason.ContentFilter)
{
throw new InvalidOperationException("The structured response was interrupted by the content filter.");
}
if (!string.IsNullOrEmpty(completion.Refusal))
{
Console.WriteLine(completion.Refusal);
}
else if (completion.Content.Count > 0)
{
Console.WriteLine(completion.Content[0].Text);
}
else
{
throw new InvalidOperationException("The completion did not contain a response.");
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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_completion_tokens: 1_024,
store: true,
response_format: {
type: :json_schema,
json_schema: {
name: "math_response",
strict: true,
schema: math_schema
}
}
)
choice = completion.choices.fetch(0)
if choice.finish_reason == OpenAI::Chat::ChatCompletion::Choice::FinishReason::LENGTH
raise "Incomplete response"
elsif choice.message.refusal
puts(choice.message.refusal)
else
content = choice.message.content or raise "No response content"
puts(content)
end1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77try {
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);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61try:
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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66package 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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93import 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());
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68using 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
);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65require "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)
endDepois de confirmar que a resposta contém JSON compatível com seu esquema, converta-o nas estruturas de dados nativas da sua linguagem. Em linguagens tipadas, você também pode modelar os dados com um tipo ou uma classe correspondente.
Por exemplo:
1
2
3
4
5// The request that produces `response` appears earlier in this guide.
const content = response.choices[0].message.content;
if (!content) throw new Error("The response did not contain JSON output.");
const solution = JSON.parse(content);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18from pydantic import BaseModel, ValidationError
class Step(BaseModel):
explanation: str
output: str
class Solution(BaseModel):
steps: list[Step]
final_answer: str
try:
solution = Solution.model_validate_json(response.choices[0].message.content)
print(solution)
except ValidationError as error:
print(error.json())1System.out.println(new ObjectMapper().readTree(content));1
2
3
4
5content = completion.choices.fetch(0).message.content
raise "Response did not contain JSON output." if content.nil?
solution = JSON.parse(content)
puts(solution)Como usar saídas estruturadas com text.format
Primeiro, você deve definir o JSON Schema que o modelo deverá seguir. Consulte os exemplos no início deste guia como referência.
Embora as saídas estruturadas ofereçam suporte a grande parte do JSON Schema, alguns recursos estão indisponíveis por motivos técnicos ou de desempenho. Veja mais detalhes aqui.
Dicas para seu JSON Schema
Para maximizar a qualidade das respostas geradas pelo modelo, recomendamos o seguinte:
- Dê nomes claros e intuitivos às chaves
- Crie títulos e descrições claros para as chaves importantes da sua estrutura
- Crie e use avaliações para determinar a estrutura mais adequada ao seu caso de uso
Para usar saídas estruturadas, basta especificar
response_format: { "type": "json_schema", "json_schema": … , "strict": true } text: { format: { type: "json_schema", "strict": true, "schema": … } } Por exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41const response = await openai.chat.completions.create({
model: "gpt-6-astra",
messages: [
{
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" },
],
store: true,
response_format: {
type: "json_schema",
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.choices[0].message.content);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39response = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format={
"type": "json_schema",
"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.choices[0].message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
schema := mathSchema()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful math tutor. Guide the user through the solution step by step."),
openai.UserMessage("how can I solve 8x + 7 = -23"),
},
Store: openai.Bool(true),
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "math_response", Schema: schema, Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
fmt.Println(completion.Choices[0].Message.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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.List;
import java.util.Map;
Map<String, Object> stepSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false);
Map<String, Object> mathSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps", Map.of("type", "array", "items", stepSchema),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.addUserMessage("How can I solve 8x + 7 = -23?")
.store(true)
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "math_response", "strict", true, "schema", mathSchema))))
.build();
client.chat().completions().create(params).choices().stream()
.flatMap(choice -> choice.message().content().stream())
.forEach(System.out::println);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46using System.Text.Json;
using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful math tutor. Guide the user through the solution step by step."), new UserChatMessage("How can I solve 8x + 7 = -23?")],
options
);
using JsonDocument parsed = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(parsed.RootElement);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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?"
}
],
store: true,
response_format: {
type: :json_schema,
json_schema: {
name: "math_response",
strict: true,
schema: math_schema
}
}
)
puts(completion.choices.fetch(0).message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43curl https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6-astra",
"messages": [
{
"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"
}
],
"response_format": {
"type": "json_schema",
"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
}
}
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40const 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39response = 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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45package 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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73import 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()));1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49using 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47require "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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43curl 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
}
}
}'Observação: a primeira solicitação feita com qualquer esquema terá uma latência adicional enquanto nossa API processa o esquema, mas as solicitações seguintes com o mesmo esquema não terão essa latência adicional.
Em alguns casos, o modelo pode não gerar uma resposta válida que corresponda ao esquema JSON fornecido.
Isso pode acontecer quando o modelo se recusa a responder por motivos de segurança ou quando, por exemplo, o limite máximo de tokens é atingido e a resposta fica incompleta.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70try {
const completion = await openai.chat.completions.create({
model: "gpt-6-astra",
messages: [
{
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",
},
],
store: true,
response_format: {
type: "json_schema",
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,
},
},
max_completion_tokens: 50,
});
if (completion.choices[0].finish_reason === "length") {
// Handle the case where the model did not return a complete response
throw new Error("Incomplete response");
}
const math_response = completion.choices[0].message;
if (math_response.refusal) {
// handle refusal
console.log(math_response.refusal);
} else if (math_response.content) {
console.log(math_response.content);
} else {
throw new Error("No response content");
}
} catch (e) {
// Handle edge cases
console.error(e);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54try:
response = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format={
"type": "json_schema",
"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_completion_tokens=50,
)
if response.choices[0].finish_reason == "length":
raise Exception("Incomplete response")
math_response = response.choices[0].message
if math_response.refusal:
print(math_response.refusal)
elif math_response.content:
print(math_response.content)
else:
raise Exception("No response content")
except Exception as e:
# handle errors like finish_reason, refusal, content_filter, etc.
print(e)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56package main
import (
"context"
"errors"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful math tutor. Guide the user through the solution step by step."),
openai.UserMessage("how can I solve 8x + 7 = -23"),
},
Store: openai.Bool(true),
MaxCompletionTokens: openai.Int(1024),
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "math_response", Schema: mathSchema(), Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
choice := completion.Choices[0]
if choice.FinishReason == "length" {
panic(errors.New("incomplete response"))
}
if choice.Message.Refusal != "" {
fmt.Println(choice.Message.Refusal)
return
}
if choice.Message.Content == "" {
panic(errors.New("no response content"))
}
fmt.Println(choice.Message.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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.List;
import java.util.Map;
Map<String, Object> stepSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"explanation", Map.of("type", "string"),
"output", Map.of("type", "string")),
"required",
List.of("explanation", "output"),
"additionalProperties",
false);
Map<String, Object> mathSchema =
Map.of(
"type",
"object",
"properties",
Map.of(
"steps", Map.of("type", "array", "items", stepSchema),
"final_answer", Map.of("type", "string")),
"required",
List.of("steps", "final_answer"),
"additionalProperties",
false);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.addUserMessage("How can I solve 8x + 7 = -23?")
.maxCompletionTokens(1024)
.store(true)
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "math_response", "strict", true, "schema", mathSchema))))
.build();
var choice = client.chat().completions().create(params).choices().get(0);
if (choice.finishReason().equals(ChatCompletion.Choice.FinishReason.LENGTH)) {
System.out.println("Incomplete response");
} else if (choice.message().refusal().isPresent()) {
System.out.println(choice.message().refusal().orElseThrow());
} else {
System.out.println(
choice
.message()
.content()
.orElseThrow(() -> new IllegalStateException("No response content")));
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
MaxOutputTokenCount = 300,
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful math tutor. Guide the user through the solution step by step."), new UserChatMessage("How can I solve 8x + 7 = -23?")],
options
);
if (completion.FinishReason == ChatFinishReason.Length)
{
throw new InvalidOperationException("The structured response was incomplete.");
}
if (completion.FinishReason == ChatFinishReason.ContentFilter)
{
throw new InvalidOperationException("The structured response was interrupted by the content filter.");
}
if (!string.IsNullOrEmpty(completion.Refusal))
{
Console.WriteLine(completion.Refusal);
}
else if (completion.Content.Count > 0)
{
Console.WriteLine(completion.Content[0].Text);
}
else
{
throw new InvalidOperationException("The completion did not contain a response.");
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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_completion_tokens: 1_024,
store: true,
response_format: {
type: :json_schema,
json_schema: {
name: "math_response",
strict: true,
schema: math_schema
}
}
)
choice = completion.choices.fetch(0)
if choice.finish_reason == OpenAI::Chat::ChatCompletion::Choice::FinishReason::LENGTH
raise "Incomplete response"
elsif choice.message.refusal
puts(choice.message.refusal)
else
content = choice.message.content or raise "No response content"
puts(content)
end1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77try {
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);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61try:
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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66package 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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93import 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());
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68using 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
);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65require "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)
endDepois de confirmar que a resposta contém JSON compatível com seu esquema, converta-o nas estruturas de dados nativas da sua linguagem. Em linguagens tipadas, você também pode modelar os dados com um tipo ou uma classe correspondente.
Por exemplo:
1
2
3
4
5// The request that produces `response` appears earlier in this guide.
const content = response.choices[0].message.content;
if (!content) throw new Error("The response did not contain JSON output.");
const solution = JSON.parse(content);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18from pydantic import BaseModel, ValidationError
class Step(BaseModel):
explanation: str
output: str
class Solution(BaseModel):
steps: list[Step]
final_answer: str
try:
solution = Solution.model_validate_json(response.choices[0].message.content)
print(solution)
except ValidationError as error:
print(error.json())1System.out.println(new ObjectMapper().readTree(content));1
2
3
4
5content = completion.choices.fetch(0).message.content
raise "Response did not contain JSON output." if content.nil?
solution = JSON.parse(content)
puts(solution)Recusas com saídas estruturadas
Ao usar saídas estruturadas com entradas geradas por usuários, os modelos da OpenAI podem ocasionalmente se recusar a atender à solicitação por motivos de segurança. Como uma recusa não segue necessariamente o esquema fornecido em response_format, a resposta da API incluirá um novo campo chamado refusal para indicar que o modelo se recusou a atender à solicitação.
Quando a propriedade refusal aparecer no objeto de saída, você poderá exibir a recusa na interface ou incluir lógica condicional no código que consome a resposta para tratar a solicitação recusada.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31const Step = z.object({
explanation: z.string(),
output: z.string(),
});
const MathReasoning = z.object({
steps: z.array(Step),
final_answer: z.string(),
});
const completion = await openai.chat.completions.parse({
model: "gpt-6-astra",
messages: [
{
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" },
],
response_format: zodResponseFormat(MathReasoning, "math_reasoning"),
});
const math_reasoning = completion.choices[0].message;
// If the model refuses to respond, you will get a refusal message
if (math_reasoning.refusal) {
console.log(math_reasoning.refusal);
} else {
console.log(math_reasoning.parsed);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class Step(BaseModel):
explanation: str
output: str
class MathReasoning(BaseModel):
steps: list[Step]
final_answer: str
completion = client.chat.completions.parse(
model="gpt-6-astra",
messages=[
{
"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"},
],
response_format=MathReasoning,
)
math_reasoning = completion.choices[0].message
# If the model refuses to respond, you will get a refusal message
if math_reasoning.refusal:
print(math_reasoning.refusal)
else:
print(math_reasoning.parsed)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful math tutor. Guide the user through the solution step by step."),
openai.UserMessage("how can I solve 8x + 7 = -23"),
},
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONSchema: &shared.ResponseFormatJSONSchemaParam{JSONSchema: shared.ResponseFormatJSONSchemaJSONSchemaParam{
Name: "math_reasoning", Schema: mathSchema(), Strict: openai.Bool(true),
}},
},
})
if err != nil {
panic(err)
}
message := completion.Choices[0].Message
if message.Refusal != "" {
fmt.Println(message.Refusal)
return
}
fmt.Println(message.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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
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);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage(
"You are a helpful math tutor. Guide the user through the solution step by step.")
.addUserMessage("How can I solve 8x + 7 = -23?")
.putAdditionalBodyProperty(
"response_format",
JsonValue.from(
Map.of(
"type",
"json_schema",
"json_schema",
Map.of("name", "math_reasoning", "strict", true, "schema", schema))))
.build();
var message = client.chat().completions().create(params).choices().get(0).message();
System.out.println(message.refusal().or(() -> message.content()).orElseThrow());1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, 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
}
"""
);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
"math_response",
schema,
jsonSchemaIsStrict: true
),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful math tutor. Guide the user through the solution step by step."), new UserChatMessage("How can I solve 8x + 7 = -23?")],
options
);
if (!string.IsNullOrEmpty(completion.Refusal))
{
Console.WriteLine(completion.Refusal);
}
else
{
Console.WriteLine(completion.Content[0].Text);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48require "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
}
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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?"
}
],
response_format: {
type: :json_schema,
json_schema: {
name: "math_reasoning",
strict: true,
schema: math_schema
}
}
)
message = completion.choices.fetch(0).message
puts(message.refusal || message.content)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44const 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);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36class 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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57package 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,
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79import 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()));
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55using 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
);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58require "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
endA resposta da API em caso de recusa será semelhante a esta:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28{
"id": "chatcmpl-9nYAG9LPNonX8DAyrkwYfemr3C8HC",
"object": "chat.completion",
"created": 1721596428,
"model": "gpt-4o-2024-08-06",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"refusal": "I'm sorry, I cannot assist with that request."
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 81,
"completion_tokens": 11,
"total_tokens": 92,
"completion_tokens_details": {
"reasoning_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": "fp_3407719c7f"
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32{
"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": [
{
"type": "refusal",
"refusal": "I'm sorry, I cannot assist with that request."
}
]
}],
"usage": {
"input_tokens": 81,
"output_tokens": 11,
"total_tokens": 92,
"output_tokens_details": {
"reasoning_tokens": 0,
}
},
}Dicas e práticas recomendadas
Como lidar com entradas geradas por usuários
Se o seu aplicativo usa entradas geradas por usuários, certifique-se de que o prompt inclua instruções sobre como lidar com situações em que a entrada não pode resultar em uma resposta válida.
O modelo sempre tentará seguir o esquema fornecido, o que pode resultar em alucinações se a entrada não tiver nenhuma relação com o esquema.
Você pode incluir instruções no prompt para especificar que deseja retornar parâmetros vazios ou uma frase específica caso o modelo detecte que a entrada é incompatível com a tarefa.
Como lidar com erros
As saídas estruturadas ainda podem conter erros. Se você encontrar erros, tente ajustar suas instruções, fornecer exemplos nas instruções do sistema ou dividir as tarefas em subtarefas mais simples. Consulte o guia de engenharia de prompt para obter mais orientações sobre como ajustar suas entradas.
Evite divergências no esquema JSON
Para evitar divergências entre seu JSON Schema e os tipos correspondentes na sua linguagem de programação, recomendamos fortemente usar os recursos auxiliares nativos dos SDKs para esquemas, quando disponíveis.
Se preferir especificar o esquema JSON diretamente, você pode adicionar regras de CI que sinalizem alterações no esquema JSON ou nos objetos de dados subjacentes, ou adicionar uma etapa de CI que gere automaticamente o JSON Schema a partir das definições de tipos (ou vice-versa).
Streaming
Você pode usar streaming para processar respostas do modelo ou argumentos de chamadas de função à medida que são gerados e interpretá-los como dados estruturados.
Assim, você não precisa esperar a resposta inteira ser concluída para começar a processá-la. Isso é especialmente útil se você quiser exibir os campos JSON um por um ou processar os argumentos de chamadas de função assim que estiverem disponíveis.
Recomendamos usar os SDKs para lidar com streaming de saídas estruturadas.
Você encontra um exemplo de como transmitir argumentos de chamadas de função por streaming sem a função auxiliar stream do SDK no guia de chamada de função.
Veja como transmitir uma resposta do modelo por streaming com a função auxiliar stream:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI();
const EntitiesSchema = z.object({
attributes: z.array(z.string()),
colors: z.array(z.string()),
animals: z.array(z.string()),
});
const stream = openai.chat.completions
.stream({
model: "gpt-6-astra",
messages: [
{ 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",
},
],
response_format: zodResponseFormat(EntitiesSchema, "entities"),
})
.on("refusal.done", () => console.log("request refused"))
.on("content.delta", ({ snapshot, parsed }) => {
console.log("content:", snapshot);
console.log("parsed:", parsed);
console.log();
})
.on("content.done", (props) => {
console.log(props);
});
await stream.done();
const finalCompletion = await stream.finalChatCompletion();
console.log(finalCompletion);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34from pydantic import BaseModel
from openai import OpenAI
class EntitiesModel(BaseModel):
attributes: list[str]
colors: list[str]
animals: list[str]
client = OpenAI()
with client.beta.chat.completions.stream(
model="gpt-6-astra",
messages=[
{"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",
},
],
response_format=EntitiesModel,
) as stream:
for event in stream:
if event.type == "content.delta":
if event.parsed is not None: # Print the parsed data as JSON
print("content.delta parsed:", event.parsed)
elif event.type == "content.done":
print("content.done")
elif event.type == "error":
print("Error in stream:", event.error)
final_completion = stream.get_final_completion()
print("Final completion:", final_completion)Você também pode usar a função auxiliar stream para interpretar argumentos de chamadas de função:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36import { zodFunction } from "openai/helpers/zod";
import OpenAI from "openai/index";
import { z } from "zod";
const GetWeatherArgs = z.object({
city: z.string(),
country: z.string(),
});
const client = new OpenAI();
const stream = client.chat.completions
.stream({
model: "gpt-5.6",
messages: [
{
role: "user",
content: "What's the weather like in SF and London?",
},
],
tools: [zodFunction({ name: "get_weather", parameters: GetWeatherArgs })],
})
.on("tool_calls.function.arguments.delta", (props) =>
console.log("tool_calls.function.arguments.delta", props)
)
.on("tool_calls.function.arguments.done", (props) =>
console.log("tool_calls.function.arguments.done", props)
)
.on("refusal.delta", ({ delta }) => {
process.stdout.write(delta);
})
.on("refusal.done", () => console.log("request refused"));
const completion = await stream.finalChatCompletion();
console.log("final completion:", completion);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33from pydantic import BaseModel
import openai
from openai import OpenAI
class GetWeather(BaseModel):
city: str
country: str
client = OpenAI()
with client.beta.chat.completions.stream(
model="gpt-5.6",
messages=[
{
"role": "user",
"content": "What's the weather like in SF and London?",
},
],
tools=[
openai.pydantic_function_tool(GetWeather, name="get_weather"),
],
parallel_tool_calls=True,
) as stream:
for event in stream:
if (
event.type == "tool_calls.function.arguments.delta"
or event.type == "tool_calls.function.arguments.done"
):
print(event)
print(stream.get_final_completion())1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37import { 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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35from 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)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86import 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());
});
});
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56require "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
endEsquemas compatíveis
As saídas estruturadas oferecem suporte a um subconjunto da linguagem JSON Schema.
Tipos compatíveis
Os seguintes tipos são compatíveis com saídas estruturadas:
- Cadeia de caracteres
- Número
- Booleano
- Inteiro
- Objeto
- Array
- Enum
- anyOf
Propriedades compatíveis
Além de especificar o tipo de uma propriedade, você pode definir algumas restrições adicionais:
Propriedades compatíveis com string:
pattern— Uma expressão regular à qual a cadeia de caracteres deve corresponder.format— Formatos predefinidos para cadeias de caracteres. Atualmente, há suporte para:date-timetimedatedurationemailhostnameipv4ipv6uuid
Propriedades compatíveis com number:
multipleOf— O número deve ser um múltiplo deste valor.maximum— O número deve ser menor ou igual a este valor.exclusiveMaximum— O número deve ser menor que este valor.minimum— O número deve ser maior ou igual a este valor.exclusiveMinimum— O número deve ser maior que este valor.
Propriedades compatíveis com array:
minItems— O array deve ter, no mínimo, esta quantidade de itens.maxItems— O array deve ter, no máximo, esta quantidade de itens.
Veja alguns exemplos de como usar essas restrições de tipo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27{
"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 @",
"pattern": "^@[a-zA-Z0-9_]+$"
},
"email": {
"type": "string",
"description": "The email of the user",
"format": "email"
}
},
"additionalProperties": false,
"required": [
"name", "username", "email"
]
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28{
"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",
"minimum": -130,
"maximum": 130
}
},
"additionalProperties": false,
"required": [
"location", "unit", "value"
]
}
}Observe que essas restrições ainda não são compatíveis com modelos que passaram por ajuste fino.
O elemento raiz deve ser um objeto e não pode usar anyOf
Observe que o elemento raiz de um esquema deve ser um objeto e não pode usar anyOf. Um padrão encontrado no Zod, por exemplo, é o uso de uma união discriminada, que gera um anyOf no nível superior. Por isso, um código como o seguinte não funcionará:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
const BaseResponseSchema = z.object({
/* ... */
});
const UnsuccessfulResponseSchema = z.object({
/* ... */
});
const finalSchema = z.discriminatedUnion("status", [
BaseResponseSchema,
UnsuccessfulResponseSchema,
]);
// Invalid JSON Schema for Structured Outputs
const json = zodResponseFormat(finalSchema, "final_schema");Todos os campos devem ser definidos como required
Para usar saídas estruturadas, todos os campos ou parâmetros de função devem ser especificados como required.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21{
"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,
"required": ["location", "unit"]
}
}Embora todos os campos devam ser obrigatórios (e o modelo retorne um valor para cada parâmetro), é possível simular um parâmetro opcional usando um tipo de união com null.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23{
"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", "null"],
"description": "The unit to return the temperature in",
"enum": ["F", "C"]
}
},
"additionalProperties": false,
"required": [
"location", "unit"
]
}
}Os objetos têm limites de profundidade de aninhamento e tamanho
Um esquema pode ter até 5.000 propriedades de objetos no total, com até 10 níveis de aninhamento.
Limites para o tamanho total das cadeias de caracteres
Em um esquema, o comprimento total das cadeias de caracteres de todos os nomes de propriedades, nomes de definições, valores de enum e valores de const não pode ultrapassar 120.000 caracteres.
Limites para o tamanho de enum
Um esquema pode ter até 1.000 valores de enum no total, considerando todas as propriedades enum.
Para uma única propriedade enum com valores do tipo cadeia de caracteres, o comprimento total das cadeias de caracteres de todos os valores de enum não pode ultrapassar 15.000 caracteres quando houver mais de 250 valores de enum.
É necessário sempre definir additionalProperties: false nos objetos
additionalProperties controla se um objeto pode conter chaves e valores adicionais que não foram definidos no JSON Schema.
As saídas estruturadas permitem gerar apenas as chaves e os valores especificados. Por isso, exigimos que os desenvolvedores definam additionalProperties: false para usar saídas estruturadas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23{
"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"]
}
},
"additionalProperties": false,
"required": [
"location", "unit"
]
}
}Ordem das chaves
Ao usar saídas estruturadas, os resultados serão gerados na mesma ordem das chaves no esquema.
Algumas palavras-chave específicas de tipos ainda não são compatíveis
- Composição:
allOf,not,dependentRequired,dependentSchemas,if,then,else
Para modelos que passaram por ajuste fino, também não oferecemos suporte ao seguinte:
- Para strings:
minLength,maxLength,pattern,format - Para números:
minimum,maximum,multipleOf - Para objetos:
patternProperties - Para arrays:
minItems,maxItems
Se você ativar as saídas estruturadas fornecendo strict: true e chamar a API com um esquema JSON Schema não compatível, receberá um erro.
Para anyOf, cada esquema aninhado deve ser válido de acordo com este subconjunto de JSON Schema
Veja um exemplo de esquema compatível que usa anyOf:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56{
"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"
]
}Há suporte a definições
Você pode usar definições para definir subesquemas referenciados ao longo do seu esquema. Veja um exemplo simples a seguir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37{
"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
}Há suporte a esquemas recursivos
Exemplo de esquema recursivo que usa # para indicar recursão na raiz.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47{
"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
}
}Exemplo de esquema recursivo que usa recursão explícita:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37{
"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"
]
}Modo JSON
O modo JSON é uma versão mais básica do recurso de saídas estruturadas. Enquanto o modo JSON garante que a saída do modelo seja um JSON válido, as saídas estruturadas garantem, de forma confiável, que a saída do modelo siga o esquema especificado. Recomendamos usar saídas estruturadas se houver suporte para o seu caso de uso.
Quando o modo JSON está ativado, a saída do modelo tem garantia de ser um JSON válido, exceto em alguns casos extremos que você deve detectar e tratar adequadamente.
Para ativar o modo JSON com Chat Completions, defina response_format como { "type": "json_object" }. Se você estiver usando chamada de função, o modo JSON estará sempre ativado.
Para ativar o modo JSON com a Responses API, você pode definir text.format como { "type": "json_object" }. Se você estiver usando chamada de função, o modo JSON estará sempre ativado.
Observações importantes:
- Ao usar o modo JSON, você deve sempre instruir o modelo a produzir JSON por meio de alguma mensagem na conversa, por exemplo, a mensagem do sistema. Se você não incluir uma instrução explícita para gerar JSON, o modelo poderá gerar um fluxo interminável de espaços em branco, e a solicitação poderá continuar em execução até atingir o limite de tokens. Para ajudar a evitar esse esquecimento, a API retornará um erro se a string "JSON" não aparecer em algum lugar do contexto.
- O modo JSON não garante que a saída siga um esquema específico, apenas que seja válida e possa ser analisada sem erros. Você deve usar saídas estruturadas para garantir que a saída siga seu esquema ou, se isso não for possível, usar uma biblioteca de validação e, possivelmente, novas tentativas para garantir que a saída siga o esquema desejado.
- Seu aplicativo deve detectar e tratar os casos extremos que podem fazer com que a saída do modelo não seja um objeto JSON completo (veja abaixo)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52const we_did_not_specify_stop_tokens = true;
try {
const response = await openai.chat.completions.create({
model: "gpt-6-astra",
messages: [
{
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: ...}",
},
],
store: true,
response_format: { type: "json_object" },
});
// Check if the conversation was too long for the context window, resulting in incomplete JSON
if (response.choices[0].finish_reason === "length") {
// your code should handle this error case
}
// Check if the OpenAI safety system refused the request and generated a refusal instead
if (response.choices[0].message.refusal) {
// your code should handle this error case
// In this case, the .content field will contain the explanation (if any) that the model generated for why it is refusing
console.log(response.choices[0].message.refusal);
}
// Check if the model's output included restricted content, so the generation of JSON was halted and may be partial
if (response.choices[0].finish_reason === "content_filter") {
// your code should handle this error case
}
if (response.choices[0].finish_reason === "stop") {
// 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) {
// If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object
// This will parse successfully and should now contain {"winner": "Los Angeles Dodgers"}
console.log(JSON.parse(response.choices[0].message.content));
} else {
// Check if the response.choices[0].message.content ends with one of your stop tokens and handle appropriately
}
}
} catch (e) {
// Your code should handle errors here, for example a network error calling the API
console.error(e);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42we_did_not_specify_stop_tokens = True
try:
response = client.chat.completions.create(
model="gpt-6-astra",
messages=[
{
"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"}.',
},
],
response_format={"type": "json_object"},
)
# Check if the conversation was too long for the context window, resulting in incomplete JSON
if response.choices[0].finish_reason == "length":
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 response.choices[0].message.refusal:
# your code should handle this error case
# In this case, the .content field will contain the explanation (if any) that the model generated for why it is refusing
print(response.choices[0].message.refusal)
# Check if the model's output included restricted content, so the generation of JSON was halted and may be partial
if response.choices[0].finish_reason == "content_filter":
raise RuntimeError("The response was interrupted by the content filter.")
if response.choices[0].finish_reason == "stop":
# 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:
# If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object
# This will parse successfully and should now contain "{"winner": "Los Angeles Dodgers"}"
print(response.choices[0].message.content)
except Exception as e:
# Your code should handle errors here, for example a network error calling the API
print(e)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44package main
import (
"context"
"encoding/json"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/shared"
)
func main() {
client := openai.NewClient()
completion, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{
Model: "gpt-6-astra",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful assistant designed to output JSON."),
openai.UserMessage("Who won the world series in 2020? Please respond in the format {winner: ...}"),
},
ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{
OfJSONObject: &shared.ResponseFormatJSONObjectParam{},
},
})
if err != nil {
panic(err)
}
choice := completion.Choices[0]
if choice.FinishReason == "length" || choice.FinishReason == "content_filter" {
fmt.Println("The JSON response is incomplete.")
return
}
if choice.Message.Refusal != "" {
fmt.Println(choice.Message.Refusal)
return
}
if choice.FinishReason == "stop" {
var value map[string]any
if err := json.Unmarshal([]byte(choice.Message.Content), &value); err != nil {
panic(err)
}
fmt.Println(value)
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import com.fasterxml.jackson.databind.ObjectMapper;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.io.IOException;
import java.util.Map;
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.addSystemMessage("You are a helpful assistant designed to output JSON.")
.addUserMessage("Who won the World Series in 2020? Respond as {winner: ...}.")
.putAdditionalBodyProperty(
"response_format", JsonValue.from(Map.of("type", "json_object")))
.build();
var choice = client.chat().completions().create(params).choices().get(0);
if (choice.finishReason().equals(ChatCompletion.Choice.FinishReason.LENGTH)
|| choice.finishReason().equals(ChatCompletion.Choice.FinishReason.CONTENT_FILTER)) {
System.out.println("The JSON response is incomplete.");
} else if (choice.message().refusal().isPresent()) {
System.out.println(choice.message().refusal().orElseThrow());
} else if (choice.finishReason().equals(ChatCompletion.Choice.FinishReason.STOP)) {
String content = choice.message().content().orElseThrow();
System.out.println(
new ObjectMapper()
.writerWithDefaultPrettyPrinter()
.writeValueAsString(new ObjectMapper().readTree(content)));
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35using OpenAI.Chat;
string key = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;
string model = "gpt-6-astra";
ChatClient client = new(model, key);
ChatCompletionOptions options = new()
{
ResponseFormat = ChatResponseFormat.CreateJsonObjectFormat(),
};
ChatCompletion completion = await client.CompleteChatAsync(
[new SystemChatMessage("You are a helpful assistant designed to output JSON."), new UserChatMessage("Who won the World Series in 2020? Respond with the winner in JSON.")],
options
);
if (completion.FinishReason == ChatFinishReason.Length)
{
Console.WriteLine("The response was truncated before the JSON completed.");
}
else if (completion.FinishReason == ChatFinishReason.ContentFilter)
{
Console.WriteLine("The response was interrupted by the content filter.");
}
else if (!string.IsNullOrEmpty(completion.Refusal))
{
Console.WriteLine(completion.Refusal);
}
else if (completion.FinishReason == ChatFinishReason.Stop && completion.Content.Count > 0)
{
Console.WriteLine(completion.Content[0].Text);
}
else
{
throw new InvalidOperationException("The completion did not contain a JSON response.");
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32require "json"
require "openai"
client = OpenAI::Client.new
completion = client.chat.completions.create(
model: "gpt-6-astra",
messages: [
{
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: ...}."
}
],
response_format: { type: :json_object }
)
choice = completion.choices.fetch(0)
finish_reason = choice.finish_reason
if [
OpenAI::Chat::ChatCompletion::Choice::FinishReason::LENGTH,
OpenAI::Chat::ChatCompletion::Choice::FinishReason::CONTENT_FILTER
].include?(finish_reason)
warn("The JSON response is incomplete.")
elsif choice.message.refusal
puts(choice.message.refusal)
elsif finish_reason == OpenAI::Chat::ChatCompletion::Choice::FinishReason::STOP
content = choice.message.content or raise "No response content"
puts(JSON.pretty_generate(JSON.parse(content)))
end1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60const 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];
// 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
// 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);
}
// 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") {
// 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) {
// If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object
// 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) {
// Your code should handle errors here, for example a network error calling the API
console.error(e);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51we_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
# 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
# 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)
# 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":
# 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:
# If you didn't specify any stop tokens, then the generation is complete and the content key will contain the serialized JSON object
# This will parse successfully and should now contain "{"winner": "Los Angeles Dodgers"}"
print(response.output_text)
except Exception as e:
# Your code should handle errors here, for example a network error calling the API
print(e)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57package 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)
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61import 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());
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46using 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}");
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33require "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
endRecursos
Para saber mais sobre saídas estruturadas, recomendamos consultar os seguintes recursos:
- Confira nosso cookbook introdutório sobre saídas estruturadas
- Aprenda como criar sistemas com múltiplos agentes usando saídas estruturadas