JSON est l’un des formats les plus utilisés au monde pour échanger des données entre applications.
Les sorties structurées garantissent que le modèle génère toujours des réponses conformes au schéma JSON que vous fournissez. Vous n’avez donc pas à craindre que le modèle omette une clé obligatoire ou invente une valeur absente d’une énumération.
Les sorties structurées présentent plusieurs avantages :
- Respect des types : vous n’avez plus à valider des réponses mal formatées ni à relancer les requêtes correspondantes.
- Refus explicites : votre code peut désormais détecter les refus du modèle pour des raisons de sécurité.
- Prompts plus simples : inutile d’insister dans vos prompts pour obtenir un format cohérent.
Outre la prise en charge de JSON Schema dans l’API REST, les bibliothèques OpenAI pour Python et JavaScript permettent de définir des schémas d’objets avec pydantic.BaseModel et z.object respectivement. L’exemple ci-dessous montre comment extraire des informations d’un texte non structuré et les restituer selon un schéma défini dans le code.
Le SDK Ruby prend en charge les schémas définis avec le type T::Struct de Sorbet et renvoie des résultats typés après analyse de la réponse.
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(", "))Modèles compatibles
Nos grands modèles de langage les plus récents prennent en charge les sorties structurées depuis GPT-4o. Pour un nouveau projet, commencez avec gpt-6-astra. Avec des modèles plus anciens, comme gpt-4-turbo et les versions antérieures, vous pouvez utiliser le mode JSON à la place.
Sorties structurées : choix entre l’appel de fonction et response_format
Sorties structurées : choix entre l’appel de fonction et text.format
L’API OpenAI permet d’utiliser les sorties structurées de deux façons :
- Avec l’appel de fonction
- Avec le format de réponse
json_schema
L’appel de fonction est utile pour donner aux modèles accès aux fonctionnalités de votre application.
Par exemple, vous pouvez créer un assistant IA qui aide les utilisateurs à gérer leurs commandes en donnant au modèle accès à des fonctions qui interrogent une base de données. Vous pouvez aussi lui donner accès à des fonctions qui interagissent avec l’interface utilisateur.
Les sorties structurées avec response_format conviennent mieux lorsque vous souhaitez définir le schéma que le modèle doit respecter dans sa réponse à l’utilisateur, plutôt que lors d’un appel d’outil.
Par exemple, si vous développez une application de soutien en mathématiques, vous pouvez demander à l’assistant de répondre à l’utilisateur selon un schéma JSON précis. Vous pouvez ainsi générer une interface qui présente chaque partie de la réponse de manière distincte.
En pratique :
- Pour connecter le modèle aux outils, aux fonctions ou aux données de votre système,
utilisez l’appel de fonction. Pour structurer la réponse du modèle à l’utilisateur,
utilisez un format de réponse structuré avec
response_format
- Pour connecter le modèle aux outils, aux fonctions ou aux données de votre système,
utilisez l’appel de fonction. Pour structurer la réponse du modèle à l’utilisateur,
utilisez un format de réponse structuré avec
text.format
La suite de ce guide traite des utilisations de l’API Chat Completions sans appel de fonction. Pour savoir comment combiner sorties structurées et appel de fonction, consultez la section du guide sur
l’appel de fonction
consacrée au mode strict.
La suite de ce guide traite des utilisations de l’API Responses sans appel de fonction. Pour savoir comment combiner sorties structurées et appel de fonction, consultez la section du guide sur
l’appel de fonction
consacrée au mode strict.
Sorties structurées et mode JSON
Les sorties structurées sont une évolution du mode JSON. Les deux garantissent une sortie JSON valide, mais seules les sorties structurées garantissent le respect du schéma. Les API Responses, Chat Completions, Assistants, Fine-tuning et Batch prennent en charge les sorties structurées et le mode JSON.
Nous recommandons de privilégier systématiquement les sorties structurées lorsque c’est possible.
Toutefois, les sorties structurées avec response_format: {type: "json_schema", ...} ne sont prises en charge que par les versions gpt-4o-mini, gpt-4o-mini-2024-07-18, gpt-4o-2024-08-06 et les versions ultérieures.
| Sorties structurées | Mode JSON | |
|---|---|---|
| Produit du JSON valide | Oui | Oui |
| Respecte le schéma | Oui (voir les schémas pris en charge) | Non |
| Modèles compatibles | gpt-4o-mini, gpt-4o-2024-08-06 et versions ultérieures |
gpt-3.5-turbo, gpt-4-*, gpt-4o-* et modèles GPT-5 compatibles |
| Activation | response_format: { type: "json_schema", json_schema: {"strict": true, "schema": ...} } |
response_format: { type: "json_object" } |
| Sorties structurées | Mode JSON | |
|---|---|---|
| Produit du JSON valide | Oui | Oui |
| Respecte le schéma | Oui (voir les schémas pris en charge) | Non |
| Modèles compatibles | gpt-4o-mini, gpt-4o-2024-08-06 et versions ultérieures |
gpt-3.5-turbo, gpt-4-*, gpt-4o-* et modèles GPT-5 compatibles |
| Activation | text: { format: { type: "json_schema", "strict": true, "schema": ... } } |
text: { format: { type: "json_object" } } |
Exemples
Raisonnement détaillé (« chain-of-thought »)
Vous pouvez demander au modèle de structurer sa réponse en étapes pour guider l’utilisateur tout au long de la résolution du problème.
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
}
}
}'Exemple de réponse
{
"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"
}Extraction de données structurées
Vous pouvez définir les champs à extraire sous forme structurée à partir de données d’entrée non structurées, comme des articles scientifiques.
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
}
}
}'Exemple de réponse
{
"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"
]
}Génération d’interfaces utilisateur
Vous pouvez générer du HTML valide en le représentant sous forme de structures de données récursives et en utilisant, par exemple, des énumérations pour limiter les valeurs autorisé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
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.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Map<String, Object> attributeProperties = new LinkedHashMap<>();
attributeProperties.put("name", Map.of("type", "string"));
attributeProperties.put("value", Map.of("type", "string"));
// Structured Outputs preserves the order of the schema's properties.
Map<String, Object> properties = new LinkedHashMap<>();
properties.put(
"type",
Map.of(
"type",
"string",
"enum",
List.of("div", "button", "header", "section", "field", "form")));
properties.put("label", Map.of("type", "string"));
properties.put("children", Map.of("type", "array", "items", Map.of("$ref", "#")));
properties.put(
"attributes",
Map.of(
"type",
"array",
"items",
Map.of(
"type",
"object",
"properties",
attributeProperties,
"required",
List.of("name", "value"),
"additionalProperties",
false)));
Map<String, Object> schema =
Map.of(
"type",
"object",
"properties",
properties,
"required",
List.of("type", "label", "children", "attributes"),
"additionalProperties",
false);
ChatCompletionCreateParams params =
ChatCompletionCreateParams.builder()
.model("gpt-6-astra")
.maxCompletionTokens(4096)
.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();
var completion = client.chat().completions().create(params);
if (completion.choices().size() != 1) {
throw new IllegalStateException("UI generation did not complete.");
}
var choice = completion.choices().get(0);
if (!choice.finishReason().equals(ChatCompletion.Choice.FinishReason.STOP)
|| choice.message().refusal().isPresent()
|| choice.message().content().filter(text -> !text.isBlank()).isEmpty()) {
throw new IllegalStateException("UI generation did not complete.");
}
System.out.println(choice.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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67using 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" },
"attributes": {
"type": "array",
"items": {
"type": "object",
"properties": { "name": { "type": "string" }, "value": { "type": "string" } },
"required": ["name", "value"],
"additionalProperties": false
}
},
"children": { "type": "array", "items": { "$ref": "#/$defs/component" } }
},
"required": ["type", "label", "children", "attributes"],
"additionalProperties": false
}
}
}
"""
);
ChatCompletionOptions options = new()
{
MaxOutputTokenCount = 4096,
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 small user profile form with exactly three direct children: " +
"a Name field, an Email field, and a Save button. Give each child no children. " +
"Use short labels and at most two short attributes per component."
),
],
options
);
if (completion.FinishReason != ChatFinishReason.Stop || !string.IsNullOrEmpty(completion.Refusal) ||
completion.Content.Count != 1 || string.IsNullOrWhiteSpace(completion.Content[0].Text))
throw new InvalidOperationException("UI generation did not complete.");
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
85import 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.LinkedHashMap;
import java.util.List;
import java.util.Map;
Map<String, Object> attributeProperties = new LinkedHashMap<>();
attributeProperties.put("name", Map.of("type", "string"));
attributeProperties.put("value", Map.of("type", "string"));
// Structured Outputs preserves the order of the schema's properties.
Map<String, Object> properties = new LinkedHashMap<>();
properties.put(
"type",
Map.of(
"type",
"string",
"enum",
List.of("div", "button", "header", "section", "field", "form")));
properties.put("label", Map.of("type", "string"));
properties.put("children", Map.of("type", "array", "items", Map.of("$ref", "#")));
properties.put(
"attributes",
Map.of(
"type",
"array",
"items",
Map.of(
"type",
"object",
"properties",
attributeProperties,
"required",
List.of("name", "value"),
"additionalProperties",
false)));
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(properties))
.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71using 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" },
"attributes": {
"type": "array",
"items": {
"type": "object",
"properties": { "name": { "type": "string" }, "value": { "type": "string" } },
"required": ["name", "value"],
"additionalProperties": false
}
},
"children": { "type": "array", "items": { "$ref": "#/$defs/component" } }
},
"required": ["type", "label", "children", "attributes"],
"additionalProperties": false
}
}
}
"""
);
CreateResponseOptions options = new()
{
Model = "gpt-6-astra",
MaxOutputTokenCount = 4096,
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 small user profile form with exactly three direct children: " +
"a Name field, an Email field, and a Save button. Give each child no children. " +
"Use short labels and at most two short attributes per component."
));
ResponseResult response = await client.CreateResponseAsync(options);
string text = response.GetOutputText();
bool refused = response.OutputItems.OfType<MessageResponseItem>()
.SelectMany(message => message.Content)
.Any(part => part.Kind == ResponseContentPartKind.Refusal);
if (response.Status != ResponseStatus.Completed || refused || string.IsNullOrWhiteSpace(text))
{
throw new InvalidOperationException("UI generation did not complete.");
}
using JsonDocument parsed = JsonDocument.Parse(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
}
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
}
}
}'Exemple de réponse
{
"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"
}
]
}Modération
Vous pouvez classer les entrées selon plusieurs catégories. C’est une pratique courante en modération.
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
}
}
}'Exemple de réponse
{
"is_violating": false,
"category": null,
"explanation_if_violating": null
}Utiliser les sorties structurées avec response_format
Avec les sorties structurées, vous pouvez utiliser le nouvel utilitaire du SDK pour analyser la réponse du modèle et la convertir au format souhaité, ou bien spécifier directement le schéma JSON.
Remarque : pour les modèles affinés, la première requête utilisant un schéma donné prend plus de temps, car l’API doit traiter ce schéma. Les requêtes suivantes utilisant le même schéma ne subissent pas cette latence supplémentaire. Les autres modèles ne présentent pas cette limitation.
Définissez d’abord un objet ou une structure de données qui représente le schéma JSON que le modèle doit respecter. Consultez les exemples au début de ce guide.
Les sorties structurées prennent en charge une grande partie de la spécification JSON Schema. Certaines fonctionnalités restent toutefois indisponibles pour des raisons techniques ou de performance. Pour en savoir plus, consultez la section sur les schémas pris en charge.
Voici un exemple de définition d’objet :
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: strConseils pour définir votre structure de données
Pour obtenir des réponses de la meilleure qualité possible, suivez ces recommandations :
- Donnez aux clés des noms clairs et intuitifs.
- Rédigez des titres et des descriptions clairs pour les clés importantes de votre structure.
- Créez et exécutez des évaluations pour déterminer quelle structure convient le mieux à votre cas d’usage.
Utilisez la méthode parse pour convertir automatiquement la réponse JSON en un objet du type que vous avez défini.
Le SDK se charge de fournir le schéma JSON correspondant à votre structure de données, puis de convertir la réponse en objet.
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,
)Dans certains cas, le modèle peut ne pas produire de réponse valide conforme au schéma JSON fourni.
Cela peut arriver si le modèle refuse de répondre pour des raisons de sécurité ou si, par exemple, la réponse reste incomplète parce que le nombre maximal de tokens est atteint.
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: 1024,
});
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=1024,
)
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)
endCommencez par définir, au format JSON Schema, le schéma que le modèle devra respecter. Consultez les exemples au début de ce guide.
Les sorties structurées prennent en charge une grande partie des fonctionnalités de JSON Schema. Certaines restent indisponibles pour des raisons techniques ou de performance. Pour en savoir plus, consultez la section sur les schémas pris en charge.
Conseils pour définir votre schéma JSON
Pour obtenir des réponses de la meilleure qualité possible, suivez ces recommandations :
- Donnez aux clés des noms clairs et intuitifs.
- Rédigez des titres et des descriptions clairs pour les clés importantes de votre schéma.
- Créez et exécutez des évaluations pour déterminer la structure la mieux adaptée à votre cas d’usage.
Pour utiliser les sorties structurées, indiquez le format suivant dans votre requête.
response_format: { "type": "json_schema", "json_schema": … , "strict": true } text: { format: { type: "json_schema", "strict": true, "schema": … } } Voici un exemple.
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
}
}
}'Remarque : la première requête utilisant un schéma donné prend plus de temps, car notre API doit traiter ce schéma. Les requêtes suivantes qui utilisent le même schéma n’entraînent aucune latence supplémentaire.
Dans certains cas, il se peut que le modèle ne génère pas de réponse valide conforme au schéma JSON fourni.
Cela peut arriver si le modèle refuse de répondre pour des raisons de sécurité ou si, par exemple, la réponse reste incomplète parce que le nombre maximal de tokens est atteint.
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: 1024,
});
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=1024,
)
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: 1024,
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=1024,
)
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)
endAprès avoir vérifié que la réponse contient des données JSON conformes à votre schéma, désérialisez-les en structures de données natives de votre langage. Si vous utilisez un langage typé, vous pouvez aussi modéliser ces données à l’aide d’un type ou d’une classe qui correspond au schéma.
Par exemple :
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())1
2
3
4
5
6
7
8
9
10
11var solution struct {
Steps []struct {
Explanation string `json:"explanation"`
Output string `json:"output"`
} `json:"steps"`
FinalAnswer string `json:"final_answer"`
}
if err := json.Unmarshal([]byte(completion.Choices[0].Message.Content), &solution); err != nil {
return err
}
fmt.Println(solution)1System.out.println(new ObjectMapper().readTree(content));1
2
3
4
5using System.Text.Json;
using OpenAI.Chat;
using JsonDocument solution = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(solution.RootElement);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)Utiliser les sorties structurées avec text.format
Commencez par définir, au format JSON Schema, le schéma que le modèle devra respecter. Consultez les exemples au début de ce guide.
Les sorties structurées prennent en charge une grande partie des fonctionnalités de JSON Schema. Certaines restent indisponibles pour des raisons techniques ou de performance. Pour en savoir plus, consultez la section sur les schémas pris en charge.
Conseils pour définir votre schéma JSON
Pour obtenir des réponses de la meilleure qualité possible, suivez ces recommandations :
- Donnez aux clés des noms clairs et intuitifs.
- Rédigez des titres et des descriptions clairs pour les clés importantes de votre schéma.
- Créez et exécutez des évaluations pour déterminer la structure la mieux adaptée à votre cas d’usage.
Pour utiliser les sorties structurées, indiquez le format suivant dans votre requête.
response_format: { "type": "json_schema", "json_schema": … , "strict": true } text: { format: { type: "json_schema", "strict": true, "schema": … } } Voici un exemple.
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
}
}
}'Remarque : la première requête utilisant un schéma donné prend plus de temps, car notre API doit traiter ce schéma. Les requêtes suivantes qui utilisent le même schéma n’entraînent aucune latence supplémentaire.
Dans certains cas, il se peut que le modèle ne génère pas de réponse valide conforme au schéma JSON fourni.
Cela peut arriver si le modèle refuse de répondre pour des raisons de sécurité ou si, par exemple, la réponse reste incomplète parce que le nombre maximal de tokens est atteint.
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: 1024,
});
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=1024,
)
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: 1024,
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=1024,
)
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)
endAprès avoir vérifié que la réponse contient des données JSON conformes à votre schéma, désérialisez-les en structures de données natives de votre langage. Si vous utilisez un langage typé, vous pouvez aussi modéliser ces données à l’aide d’un type ou d’une classe qui correspond au schéma.
Par exemple :
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())1
2
3
4
5
6
7
8
9
10
11var solution struct {
Steps []struct {
Explanation string `json:"explanation"`
Output string `json:"output"`
} `json:"steps"`
FinalAnswer string `json:"final_answer"`
}
if err := json.Unmarshal([]byte(completion.Choices[0].Message.Content), &solution); err != nil {
return err
}
fmt.Println(solution)1System.out.println(new ObjectMapper().readTree(content));1
2
3
4
5using System.Text.Json;
using OpenAI.Chat;
using JsonDocument solution = JsonDocument.Parse(completion.Content[0].Text);
Console.WriteLine(solution.RootElement);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)Changer le format de réponse en cours de conversation
Pour changer de schéma entre deux réponses, ajoutez un élément configuration_update à input avant le prochain message de l’utilisateur. Dans chaque requête, conservez la valeur initiale du paramètre de premier niveau text.format pour que le préfixe du prompt précédent reste admissible à la mise en cache des prompts.
Vous pouvez mettre à jour le format de réponse en mode standard avec un seul agent sur les modèles compatibles à partir de GPT-6.
Supposons qu’au tour précédent, un message ait décrit en texte brut une expédition de 17 caisses rouges et de 26 caisses bleues. Poursuivez la conversation avec previous_response_id et passez le tableau suivant comme valeur de input.
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
28import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";
const client = new OpenAI();
const model = "gpt-6-astra";
const CrateCount = z.object({ total_crates: z.number().int() });
const first = await client.responses.create({
model,
input:
"Summarize this shipment in one sentence: 17 red crates and 26 blue crates.",
store: true,
});
const format = zodTextFormat(CrateCount, "crate_count");
const second = await client.responses.parse({
model,
previous_response_id: first.id,
input: [
{ type: "configuration_update", text: { format } },
{ role: "user", content: "How many crates are in the shipment?" },
],
});
if (second.status === "completed" && second.output_parsed) {
console.log(second.output_parsed.total_crates);
}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
40from openai import OpenAI
from pydantic import BaseModel, ConfigDict
class CrateCount(BaseModel):
model_config = ConfigDict(extra="forbid")
total_crates: int
client = OpenAI()
model = "gpt-6-astra"
first = client.responses.create(
model=model,
input="Summarize this shipment in one sentence: 17 red crates and 26 blue crates.",
store=True,
)
second = client.responses.parse(
model=model,
previous_response_id=first.id,
input=[
{
"type": "configuration_update",
"text": {
"format": {
"type": "json_schema",
"name": "crate_count",
"schema": CrateCount.model_json_schema(),
"strict": True,
}
},
},
{"role": "user", "content": "How many crates are in the shipment?"},
],
parse_as=CrateCount,
)
if second.status == "completed" and second.output_parsed is not None:
print(second.output_parsed.total_crates)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
64package main
import (
"context"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
ctx := context.Background()
const model = "gpt-6-astra"
first, err := client.Responses.New(ctx, responses.ResponseNewParams{
Model: model,
Input: responses.ResponseNewParamsInputUnion{
OfString: openai.String("Summarize this shipment in one sentence: 17 red crates and 26 blue crates."),
},
Store: openai.Bool(true),
})
if err != nil {
panic(err)
}
format := responses.ResponseFormatTextJSONSchemaConfigParam{
Name: "crate_count",
Schema: map[string]any{
"type": "object",
"properties": map[string]any{"total_crates": map[string]any{"type": "integer"}},
"required": []string{"total_crates"},
"additionalProperties": false,
},
Strict: openai.Bool(true),
}
second, err := client.Responses.New(ctx, responses.ResponseNewParams{
Model: model,
PreviousResponseID: openai.String(first.ID),
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: responses.ResponseInputParam{
{OfConfigurationUpdate: &responses.ResponseConfigurationUpdateItemParam{
Text: responses.ResponseConfigurationUpdateItemParamText{
Format: responses.ResponseConfigurationUpdateItemParamTextFormatUnion{OfJSONSchema: &format},
},
}},
responses.ResponseInputItemParamOfMessage("How many crates are in the shipment?", responses.EasyInputMessageRoleUser),
}},
})
if err != nil {
panic(err)
}
if second.Status != responses.ResponseStatusCompleted {
return
}
for _, item := range second.Output {
if item.Type != "message" || (item.Phase != "" && item.Phase != responses.ResponseOutputMessagePhaseFinalAnswer) {
continue
}
for _, part := range item.Content {
if part.Type == "output_text" {
fmt.Println(part.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
68
69
70
71
72
73import com.openai.core.JsonValue;
import com.openai.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseConfigurationUpdateItemParam;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFormatTextJsonSchemaConfig;
import com.openai.models.responses.ResponseInputItem;
import com.openai.models.responses.ResponseOutputMessage;
import com.openai.models.responses.ResponseStatus;
import java.util.List;
import java.util.Map;
String model = "gpt-6-astra";
var first =
client
.responses()
.create(
ResponseCreateParams.builder()
.model(model)
.input(
"Summarize this shipment in one sentence: 17 red crates and 26 blue crates.")
.store(true)
.build());
var schema =
Map.of(
"type",
"object",
"properties",
Map.of("total_crates", Map.of("type", "integer")),
"required",
List.of("total_crates"),
"additionalProperties",
false);
var format =
ResponseFormatTextJsonSchemaConfig.builder()
.name("crate_count")
.schema(JsonValue.from(schema).convert(ResponseFormatTextJsonSchemaConfig.Schema.class))
.strict(true)
.build();
var update =
ResponseConfigurationUpdateItemParam.builder()
.text(ResponseConfigurationUpdateItemParam.Text.builder().format(format).build())
.build();
var question =
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("How many crates are in the shipment?")
.build();
var second =
client
.responses()
.create(
ResponseCreateParams.builder()
.model(model)
.previousResponseId(first.id())
.inputOfResponse(
List.of(
ResponseInputItem.ofConfigurationUpdate(update),
ResponseInputItem.ofEasyInputMessage(question)))
.build());
if (!ResponseStatus.COMPLETED.equals(second.status().orElse(null))) {
return;
}
second.output().stream()
.flatMap(item -> item.message().stream())
.filter(
message ->
message.phase().map(ResponseOutputMessage.Phase.FINAL_ANSWER::equals).orElse(true))
.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# gem install openai sorbet-runtime
require "openai"
require "openai/helpers/sorbet"
class CrateCount < T::Struct
const :total_crates, Integer
end
client = OpenAI::Client.new
model = "gpt-6-astra"
first = client.responses.create(
model: model,
input: "Summarize this shipment in one sentence: 17 red crates and 26 blue crates.",
store: true
)
second = client.responses.create(
model: model,
previous_response_id: first.id,
input: [
{
type: :configuration_update,
text: {
format: {
type: :json_schema,
name: "crate_count",
schema: OpenAI::StructuredOutput.from_sorbet(CrateCount),
strict: true
}
}
},
{
role: :user,
content: "How many crates are in the shipment?"
}
]
)
if second.status == OpenAI::Responses::ResponseStatus::COMPLETED
second.output.grep(OpenAI::Responses::ResponseOutputMessage).each do |message|
next unless message.phase.nil? || message.phase == :final_answer
message.content.grep(OpenAI::Responses::ResponseOutputText).each do |part|
count = part.parsed
case count
when CrateCount
puts count.total_crates
end
end
end
endLa réponse attendue est {"total_crates":43}. Le champ text.format de l’objet de réponse indique toujours le format initial défini au niveau de la requête. Après avoir vérifié que la réponse est complète et que le modèle n’a pas opposé de refus, analysez la réponse à l’aide du schéma fourni dans la dernière mise à jour du format.
Chaque mise à jour remplace le format dans son intégralité. Ce format reste en vigueur d’un tour à l’autre, y compris lorsque vous modifiez uniquement reasoning.effort. Pour revenir au texte brut, ajoutez {"type":"configuration_update","text":{"format":{"type":"text"}}}. Les mises à jour du format acceptent uniquement json_schema et text.
Si vous renvoyez manuellement l’historique, conservez chaque mise à jour à sa position d’origine. Après un compactage explicite, spécifiez à nouveau la valeur de chaque paramètre que vous avez modifié. Consultez la section sur la compatibilité des mises à jour de configuration.
Refus avec les sorties structurées
Lorsque vous utilisez les sorties structurées avec des données fournies par les utilisateurs, les modèles OpenAI peuvent parfois refuser de répondre à une demande pour des raisons de sécurité. Comme un refus ne respecte pas nécessairement le schéma fourni dans response_format, la réponse de l’API contient alors un nouveau champ, refusal, qui signale le refus du modèle.
Lorsque la propriété refusal figure dans l’objet de sortie, vous pouvez afficher le refus dans votre interface ou ajouter une condition dans le code qui traite la réponse pour gérer ce cas.
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
endEn cas de refus, la réponse de l’API ressemble à ceci :
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,
}
},
}Conseils et bonnes pratiques
Traiter les données fournies par les utilisateurs
Si votre application utilise des données fournies par les utilisateurs, précisez dans votre prompt ce que le modèle doit faire lorsque ces données ne permettent pas de produire une réponse valide.
Le modèle essaie toujours de respecter le schéma fourni. Si les données n’ont aucun rapport avec ce schéma, il risque donc d’inventer des informations.
Vous pouvez par exemple préciser dans votre prompt que le modèle doit renvoyer des paramètres vides ou une phrase précise s’il détecte que les données sont incompatibles avec la tâche.
Gérer les erreurs
Les sorties structurées peuvent tout de même contenir des erreurs. Si vous en constatez, essayez d’ajuster vos instructions, d’ajouter des exemples dans les instructions système ou de décomposer les tâches en sous-tâches plus simples. Consultez le guide d’ingénierie de prompts pour en savoir plus sur la façon d’ajuster vos entrées.
Maintenir la cohérence entre le schéma JSON et les types
Pour éviter que votre schéma JSON et les types correspondants dans votre langage de programmation ne divergent, nous vous recommandons vivement d’utiliser les utilitaires de schéma intégrés au SDK lorsqu’ils sont disponibles.
Si vous préférez spécifier directement le schéma JSON, vous pouvez ajouter des règles d’intégration continue qui signalent toute modification du schéma ou des objets de données sous-jacents. Vous pouvez aussi ajouter une étape d’intégration continue qui génère automatiquement le schéma JSON à partir des définitions de types, ou inversement.
Diffusion en continu
La diffusion en continu vous permet de traiter les réponses du modèle ou les arguments d’un appel de fonction à mesure que le modèle les génère et de les analyser sous forme de données structurées.
Vous pouvez ainsi commencer à traiter la réponse avant de l’avoir reçue en entier. C’est particulièrement utile si vous souhaitez afficher les champs JSON un par un ou traiter les arguments d’un appel de fonction dès qu’ils sont disponibles.
Nous vous recommandons d’utiliser les SDK pour gérer la diffusion en continu des sorties structurées.
Pour voir comment recevoir en continu les arguments d’un appel de fonction sans utiliser la méthode stream du SDK, consultez l’exemple du guide sur l’appel de fonction.
L’exemple suivant montre comment recevoir la réponse du modèle en continu avec la méthode 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)Vous pouvez aussi utiliser la méthode stream pour analyser les arguments d’un appel de fonction.
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 { 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-terra",
reasoning_effort: "none",
parallel_tool_calls: true,
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
33
34from 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-terra",
reasoning_effort="none",
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
endSchémas pris en charge
Les sorties structurées prennent en charge un sous-ensemble du langage JSON Schema.
Types pris en charge
Les sorties structurées prennent en charge les types suivants :
- Chaîne de caractères
- Nombre
- Booléen
- Entier
- Objet
- Tableau
- Énumération
- anyOf
Propriétés prises en charge
En plus du type d’une propriété, vous pouvez spécifier les contraintes suivantes :
Propriétés prises en charge pour le type string :
pattern— Expression régulière à laquelle la chaîne doit correspondre.format— Format prédéfini de la chaîne. Les formats actuellement pris en charge sont les suivants :date-timetimedatedurationemailhostnameipv4ipv6uuid
Propriétés prises en charge pour le type number :
multipleOf— Le nombre doit être un multiple de cette valeur.maximum— Le nombre doit être inférieur ou égal à cette valeur.exclusiveMaximum— Le nombre doit être strictement inférieur à cette valeur.minimum— Le nombre doit être supérieur ou égal à cette valeur.exclusiveMinimum— Le nombre doit être strictement supérieur à cette valeur.
Propriétés prises en charge pour le type array :
minItems— Nombre minimal d’éléments que doit contenir le tableau.maxItems— Nombre maximal d’éléments que peut contenir le tableau.
Voici quelques exemples d’utilisation de ces contraintes :
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"
]
}
}Ces contraintes ne sont pas encore prises en charge pour les modèles ajustés.
La racine doit être un objet et ne peut pas utiliser anyOf
La racine du schéma doit être de type objet et ne doit pas utiliser anyOf. Avec Zod, par exemple, une union discriminée produit un anyOf à la racine. Le code suivant ne fonctionnera donc pas :
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");Tous les champs doivent figurer dans required
Pour utiliser les sorties structurées, indiquez dans required tous les champs ou paramètres de fonction.
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"]
}
}Tous les champs sont obligatoires et le modèle renvoie une valeur pour chaque paramètre. Vous pouvez toutefois simuler un paramètre facultatif en utilisant un type union qui accepte 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"
]
}
}Limites de profondeur d’imbrication et de taille des objets
Un schéma peut contenir jusqu’à 5 000 propriétés d’objet au total et jusqu’à 10 niveaux d’imbrication.
Limite de longueur cumulée des chaînes
Dans un schéma, la longueur cumulée des noms de propriétés, des noms de définitions, des valeurs d’énumération et des valeurs de const ne peut pas dépasser 120 000 caractères.
Limites de taille des énumérations
Un schéma peut contenir jusqu’à 1 000 valeurs d’énumération, toutes propriétés d’énumération confondues.
Si une propriété d’énumération contient plus de 250 valeurs de type chaîne, leur longueur cumulée ne peut pas dépasser 15 000 caractères.
Chaque objet doit spécifier additionalProperties: false
additionalProperties détermine si un objet peut contenir des paires clé-valeur supplémentaires que le schéma JSON ne définit pas.
Les sorties structurées ne peuvent générer que les paires clé-valeur prévues par le schéma. Pour utiliser les sorties structurées, spécifiez donc 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{
"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"
]
}
}Ordre des clés
Dans les sorties structurées, les clés apparaissent dans le même ordre que dans le schéma.
Certains mots-clés propres à un type ne sont pas encore pris en charge
- Composition :
allOf,not,dependentRequired,dependentSchemas,if,then,else
Pour les modèles ajustés, les mots-clés suivants ne sont pas non plus pris en charge :
- Pour les chaînes :
minLength,maxLength,pattern,format - Pour les nombres :
minimum,maximum,multipleOf - Pour les objets :
patternProperties - Pour les tableaux :
minItems,maxItems
Si vous activez les sorties structurées en spécifiant strict: true et que vous appelez l’API avec un schéma JSON non pris en charge, l’API renvoie une erreur.
Avec anyOf, chaque schéma imbriqué doit être un schéma JSON valide et respecter le sous-ensemble pris en charge
Voici un exemple de schéma pris en charge qui utilise 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"
]
}Prise en charge des définitions
Les définitions permettent de créer des sous-schémas auxquels vous pouvez faire référence à différents endroits du schéma. Voici un exemple simple :
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
}Prise en charge des schémas récursifs
Voici un schéma récursif qui utilise # pour faire référence à sa racine :
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
}
}Voici un schéma qui utilise la récursion explicite :
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"
]
}Mode JSON
Le mode JSON est une version plus simple des sorties structurées. Le mode JSON garantit que le modèle produit du JSON valide, tandis que les sorties structurées garantissent que sa réponse respecte le schéma que vous spécifiez. Nous vous recommandons d’utiliser les sorties structurées si votre cas d’usage le permet.
Lorsque le mode JSON est activé, le modèle produit du JSON valide, sauf dans certains cas limites que votre application doit détecter et traiter.
Pour activer le mode JSON avec l’API Chat Completions, définissez response_format sur { "type": "json_object" }. Si vous utilisez l’appel de fonction, le mode JSON est toujours activé.
Pour activer le mode JSON avec l’API Responses, définissez text.format sur { "type": "json_object" }. Si vous utilisez l’appel de fonction, le mode JSON est toujours activé.
Points importants :
- En mode JSON, vous devez toujours demander au modèle de produire du JSON dans l’un des messages de la conversation, par exemple dans le message système. Sans instruction explicite, le modèle risque de générer des caractères d’espacement en continu, et la requête peut se poursuivre jusqu’à la limite de tokens. Pour éviter les oublis, l’API renvoie une erreur si la chaîne « JSON » n’apparaît nulle part dans le contexte.
- Le mode JSON garantit uniquement que la sortie est valide et peut être analysée sans erreur. Pour garantir qu’elle respecte un schéma précis, utilisez les sorties structurées. Si ce n’est pas possible, utilisez une bibliothèque de validation et relancez la requête si nécessaire pour obtenir une sortie conforme au schéma souhaité.
- Votre application doit détecter et traiter les cas limites dans lesquels le modèle risque de produire un objet JSON incomplet (voir ci-dessous).
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
endRessources
Pour en savoir plus sur les sorties structurées, nous vous recommandons les ressources suivantes :
- Consultez notre guide pratique d’introduction aux sorties structurées.
- Découvrez comment créer des systèmes multi-agents avec les sorties structurées.