Skip to content
This page has been auto-translated and may contain errors.View in English

Chat Completions e Responses

Abra o playground da lição e você vai encontrar dois botões, um para cada uma das duas estruturas de API da OpenAI: Chat Completions e Responses. Você vai encontrar os dois nomes de novo em código de outras pessoas e na própria documentação do provedor, geralmente sem nenhuma explicação sobre por que existem dois.

Os dois fazem o mesmo trabalho. Ambos enviam instruções e uma mensagem do usuário para um modelo e recebem uma resposta de volta. O que muda é onde você coloca cada parte da requisição, e onde o texto da resposta aparece depois — e é essa segunda diferença que costuma pegar você quando está copiando um trecho de código de algum lugar.

Esses botões do playground chamam rotas no servidor Express, o pequeno programa em Node que o projeto do curso executa junto com a página, para que as requisições ao modelo aconteçam fora do código do navegador e sua chave de API nunca fique exposta. No Scrimba, a saída dessas rotas do servidor aparece na aba Runner em vez da aba Console.

Os dois exemplos abaixo usam o mesmo client, criado uma única vez a partir dos valores que você salvou em Configurando o provedor:

js
import OpenAI from "openai"

const client = new OpenAI({
  apiKey: process.env.AI_KEY,
  baseURL: process.env.AI_URL,
})

Chat Completions

O Chat Completions coloca o prompt de sistema e a entrada do usuário juntos em messages:

js
const response = await client.chat.completions.create({
  model: process.env.AI_MODEL,
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    {
      role: "user",
      content: "Give me a short explanation of why open-source tools matter.",
    },
  ],
});

O texto da resposta fica aninhado dentro da primeira escolha:

js
response.choices[0].message.content
JunoChat Completions Tudo entra em uma única lista messages: primeiro o prompt de sistema, depois sua pergunta. A resposta volta escondida em response.choices[0].message.content.

Esse caminho parece complicado nas primeiras vezes que você o digita. Vale a pena ler com calma uma vez, porque você vai vê-lo em praticamente todo exemplo de código que encontrar por aí!

JunoChat Completions Um único array carrega toda a requisição, e o role define para que serve cada item. A resposta fica dentro de choices[0] porque a API pode retornar várias respostas alternativas em uma única chamada.

Na prática, você quase sempre vai querer a primeira, então choices[0].message.content acaba virando automático. Reconhecer esse caminho é útil até aqui, porque ele te mostra de imediato que um trecho de código que você encontrou é Chat Completions, e não Responses.

JunoChat Completionschoices é um plural que quase nunca é plural de fato. Isso vem do parâmetro n da API de completions, que pedia várias amostras independentes em uma única requisição, e essa característica sobrevive na estrutura da resposta muito depois de quase todo mundo ter parado de usá-la.

Vale saber isso porque explica a praticidade que você está prestes a perder. Cada leitura custa um índice de array que não carrega informação nenhuma, e cada turno de chamada de ferramenta que você adiciona precisa ser reconstruído manualmente na mesma lista plana.

Responses

O Responses dá ao prompt de sistema um campo próprio, instructions. Para uma requisição simples, input pode ser uma string direta:

js
const response = await client.responses.create({
  model: process.env.AI_MODEL,
  instructions: "You are a helpful assistant.",
  input: "Give me a short explanation of why open-source tools matter.",
});

A mesma string direta pode ser transformada em um objeto de mensagem com role/content quando você precisa desse formato:

js
input: [
  {
    role: "user",
    content: "Give me a short explanation of why open-source tools matter.",
  },
],

O Responses expõe o texto da resposta diretamente:

js
response.output_text

Ele também mantém a estrutura completa da resposta em response.output. Uma resposta de texto básica geralmente contém um item de mensagem cujo content inclui o mesmo texto de saída.

JunoResponses O prompt de sistema recebe seu próprio campo instructions em vez de compartilhar a lista, e input pode ser uma string simples quando você está pedindo só uma coisa.

A melhor parte: a resposta está em response.output_text. Um passo, em vez de três.

JunoResponses Duas diferenças práticas. instructions separa o prompt de sistema da conversa, então você não precisa reconstruir um array a cada turno só para mantê-lo no início. E output_text te dá o texto diretamente.

input ainda aceita o formato de array de mensagens quando você precisa dele, que é o que o histórico de conversa e os resultados de ferramentas vão usar mais adiante no curso. O formato de string é um atalho para o caso simples, não uma API diferente.

JunoResponsesoutput_text é uma conveniência sobre output, que é o valor de retorno real: uma lista de itens tipados, em vez de uma única mensagem. Essa estrutura é o ponto central, porque um turno que chama ferramentas retorna itens de chamada de ferramenta junto com qualquer texto, e uma string de conteúdo plana não tem onde colocá-los.

Então leia output_text quando quiser uma resposta final e output sempre que precisar saber o que o modelo realmente fez. No momento em que você adicionar sua primeira ferramenta, é esse segundo campo que você vai precisar consultar.

Por que o curso usa o Responses

O Chat Completions continua sendo uma API válida, e a funcionalidade de agentes deste curso poderia ser construída com ele.

O curso usa o Responses por causa da diferença que você já pode ver nos dois blocos de código acima. Ler uma resposta é response.output_text em vez de response.choices[0].message.content, e o prompt de sistema tem um lugar próprio em vez de ser o primeiro item de um array ao qual você também vai anexando os turnos do usuário. Depois que as chamadas de ferramenta e o histórico de conversa começam a se acumular, essa estrutura significa menos código para manter tudo conectado.

Use a saída completa quando precisar da estrutura

output_text é a forma prática de ler uma resposta de texto final. Use output quando precisar examinar o conjunto completo de itens da resposta.

JunoPor que o curso usa o Responses As duas APIs conseguem fazer tudo o que este curso precisa. O Responses é o que exige digitar menos: a resposta está a um passo de distância em vez de três, e o prompt de sistema tem um campo próprio.

Você não precisa memorizar as diferenças. Use o Responses aqui, e reconheça o Chat Completions quando encontrá-lo em outro lugar.

JunoPor que o curso usa o Responses A escolha é sobre quanto código de "cola" você precisa escrever em volta da chamada. Com o Responses, o prompt de sistema tem um lugar próprio, então ele deixa de ser um elemento de array que você precisa manter na posição zero, e a resposta está a apenas uma propriedade de distância.

O Chat Completions não está obsoleto, e bastante código em produção o usa. Se você herdar uma base de código construída com ele, nada aqui precisa ser reescrito.

JunoPor que o curso usa o Responses A diferença se acumula em vez de aparecer já na primeira requisição. Em um loop de chamada de ferramentas, você anexa o turno do modelo, depois os resultados da ferramenta, e chama de novo — e o Chat Completions te obriga a reconstruir todo esse array plano manualmente a cada vez, mantendo a mensagem de sistema fixada no início.

O Responses modela um turno como itens, que é a estrutura que o loop realmente tem. Esse é o argumento de verdade, e ele é invisível nos dois exemplos simples acima — por isso vale a pena dizer isso em voz alta antes de você se deparar com ele.

Para onde isso leva

Executando o código localmente explica como o navegador e o servidor Express se conectam depois que você baixa uma lição do Scrimba. Se você ainda não escolheu um modelo, Modelos recomendados cobre o que o trabalho com agentes exige.