Construindo um Backend de Aplicativo de Chat em Tempo Real com Node.js e API do Taotoken

Implementando um backend de chat em tempo real com Node.js e API do Taotoken


Este artigo é direcionado a desenvolvedores de backend com Node.js, demonstrando como utilizar o SDK oficial do OpenAI junto com a API compatível OpenAI do Taotoken para criar uma interface de completão de chat com suporte a saída em fluxo. Abordaremos configuração do ambiente, chamadas da API, gestão de contexto e tratamento de eros, finalizando com a implantação de um endpoint funcional.

  1. Preparação do Ambiente e Inicialização do Projeto

Antes de começar, você precisará de uma conta no Taotoken. Acesse o console do Taotoken, na seção 'Chaves de API' crie uma nova chave. Além disso, verifique e anote o ID do modelo que pretende usar no 'Mercado de Modelos', por exemplo 'claude-sonnet-4-6' ou 'gpt-4o-mini'.

Crie um novo diretório para o projeto e inicialize-o:

mkdir chat-backend
cd chat-backend
npm init -y

Instale as dependências necessárias. Utilizaremos o SDK oficial do OpenAI para chamadas da API, o Express para construir o serviço web e o dotenv para gerenciar variáveis de ambiente.

npm install openai express dotenv
npm install -D nodemon

Crie um arquivo .env na raiz do projeto para armazenar suas chaves de API de forma segura:

TOKEN_API_TAOTOKEN= sua_chave_api_taotoken
PORTA=3000
  1. Configuração do SDK do OpenAI e Chamada de Interface em Fluxo

O Taotoken oferece uma API HTTP compatível com o OpenAI, permitindo que você use diretamente o SDK oficial do OpenAI, modificando apenas a configuração da baseURL. Crie um módulo principal para chamadas da API em src/clienteTaotoken.js.

import OpenAI from 'openai';
import dotenv from 'dotenv';

dotenv.config();

const cliente = new OpenAI({
  apiKey: process.env.TOKEN_API_TAOTOKEN,
  baseURL: 'https://taotoken.net/api',
});

export async function criarRespostaStreaming(mensagens, modelo = 'claude-sonnet-4-6') {
  try {
    const fluxo = await cliente.chat.completions.create({
      modelo: modelo,
      mensagens: mensagens,
      stream: true,
    });

    return fluxo;
  } catch (erro) {
    console.error('Falha na chamada da API:', erro);
    throw erro;
  }
}

A chave está no ajuste da baseURL para 'https://taotoken.net/api'. Quando o parâmetro stream for definido como true, a API retornará um objeto iterável para receber tokens gerados gradualmente pelo modelo.

  1. Construção do Serviço Express e Endpoint de Resposta em Fluxo

Em seguida, implementamos um serviço Express com um endpoint POST '/chat' que recebe mensagens do usuário, chama a interface em fluxo e retorna os resultados como eventos Server-Sent (SSE) para o frontend.

import express from 'express';
import { criarRespostaStreaming } from './clienteTaotoken.js';
import dotenv from 'dotenv';

dotenv.config();
const app = express();
const porta = process.env.PORTA || 3000;

app.use(express.json());

// Armazenamento em memória para demonstração de gestão de contexto
const armazenamentoConversas = new Map();

app.post('/chat', async (req, res) => {
  const { mensagem, sessionId = 'padrão' } = req.body;
  const modelo = req.body.modelo || 'claude-sonnet-4-6';

  if (!mensagem) {
    return res.status(400).json({ erro: 'Conteúdo da mensagem não pode estar vazio' });
  }

  // Obter ou inicializar histórico da conversa
  if (!armazenamentoConversas.has(sessionId)) {
    armazenamentoConversas.set(sessionId, []);
  }
  const mensagens = armazenamentoConversas.get(sessionId);
  mensagens.push({ papel: 'usuario', conteudo: mensagem });

  // Configurar cabeçalhos SSE
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  let respostaCompleta = '';

  try {
    const fluxo = await criarRespostaStreaming(mensagens, modelo);

    for await (const chunk of fluxo) {
      const conteudo = chunk.choices[0]?.delta?.conteudo || '';
      if (conteudo) {
        respostaCompleta += conteudo;
        // Enviar cada token como evento SSE
        res.write(`data: ${JSON.stringify({ conteudo })}\n\n`);
      }
    }

    // Após o fluxo, adicionar a resposta do assistente ao histórico
    mensagens.push({ papel: 'assistente', conteudo: respostaCompleta });
    armazenamentoConversas.set(sessionId, mensagens);

    // Enviar evento de término
    res.write(`data: [DONE]\n\n`);
    res.end();

  } catch (erro) {
    console.error('Erro no processamento do fluxo:', erro);
    // Enviar mensagem de erro e fechar conexão
    res.write(`data: ${JSON.stringify({ erro: 'Serviço de modelo temporariamente indisponível' })}\n\n`);
    res.end();
  }
});

// Opcional: Interface para limpar contexto de uma sessão
app.delete('/chat/:sessionId', (req, res) => {
  const { sessionId } = req.params;
  armazenamentoConversas.delete(sessionId);
  res.json({ sucesso: true });
});

app.listen(porta, () => {
  console.log(`Servidor rodando em http://localhost:${porta}`);
});

Esse serviço realiza várias tarefas: recebe mansagens e IDs de sessão, mantém histórico de conversa em memória, chama a API em fluxo do Taotoken, transmite tokens em tempo real para o cliente e trata erros adequadamente.

  1. Tratamento de Erros e Considerações para Produção

O código acima inclui tratamento básico de erros. Em produção, você deve considerar mais aspectos.

Primeiro, as chamadas da API podem enfrentar problemas de rede, falhas de autenticação, modelos indisponíveis ou limite de cotas. O SDK do OpenAI lança erros específicos que podemos classificar com mais precisão.

// No clienteTaotoken.js melhorando o tratamento de erros
export async function criarRespostaStreaming(mensagens, modelo) {
  try {
    const fluxo = await cliente.chat.completions.create({
      modelo: modelo,
      mensagens: mensagens,
      stream: true,
    });
    return fluxo;
  } catch (erro) {
    // Classificar erros conforme tipo
    if (erro instanceof OpenAI.APIError) {
      // Erro identificado pelo SDK do OpenAI
      console.error(`Erro API (código ${erro.status}):`, erro.mensagem);
      // Aqui poderia ser adicionada lógica de retry ou downgrade
      throw new Error(`Requisição falhou: ${erro.mensagem}`);
    } else if (erro instanceof OpenAI.APIConnectionError) {
      // Problemas de conexão
      console.error('Erro de conexão:', erro.mensagem);
      throw new Error('Erro de conexão, verifique e tente novamente');
    } else {
      // Outros erros desconhecidos
      console.error('Erro desconhecido:', erro);
      throw new Error('Erro interno do sistema');
    }
  }
}

Segundo, o armazenamento em memória ('armazenamentoConversas') é adequado apenas para demonstração ou deploys de instância única. Para aplicações escaláveis ou com requisitos de persistência, recomenda-se substituí-lo por armazenamento externo como Redis ou banco de dados. Além disso, deve-se considerar limites de tamanho ou quantidade de tokens para evitar exceder o contexto do modelo ou custos elevados.

Por fim, recomendamos adicionar limites de taxa de requisições, verificações de segurança nas entradas (como filtragem de palavras sensíveis) e logs mais detalhados, essenciais para aplicações de produção.

  1. Execução e Teste

Adicione scripts de inicialização no package.json:

{
  "scripts": {
    "dev": "nodemon src/app.js",
    "start": "node src/app.js"
  },
  "type": "module"
}

Use 'npm run dev' para iniciar o servidor de desenvolvimento. Pode-se testar o endpoint usando curl ou Postman:

curl -X POST http://localhost:3000/chat \
  -H "Content-Type: application/json" \
  -d '{
    "mensagem": "Olá, apresente-se.",
    "sessionId": "teste-1"
  }'

Para respostas em fluxo, é necessário um cliente que suporte SSE. Um exemplo simples de página frontend pode validar a funcionalidade. Crie um arquivo public/teste.html e abra-o no navegador, com código JavaScript centralizado:

const sourceEvento = new EventSource(`http://localhost:3000/chat?sse=1`); // Exemplo simplificado, na prática precisa integrar POST com SSE
// Uma abordagem mais prática seria usar Fetch API com ReadableStream para tratar respostas em fluxo

Nota: A abordagem descrita acima é apenas ilustrativa, a integração completa entre frontend e backend requer conhecimento adicional sobre manipulação de fluxos, que ultrapassa o escopo deste tutorial de backend.

Através dessas etapas, você já construiu um backend de chat em tempo real baseado em Node.js e API do Taotoken, com suporte a saída em fluxo. Ele possui capacidades básicas de gestão de contexto de conversa, tratamento de erros e respostas em tempo real. Você pode expandir essa base com funcionalidades avançadas como autenticação de usuários, estratégias de conversas multirrouca, cache de respostas e outras funcionalidades específicas às necessidades do seu negócio. Todos os detalhes de configuração relacionados à API do Taotoken, como lista de modelos disponíveis e detalhes de cobrança, devem ser consultados no console e na documentação oficial.

Tags: Node.js express SDK OpenAI SSE APIs

Publicado em 9-21 18:45