Ir para o conteúdo

Guia de Integração com o OpenAI SDK

A API do Nodexa é wire-compatible com a Responses API da OpenAI. Você pode usar o SDK oficial da OpenAI para Node.js ou Python sem nenhum código customizado — basta apontá-lo para sua instância Nodexa.


Configuração

O sufixo de path /v1 é obrigatório

O baseURL deve terminar com /v1. Esse é o erro de configuração mais comum.

# Correto
baseURL: 'https://app.nodexa.cloud/v1'

# Errado — as requests não vão chegar à API
baseURL: 'https://app.nodexa.cloud'

Sem /v1, as requests caem em um middleware que retorna uma página de redirecionamento em vez de uma resposta da API, gerando erros confusos que não parecem erros de API.

Instale o OpenAI SDK:

npm install openai

Configure o cliente:

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://app.nodexa.cloud/v1',
  apiKey: process.env.NODEXA_API_KEY,
});

Com CommonJS:

const OpenAI = require('openai');

const client = new OpenAI({
  baseURL: 'https://app.nodexa.cloud/v1',
  apiKey: process.env.NODEXA_API_KEY,
});

Instale o OpenAI SDK:

pip install openai

Configure o cliente:

from openai import OpenAI
import os

client = OpenAI(
    base_url="https://app.nodexa.cloud/v1",
    api_key=os.environ["NODEXA_API_KEY"],
)

Com um arquivo .env usando python-dotenv:

from openai import OpenAI
from dotenv import load_dotenv
import os

load_dotenv()

client = OpenAI(
    base_url="https://app.nodexa.cloud/v1",
    api_key=os.environ["NODEXA_API_KEY"],
)

Enviando Headers Adicionais

Algumas funcionalidades do Nodexa precisam de headers customizados (x-user-id, x-user-tokens). Você pode passar headers extras usando a opção defaultHeaders do SDK ou via headers por request.

const client = new OpenAI({
  baseURL: 'https://your-admin.example.com/v1',
  apiKey: process.env.NODEXA_API_KEY,
  defaultHeaders: {
    'x-user-id': currentUserId,
  },
});
const response = await client.responses.create(
  {
    model: 'YOUR_ASSISTANT_ID',
    input: 'What meetings do I have today?',
  },
  {
    headers: {
      'x-user-id': userId,
      'x-user-tokens': JSON.stringify({ google: userGoogleToken }),
    },
  }
);
client = OpenAI(
    base_url="https://your-admin.example.com/v1",
    api_key=os.environ["NODEXA_API_KEY"],
    default_headers={"x-user-id": current_user_id},
)
import json

response = client.responses.create(
    model="YOUR_ASSISTANT_ID",
    input="What meetings do I have today?",
    extra_headers={
        "x-user-id": user_id,
        "x-user-tokens": json.dumps({"google": user_google_token}),
    },
)

Requests Sem Streaming

import OpenAI from 'openai';

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

async function ask(question) {
  const response = await client.responses.create({
    model: process.env.NODEXA_ASSISTANT_ID,
    input: question,
  });

  return {
    id: response.id,
    text: response.output_text,
    status: response.status,
  };
}

const result = await ask('What is the difference between TCP and UDP?');
console.log(result.text);
from openai import OpenAI
import os

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

def ask(question: str) -> dict:
    response = client.responses.create(
        model=os.environ["NODEXA_ASSISTANT_ID"],
        input=question,
    )
    return {
        "id": response.id,
        "text": response.output_text,
        "status": response.status,
    }

result = ask("What is the difference between TCP and UDP?")
print(result["text"])

Requests com Streaming

import OpenAI from 'openai';

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

async function streamAnswer(question) {
  const stream = await client.responses.create({
    model: process.env.NODEXA_ASSISTANT_ID,
    input: question,
    stream: true,
  });

  let fullText = '';
  let responseId = null;

  for await (const event of stream) {
    switch (event.type) {
      case 'response.output_text.delta':
        process.stdout.write(event.delta);
        fullText += event.delta;
        break;

      case 'response.completed':
        responseId = event.response.id;
        break;
    }
  }

  console.log('\n');
  return { text: fullText, id: responseId };
}

const { text, id } = await streamAnswer('Explain how async/await works in JavaScript.');
console.log('Response ID for threading:', id);
from openai import OpenAI
import os

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

def stream_answer(question: str) -> tuple[str, str]:
    full_text = ""
    response_id = None

    with client.responses.stream(
        model=os.environ["NODEXA_ASSISTANT_ID"],
        input=question,
    ) as stream:
        for event in stream:
            if event.type == "response.output_text.delta":
                print(event.delta, end="", flush=True)
                full_text += event.delta
            elif event.type == "response.completed":
                response_id = event.response.id

    print()
    return full_text, response_id

text, response_id = stream_answer("Explain how async/await works in Python.")
print(f"Response ID: {response_id}")

Conversas com Múltiplos Turnos

import OpenAI from 'openai';
import * as readline from 'readline';

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

async function interactiveChat() {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  let lastResponseId = null;

  const prompt = (question) =>
    new Promise((resolve) => rl.question(question, resolve));

  console.log('Chat with Nodexa (type "exit" to quit)\n');

  while (true) {
    const userInput = await prompt('You: ');
    if (userInput.toLowerCase() === 'exit') break;

    const response = await client.responses.create({
      model: process.env.NODEXA_ASSISTANT_ID,
      input: userInput,
      ...(lastResponseId ? { previous_response_id: lastResponseId } : {}),
    });

    lastResponseId = response.id;
    console.log(`Assistant: ${response.output_text}\n`);
  }

  rl.close();
}

interactiveChat();
from openai import OpenAI
import os

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

def interactive_chat():
    last_response_id = None
    print("Chat with Nodexa (type 'exit' to quit)\n")

    while True:
        user_input = input("You: ")
        if user_input.lower() == "exit":
            break

        kwargs = {
            "model": os.environ["NODEXA_ASSISTANT_ID"],
            "input": user_input,
        }
        if last_response_id:
            kwargs["previous_response_id"] = last_response_id

        response = client.responses.create(**kwargs)
        last_response_id = response.id
        print(f"Assistant: {response.output_text}\n")

interactive_chat()

Function Calling com o SDK

import OpenAI from 'openai';

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

const tools = [
  {
    type: 'function',
    name: 'lookup_order',
    description: 'Look up an order by its order number',
    parameters: {
      type: 'object',
      properties: {
        orderNumber: {
          type: 'string',
          description: 'The order number, e.g. ORD-2024-00123',
        },
      },
      required: ['orderNumber'],
    },
  },
];

async function lookupOrder(orderNumber) {
  // Substitua pela sua lógica real de consulta de pedidos
  return {
    orderNumber,
    status: 'shipped',
    estimatedDelivery: '2024-11-20',
    items: [{ name: 'Widget Pro', quantity: 2, price: 49.99 }],
  };
}

async function chatWithOrderLookup(userMessage) {
  let response = await client.responses.create({
    model: process.env.NODEXA_ASSISTANT_ID,
    input: userMessage,
    tools,
  });

  while (response.status === 'requires_action') {
    const results = [];

    for (const item of response.output) {
      if (item.type !== 'function_call') continue;

      const args = JSON.parse(item.arguments);
      let result;

      if (item.name === 'lookup_order') {
        result = await lookupOrder(args.orderNumber);
      } else {
        result = { error: `Unknown function: ${item.name}` };
      }

      results.push({
        type: 'function_call_output',
        call_id: item.call_id,
        output: JSON.stringify(result),
      });
    }

    response = await client.responses.create({
      model: process.env.NODEXA_ASSISTANT_ID,
      previous_response_id: response.id,
      input: results,
    });
  }

  return response.output_text;
}

const answer = await chatWithOrderLookup('Where is my order ORD-2024-00123?');
console.log(answer);
import json
from openai import OpenAI
import os

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

tools = [
    {
        "type": "function",
        "name": "lookup_order",
        "description": "Look up an order by its order number",
        "parameters": {
            "type": "object",
            "properties": {
                "orderNumber": {
                    "type": "string",
                    "description": "The order number, e.g. ORD-2024-00123",
                }
            },
            "required": ["orderNumber"],
        },
    }
]

def lookup_order(order_number: str) -> dict:
    # Substitua pela lógica real de consulta
    return {
        "orderNumber": order_number,
        "status": "shipped",
        "estimatedDelivery": "2024-11-20",
    }

def chat_with_order_lookup(user_message: str) -> str:
    response = client.responses.create(
        model=os.environ["NODEXA_ASSISTANT_ID"],
        input=user_message,
        tools=tools,
    )

    while response.status == "requires_action":
        results = []
        for item in response.output:
            if item.type != "function_call":
                continue
            args = json.loads(item.arguments)
            if item.name == "lookup_order":
                result = lookup_order(args["orderNumber"])
            else:
                result = {"error": f"Unknown function: {item.name}"}
            results.append({
                "type": "function_call_output",
                "call_id": item.call_id,
                "output": json.dumps(result),
            })
        response = client.responses.create(
            model=os.environ["NODEXA_ASSISTANT_ID"],
            previous_response_id=response.id,
            input=results,
        )

    return response.output_text

print(chat_with_order_lookup("Where is my order ORD-2024-00123?"))

Tratamento de Erros

import OpenAI, { APIError } from 'openai';

try {
  const response = await client.responses.create({
    model: process.env.NODEXA_ASSISTANT_ID,
    input: 'Hello',
  });
  console.log(response.output_text);
} catch (err) {
  if (err instanceof APIError) {
    console.error(`Status: ${err.status}`);
    console.error(`Error type: ${err.error?.type}`);
    console.error(`Message: ${err.message}`);
  } else {
    throw err;
  }
}
from openai import OpenAI, APIError, APIStatusError

try:
    response = client.responses.create(
        model=os.environ["NODEXA_ASSISTANT_ID"],
        input="Hello",
    )
    print(response.output_text)
except APIStatusError as e:
    print(f"Status: {e.status_code}")
    print(f"Message: {e.message}")
except APIError as e:
    print(f"API Error: {e}")

Tipos TypeScript

O OpenAI SDK fornece tipos TypeScript completos para a Responses API:

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: process.env.NODEXA_BASE_URL + '/v1',
  apiKey: process.env.NODEXA_API_KEY!,
});

// Resposta tipada
const response: OpenAI.Responses.Response = await client.responses.create({
  model: process.env.NODEXA_ASSISTANT_ID!,
  input: 'Hello',
});

// Definições de tools tipadas
const tools: OpenAI.Responses.Tool[] = [
  {
    type: 'function',
    name: 'my_function',
    parameters: {
      type: 'object',
      properties: {
        query: { type: 'string' },
      },
      required: ['query'],
    },
  },
];

Compatibilidade de Versão do SDK

O Nodexa é compatível com a Responses API da OpenAI introduzida no SDK openai v4.x. Use uma versão recente:

# Node.js — verificar versão instalada
npm list openai

# Atualizar para a versão mais recente
npm install openai@latest
# Python — verificar versão instalada
pip show openai

# Atualizar para a versão mais recente
pip install --upgrade openai