Ir para o conteúdo

Continuidade de Conversas

O Nodexa mantém o histórico de conversas no servidor. Você não precisa reenviar todo o histórico de mensagens em cada request — basta referenciar o ID da resposta anterior.


Como Funciona

Cada resposta tem um id único com o prefixo resp_. Para continuar uma conversa, passe esse ID como previous_response_id na sua próxima request:

{
  "model": "YOUR_ASSISTANT_ID",
  "input": "What did I just ask you?",
  "previous_response_id": "resp_01234567-89ab-cdef-0123-456789abcdef"
}

A plataforma vai:

  1. Carregar o histórico de conversa associado a esse ID de resposta
  2. Adicionar a nova mensagem do usuário ao histórico
  3. Gerar uma resposta no contexto da conversa completa
  4. Armazenar o novo turno e retornar um novo ID de resposta

Esse novo ID de resposta é o que você vai usar no próximo turno.


Exemplo de Conversa com Múltiplos Turnos

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://your-admin.example.com/v1',
  apiKey: process.env.NODEXA_API_KEY,
});

const assistantId = 'YOUR_ASSISTANT_ID';

// Turno 1: apresentação
const turn1 = await client.responses.create({
  model: assistantId,
  input: 'My name is Alice and I work in software engineering.',
});
console.log('Assistant:', turn1.output_text);
// "Nice to meet you, Alice! What are you working on in software engineering?"

// Turno 2: acompanhamento, referenciando o turno 1
const turn2 = await client.responses.create({
  model: assistantId,
  input: 'What is my profession?',
  previous_response_id: turn1.id,
});
console.log('Assistant:', turn2.output_text);
// "You mentioned that you work in software engineering."

// Turno 3: referencia o turno 2
const turn3 = await client.responses.create({
  model: assistantId,
  input: 'Can you suggest some career growth tips for someone in my field?',
  previous_response_id: turn2.id,
});
console.log('Assistant:', turn3.output_text);
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://your-admin.example.com/v1",
    api_key=os.environ['NODEXA_API_KEY'],
)

assistant_id = "YOUR_ASSISTANT_ID"

# Turno 1
turn1 = client.responses.create(
    model=assistant_id,
    input="My name is Alice and I work in software engineering.",
)
print("Assistant:", turn1.output_text)

# Turno 2
turn2 = client.responses.create(
    model=assistant_id,
    input="What is my profession?",
    previous_response_id=turn1.id,
)
print("Assistant:", turn2.output_text)

# Turno 3
turn3 = client.responses.create(
    model=assistant_id,
    input="Can you suggest some career growth tips for someone in my field?",
    previous_response_id=turn2.id,
)
print("Assistant:", turn3.output_text)
# Turno 1
TURN1=$(curl -s "https://your-admin.example.com/v1/responses" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "YOUR_ASSISTANT_ID",
    "input": "My name is Alice and I work in software engineering."
  }')

echo "Assistant: $(echo $TURN1 | jq -r '.output_text')"
RESP1_ID=$(echo $TURN1 | jq -r '.id')

# Turno 2
TURN2=$(curl -s "https://your-admin.example.com/v1/responses" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"model\": \"YOUR_ASSISTANT_ID\",
    \"input\": \"What is my profession?\",
    \"previous_response_id\": \"$RESP1_ID\"
  }")

echo "Assistant: $(echo $TURN2 | jq -r '.output_text')"
RESP2_ID=$(echo $TURN2 | jq -r '.id')

# Turno 3
curl "https://your-admin.example.com/v1/responses" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"model\": \"YOUR_ASSISTANT_ID\",
    \"input\": \"Can you suggest some career growth tips for someone in my field?\",
    \"previous_response_id\": \"$RESP2_ID\"
  }"

Iniciando uma Nova Conversa

Para iniciar uma conversa nova, omita previous_response_id. A plataforma cria automaticamente uma nova conversa.

{
  "model": "YOUR_ASSISTANT_ID",
  "input": "Hello, I have a new question for you."
}

Continuidade com Streaming

A continuidade funciona da mesma forma com streaming. Leia o ID da resposta do evento response.completed:

const stream = await client.responses.create({
  model: 'YOUR_ASSISTANT_ID',
  input: 'Tell me about black holes.',
  previous_response_id: previousId,
  stream: true,
});

let responseId = null;

for await (const event of stream) {
  if (event.type === 'response.output_text.delta') {
    process.stdout.write(event.delta);
  }
  if (event.type === 'response.completed') {
    responseId = event.response.id;
  }
}

// Use responseId para o próximo turno

Continuidade com Chamadas de Tool

Quando uma resposta tem status: "requires_action" (uma function tool foi chamada), você deve continuar a mesma conversa com o resultado da função:

// Passo 1: Requisição inicial
const response = await client.responses.create({
  model: 'YOUR_ASSISTANT_ID',
  input: 'What is the weather in Paris?',
  tools: [
    {
      type: 'function',
      name: 'get_weather',
      parameters: {
        type: 'object',
        properties: {
          location: { type: 'string' },
        },
        required: ['location'],
      },
    },
  ],
});

// Passo 2: response.status === 'requires_action'
// Extrair a chamada de tool
const toolCall = response.output.find(item => item.type === 'function_call');

// Passo 3: Executar a função
const weatherData = await myGetWeatherFunction(
  JSON.parse(toolCall.arguments).location
);

// Passo 4: Retornar o resultado em uma nova request, continuando a MESMA conversa
const finalResponse = await client.responses.create({
  model: 'YOUR_ASSISTANT_ID',
  previous_response_id: response.id, // <- mesmo thread
  input: [
    {
      type: 'function_call_output',
      call_id: toolCall.call_id,
      output: JSON.stringify(weatherData),
    },
  ],
});

console.log(finalResponse.output_text);

Boas Práticas

Sempre armazene o ID da resposta mais recente. O ID da resposta do turno mais recente é o que você passa como previous_response_id — não o ID da primeira mensagem da conversa.

// Correto: armazene e atualize o ID a cada turno
let lastResponseId = null;

async function chat(message) {
  const response = await client.responses.create({
    model: assistantId,
    input: message,
    ...(lastResponseId ? { previous_response_id: lastResponseId } : {}),
  });
  lastResponseId = response.id; // sempre atualiza
  return response.output_text;
}

Inclua x-user-id para memória por usuário. Quando a continuidade é combinada com um user ID, o assistant também recupera itens de memória de longo prazo de sessões anteriores.

const response = await client.responses.create(
  {
    model: assistantId,
    input: message,
    previous_response_id: lastResponseId,
  },
  {
    headers: { 'x-user-id': currentUserId },
  }
);

Não reconstrua o histórico manualmente. Se você tem um previous_response_id, não precisa reenviar mensagens anteriores em input. A plataforma carrega o histórico completo automaticamente. Enviar histórico redundante em input junto com previous_response_id pode resultar em mensagens duplicadas.


Persistência da Conversa

O histórico de conversa é armazenado no servidor e persiste indefinidamente (sujeito à política de retenção da sua plataforma). As conversas sobrevivem a reinicializações do servidor e podem ser retomadas entre sessões do cliente.

Se você precisar invalidar uma conversa (por exemplo, a sessão do usuário terminou), simplesmente inicie uma nova omitindo previous_response_id.