Pour gérer les interactions de longue durée, vous pouvez utiliser le compactage afin de réduire la taille du contexte
tout en préservant l’état nécessaire aux échanges suivants.
Le compactage vous aide à trouver un équilibre entre qualité, coût et latence à mesure que les conversations s’allongent.
Vous pouvez activer le compactage côté serveur dans une requête de création Responses
(POST /responses ou client.responses.create) en configurant
context_management avec compact_threshold.
- Lorsque le nombre de tokens après rendu dépasse le seuil configuré, le serveur
exécute le compactage côté serveur.
- Ce mode ne nécessite aucun appel distinct à
/responses/compact.
- Le flux de réponse inclut l’élément de compactage chiffré.
- Remarque sur la ZDR : le compactage côté serveur est compatible avec la ZDR lorsque vous définissez
store=false
dans vos requêtes de création Responses.
L’élément de compactage renvoyé transmet les informations essentielles de l’état et du raisonnement antérieurs
à l’exécution suivante en utilisant moins de tokens. Il est opaque et n’est pas conçu pour être
interprété par un humain.
Pour le chaînage sans état par tableau d’entrée, ajoutez les éléments de sortie comme d’habitude. Si vous utilisez
previous_response_id, transmettez uniquement le nouveau message utilisateur à chaque échange. Dans les deux
cas, l’élément de compactage contient le contexte nécessaire à la fenêtre suivante.
Conseil pour réduire la latence : après avoir ajouté les éléments de sortie aux éléments d’entrée précédents, vous pouvez
supprimer les éléments qui précèdent l’élément de compactage le plus récent afin de réduire la taille des requêtes
et la latence des requêtes les plus lentes. Le dernier élément de compactage contient le
contexte nécessaire pour poursuivre la conversation. Si vous utilisez le chaînage avec
previous_response_id, ne supprimez pas d’éléments manuellement.
- Appelez
/responses comme d’habitude, mais incluez context_management avec
compact_threshold pour activer le compactage côté serveur.
- Pendant la diffusion de la réponse, si la taille du contexte dépasse le seuil, le serveur
déclenche une opération de compactage, émet un élément de sortie de compactage dans le même flux,
puis supprime une partie du contexte avant de poursuivre l’inférence.
- Poursuivez votre boucle en suivant une seule méthode : le chaînage sans état par tableau d’entrée (ajoutez
la sortie, y compris les éléments de compactage, à votre prochain tableau d’entrée) ou
le chaînage avec
previous_response_id (transmettez uniquement le nouveau message utilisateur à chaque échange et
réutilisez cet identifiant à l’échange suivant).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import OpenAI from "openai";
import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";
const client = new OpenAI();
const conversation = [
{
type: "message",
role: "user",
content: "Let's begin a long coding task.",
},
];
const response = await client.responses.create({
model: "gpt-5.3-codex",
input: conversation,
store: false,
context_management: [{ type: "compaction", compact_threshold: 200_000 }],
});
conversation.push(...toResponseInputItems(response.output));
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
25conversation = [
{
"type": "message",
"role": "user",
"content": "Let's begin a long coding task.",
}
]
while keep_going:
response = client.responses.create(
model="gpt-5.3-codex",
input=conversation,
store=False,
context_management=[{"type": "compaction", "compact_threshold": 200000}],
)
conversation.extend(response.output)
conversation.append(
{
"type": "message",
"role": "user",
"content": get_next_user_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
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 (
"bufio"
"context"
"encoding/json"
"fmt"
"os"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
conversation := []responses.ResponseInputItemUnionParam{
responses.ResponseInputItemParamOfMessage("Let's begin a long coding task.", responses.EasyInputMessageRoleUser),
}
scanner := bufio.NewScanner(os.Stdin)
for {
response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-5.3-codex",
Store: openai.Bool(false),
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: conversation},
ContextManagement: []responses.ResponseNewParamsContextManagement{{
Type: "compaction", CompactThreshold: openai.Int(200000),
}},
})
if err != nil {
panic(err)
}
conversation = append(conversation, outputAsInput(response.Output)...)
fmt.Println(response.OutputText())
if !scanner.Scan() {
break
}
conversation = append(conversation,
responses.ResponseInputItemParamOfMessage(scanner.Text(), responses.EasyInputMessageRoleUser),
)
}
if err := scanner.Err(); err != nil {
panic(err)
}
}
func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {
input := make([]responses.ResponseInputItemUnionParam, 0, len(output))
for _, item := range output {
var converted responses.ResponseInputItemUnion
if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {
panic(err)
}
input = append(input, converted.ToParam())
}
return 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48import 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.ResponseInputItem;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
var conversation = new ArrayList<ResponseInputItem>();
conversation.add(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("Let's begin a long coding task.")
.build()));
ResponseCreateParams params =
ResponseCreateParams.builder()
.model("gpt-5.3-codex")
.inputOfResponse(conversation)
.store(false)
.putAdditionalBodyProperty(
"context_management",
JsonValue.from(List.of(Map.of("type", "compaction", "compact_threshold", 200000))))
.build();
var response = client.responses().create(params);
response.output().stream()
.map(item -> JsonValue.from(item).convert(ResponseInputItem.class))
.forEach(conversation::add);
conversation.add(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("Now implement the next step.")
.build()));
client
.responses()
.create(params.toBuilder().inputOfResponse(conversation).build())
.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
40require "openai"
client = OpenAI::Client.new
conversation = [
{
type: :message,
role: :user,
content: "Let's begin a long coding task."
}
]
response = client.responses.create(
model: "gpt-5.3-codex",
input: conversation,
store: false,
context_management: [
{
type: :compaction,
compact_threshold: 200_000
}
]
)
conversation.concat(response.output)
conversation << {
type: :message,
role: :user,
content: "Now implement the next step."
}
next_response = client.responses.create(
model: "gpt-5.3-codex",
input: conversation,
store: false,
context_management: [
{
type: :compaction,
compact_threshold: 200_000
}
]
)
puts(next_response.output_text)
Pour contrôler explicitement le compactage, utilisez le
point de terminaison de compactage autonome afin d’effectuer
un compactage sans état dans les workflows de longue durée.
Ce point de terminaison est entièrement sans état et compatible avec la ZDR.
Vous envoyez une fenêtre de contexte complète (messages, outils et autres éléments), et le
point de terminaison renvoie une nouvelle fenêtre de contexte compactée que vous pouvez transmettre à votre prochain
appel à /responses.
La fenêtre compactée renvoyée inclut un élément de compactage chiffré qui conserve
les informations essentielles de l’état et du raisonnement antérieurs en utilisant moins de tokens. Cet élément est opaque et n’est pas
conçu pour être interprété par un humain.
Remarque : la fenêtre compactée contient généralement plus que le seul élément de
compactage. Elle peut aussi inclure des éléments conservés de la fenêtre précédente.
Traitement de la sortie : ne supprimez aucun élément de la sortie de /responses/compact. La fenêtre renvoyée
constitue la prochaine fenêtre de contexte de référence ; transmettez-la donc telle quelle à votre prochain appel à /responses
.
- Utilisez
/responses normalement, en envoyant des éléments d’entrée qui incluent les messages utilisateur,
les sorties de l’assistant et les interactions avec les outils.
- Lorsque votre fenêtre de contexte devient volumineuse, appelez
/responses/compact pour générer une
nouvelle fenêtre de contexte compactée. La fenêtre que vous envoyez à /responses/compact
doit toujours tenir dans la fenêtre de contexte de votre modèle.
- Pour les appels suivants à
/responses, transmettez en entrée la fenêtre compactée renvoyée
(y compris l’élément de compactage) à la place de la transcription complète.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import OpenAI from "openai";
const client = new OpenAI();
const conversation = [{ role: "user", content: "Plan a trip to Kyoto." }];
const compacted = await client.responses.compact({
model: "gpt-6-astra",
input: conversation,
});
const nextInput = [
...compacted.output.map((item) => item),
{ role: "user", content: "Add two more days to the itinerary." },
];
const response = await client.responses.create({
model: "gpt-6-astra",
input: nextInput,
store: false,
});
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# Full window collected from prior turns
long_input_items_array = [{"role": "user", "content": "Plan a trip to Kyoto."}]
# 1) Compact the current window
compacted = client.responses.compact(
model="gpt-6-astra",
input=long_input_items_array,
)
# 2) Start the next turn by appending a new user message
next_input = [
*compacted.output, # Use compact output as-is
{
"type": "message",
"role": "user",
"content": user_input_message(),
},
]
next_response = client.responses.create(
model="gpt-6-astra",
input=next_input,
store=False, # Keep the flow ZDR-friendly
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
54package main
import (
"bufio"
"context"
"encoding/json"
"fmt"
"os"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/responses"
)
func main() {
client := openai.NewClient()
longInputItems := []responses.ResponseInputItemUnionParam{
responses.ResponseInputItemParamOfMessage("Plan a trip to Kyoto.", responses.EasyInputMessageRoleUser),
}
compacted, err := client.Responses.Compact(context.Background(), responses.ResponseCompactParams{
Model: "gpt-6-astra",
Input: responses.ResponseCompactParamsInputUnion{OfResponseInputItemArray: longInputItems},
})
if err != nil {
panic(err)
}
scanner := bufio.NewScanner(os.Stdin)
if !scanner.Scan() {
return
}
nextInput := append(outputAsInput(compacted.Output),
responses.ResponseInputItemParamOfMessage(scanner.Text(), responses.EasyInputMessageRoleUser),
)
nextResponse, err := client.Responses.New(context.Background(), responses.ResponseNewParams{
Model: "gpt-6-astra",
Store: openai.Bool(false),
Input: responses.ResponseNewParamsInputUnion{OfInputItemList: nextInput},
})
if err != nil {
panic(err)
}
fmt.Println(nextResponse.OutputText())
}
func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {
input := make([]responses.ResponseInputItemUnionParam, 0, len(output))
for _, item := range output {
var converted responses.ResponseInputItemUnion
if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {
panic(err)
}
input = append(input, converted.ToParam())
}
return 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
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.models.responses.EasyInputMessage;
import com.openai.models.responses.ResponseCompactParams;
import com.openai.models.responses.ResponseCompactionItemParam;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputItem;
import java.util.ArrayList;
var compacted =
client
.responses()
.compact(
ResponseCompactParams.builder()
.model("gpt-6-astra")
.input("Plan a trip to Kyoto.")
.build());
var input = new ArrayList<ResponseInputItem>();
for (var item : compacted.output()) {
item.message().map(ResponseInputItem::ofResponseOutputMessage).ifPresent(input::add);
item.reasoning().map(ResponseInputItem::ofReasoning).ifPresent(input::add);
item.compaction()
.map(
value ->
ResponseInputItem.ofCompaction(
ResponseCompactionItemParam.builder()
.id(value.id())
.encryptedContent(value.encryptedContent())
.build()))
.ifPresent(input::add);
}
input.add(
ResponseInputItem.ofEasyInputMessage(
EasyInputMessage.builder()
.role(EasyInputMessage.Role.USER)
.content("Add restaurant recommendations.")
.build()));
client
.responses()
.create(
ResponseCreateParams.builder()
.model("gpt-6-astra")
.inputOfResponse(input)
.store(false)
.build())
.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
27require "openai"
client = OpenAI::Client.new
long_input = [
{
role: :user,
content: "Plan a trip to Kyoto."
}
]
compaction = client.responses.compact(
model: "gpt-6-astra",
input: long_input
)
next_input = [
*compaction.output,
{
type: :message,
role: :user,
content: "Add restaurant recommendations."
}
]
response = client.responses.create(
model: "gpt-6-astra",
input: next_input,
store: false
)
puts(response.output_text)