Chat compatível com OpenAI
Use POST /v1/chat/completions e GET /v1/models com o SDK OpenAI para Python ou JavaScript alterando a URL base e a chave API. A compatibilidade abrange Chat Completions de texto, não todos os recursos da OpenAI.
Autenticação e modelos
Use a chave atual do console: Authorization: Bearer sk-your-key. A lista contém modelos de texto disponíveis e IDs públicos. Use o id retornado, não o nome exibido. Preços e vozes continuam em /v1/chat/catalog.
curl https://api.coldstart.win/v1/models -H "Authorization: Bearer sk-your-key"{"object":"list","data":[{"id":"chat-standard","object":"model","created":0,"owned_by":"girllab"}]}Solicitações e histórico
Envie o array messages completo e ordenado em cada solicitação. Papéis: system, developer, user, assistant, tool. O conteúdo pode ser uma string ou um array de { "type": "text", "text": "..." }. Nenhum histórico do servidor ou personagem padrão é adicionado. Reenvie as instruções de sistema necessárias e o histórico relevante em cada turno.
curl https://api.coldstart.win/v1/chat/completions \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{"model":"chat-standard","messages":[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"Hello!"}],"max_tokens":256}'{
"id": "chatcmpl_example",
"object": "chat.completion",
"created": 1792540800,
"model": "chat-standard",
"choices": [{"index": 0, "message": {"role": "assistant", "content": "Hello!", "refusal": null}, "logprobs": null, "finish_reason": "stop"}],
"usage": {"prompt_tokens": 12, "completion_tokens": 3, "total_tokens": 15}
}Parâmetros aceitos
model e um array messages não vazio são obrigatórios. Opcionais: stream (padrão false), temperature (0–2), top_p (0–1), max_tokens ou max_completion_tokens (inteiro 1–8192, exclusivos), stop (uma string ou 1–4 strings), presence_penalty e frequency_penalty (−2–2), seed (inteiro seguro), n (somente 1). Valores omitidos usam os padrões do serviço; o efeito depende do modelo. stream_options: {"include_usage": true} exige stream: true. Valores null opcionais usam os padrões. O corpo JSON tem limite de 15 MiB; o contexto depende do limite de tokens do modelo.
Streaming e uso
O SSE usa somente data:, sem eventos personalizados event: delta ou event: completed. Leia choices[0].delta.content, o finish_reason final (stop, length, content_filter, tool_calls) e data: [DONE]. Com include_usage: true, um bloco extra com choices: [] e usage final antecede o encerramento; os demais têm usage: null. Sem essa opção, usage é omitido. Todos os blocos compartilham ID local, horário de criação e ID público do modelo.
{"model":"chat-standard","messages":[{"role":"user","content":"Hello!"}],"stream":true,"stream_options":{"include_usage":true}}data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}],"usage":null}
data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[{"index":0,"delta":{"content":"Hello!"},"logprobs":null,"finish_reason":null}],"usage":null}
data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}
data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":3,"total_tokens":15}}
data: [DONE]Erros e escopo
Formato de erro: { "error": { "message": "...", "type": "invalid_request_error", "param": null, "code": "invalid_request" } }. HTTP 400 indica entrada inválida ou não aceita; 401 chave inválida, 402 saldo insuficiente, 429 limite de chamadas, 503 falha temporária e 504 tempo esgotado. Os detalhes são anonimizados. Antes do streaming, a falha retorna erro HTTP JSON; depois, um bloco data: {"error": ...} encerra o fluxo sem marcador de sucesso. Resposta parcial não significa conclusão. Limites: 90 segundos até o primeiro texto, 60 segundos sem novo texto (reiniciados a cada delta), 60 segundos sem streaming.
Não são suportados: entradas de imagem/áudio, busca ou execução de código hospedadas, antigos functions / function_call, tipos de ferramentas personalizados, logprobs, múltiplos candidatos, store, Responses API e parâmetros não listados. São rejeitados explicitamente. Para voz, use /v1/chat/speech.
Cobrança e exemplos SDK
O saldo, os preços públicos e a cobrança por tokens de entrada/saída são os mesmos. Créditos são reservados antes da geração, o uso real é cobrado no sucesso e a sobra é liberada. Falhas, uso inválido ou desconexão antes da liquidação liberam a reserva. Cancelar após a liquidação não desfaz a cobrança. As chamadas aparecem no histórico de uso e painel administrativo. O JSON padrão contém usage, sem billing personalizado. Repetir uma solicitação pode gerar nova cobrança; não há garantia de idempotência.
pip install openai
npm install openaiimport os
from openai import OpenAI
client = OpenAI(api_key=os.environ["KARMAN_API_KEY"], base_url="https://api.coldstart.win/v1", max_retries=0)
print([model.id for model in client.models.list().data])
model = os.environ["KARMAN_MODEL"]
messages = [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Hello!"}]
reply = client.chat.completions.create(model=model, messages=messages, max_tokens=256)
print(reply.choices[0].message.content)
stream = client.chat.completions.create(model=model, messages=messages, max_tokens=256,
stream=True, stream_options={"include_usage": True})
for chunk in stream:
if chunk.choices:
print(chunk.choices[0].delta.content or "", end="", flush=True)
if chunk.usage:
print("\n", chunk.usage)import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.KARMAN_API_KEY, baseURL: "https://api.coldstart.win/v1", maxRetries: 0 });
const models = await client.models.list();
console.log(models.data.map(model => model.id));
const stream = await client.chat.completions.create({
model: process.env.KARMAN_MODEL,
messages: [{ role: "user", content: "Hello!" }],
stream: true,
stream_options: { include_usage: true }
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta.content ?? "");
if (chunk.usage) console.log("\n", chunk.usage);
}Ferramentas de agentes e saída estruturada
Consulte models[].capabilities em /v1/chat/catalog: tool_calling, parallel_tool_calls, json_mode, structured_outputs. As capacidades variam por modelo; recursos incompatíveis retornam HTTP 400 antes da geração. Sua aplicação executa as ferramentas. A API não executa funções nem armazena a memória do agente.
Use tools (até 128 funções), tool_choice (auto, none, required ou uma função específica) e parallel_tool_calls (booleano, requer tools). Funções aceitam name, description, parameters em JSON Schema e strict opcional. Leia message.tool_calls; content pode ser null. Preserve a mensagem assistant e adicione uma mensagem role: "tool" por chamada com o tool_call_id correspondente. Envie todos os resultados, inclusive falhas, antes da próxima chamada. Preserve IDs únicos e a ordem.
No streaming, agrupe choices[0].delta.tool_calls por index, concatene fragmentos de function.arguments e mantenha id, type, function.name. Execute apenas após finish_reason: "tool_calls" e o encerramento correto do fluxo; nunca com length ou erros. Deltas de ferramentas reiniciam o limite ocioso de 60 segundos; a primeira saída tem limite de 90 segundos. Valide nomes, argumentos e permissões e limite as rodadas.
response_format aceita text, json_object ou json_schema com json_schema: {name, schema, strict, description?}. No modo JSON, peça JSON explicitamente no prompt. Schemas estritos exigem todas as propriedades em required e additionalProperties: false; null pode representar valores opcionais. Não combine JSON Schema com parallel_tool_calls: true. Verifique refusal, length e erros antes de analisar. O schema não garante exatidão factual. Definições, argumentos e resultados entram na cobrança de tokens; cada rodada é cobrada separadamente.
Ciclo completo de ferramentas
import os, json
from openai import OpenAI
client = OpenAI(api_key=os.environ["KARMAN_API_KEY"],
base_url="https://api.coldstart.win/v1", max_retries=0)
model = os.environ["KARMAN_MODEL"]
tools = [{"type": "function", "function": {
"name": "lookup_memory", "description": "Read a saved preference.",
"parameters": {"type": "object", "properties": {"topic": {"type": "string"}},
"required": ["topic"], "additionalProperties": False},
"strict": True
}}]
messages = [{"role": "user", "content": "What food do I like? Use my saved memory."}]
for _ in range(4):
reply = client.chat.completions.create(
model=model, messages=messages, tools=tools,
tool_choice="auto", parallel_tool_calls=False, max_tokens=512)
choice = reply.choices[0]
message = choice.message
if message.refusal or choice.finish_reason not in ("stop", "tool_calls"):
raise RuntimeError("Incomplete or refused response")
messages.append(message.model_dump(exclude_none=True))
if not message.tool_calls:
print(message.content)
break
for call in message.tool_calls:
try:
if call.function.name != "lookup_memory":
raise ValueError("Unknown function")
args = json.loads(call.function.arguments)
if not isinstance(args, dict) or set(args) != {"topic"} or not isinstance(args["topic"], str):
raise ValueError("Invalid arguments")
result = {"topic": args["topic"], "preference": "apples"}
except (ValueError, TypeError):
result = {"error": "Invalid tool request"}
messages.append({"role": "tool", "tool_call_id": call.id,
"content": json.dumps(result)})
else:
raise RuntimeError("Agent round limit reached")Exemplo de saída estruturada
reply = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "I like apples. Extract this preference as JSON."}],
response_format={"type": "json_schema", "json_schema": {
"name": "memory", "strict": True,
"schema": {"type": "object", "properties": {"preference": {"type": "string"}},
"required": ["preference"], "additionalProperties": False}
}}, max_tokens=256)
choice = reply.choices[0]
if choice.finish_reason != "stop" or choice.message.refusal:
raise RuntimeError("Incomplete or refused response")
memory = json.loads(choice.message.content)
print(memory)