Saltar al contenido

Chat compatible con OpenAI ​

Usa POST /v1/chat/completions y GET /v1/models con el SDK de OpenAI para Python o JavaScript cambiando la URL base y la clave API. La compatibilidad abarca Chat Completions de texto, no todas las funciones de OpenAI.

Autenticación y modelos ​

Usa la clave actual de la consola: Authorization: Bearer sk-your-key. La lista incluye modelos de texto disponibles e identificadores públicos. Usa el id devuelto, no el nombre visible. Los precios y las voces siguen en /v1/chat/catalog.

bash
curl https://api.coldstart.win/v1/models -H "Authorization: Bearer sk-your-key"
json
{"object":"list","data":[{"id":"chat-standard","object":"model","created":0,"owned_by":"girllab"}]}

Solicitudes e historial ​

Cada solicitud debe enviar el array messages completo y ordenado. Roles: system, developer, user, assistant, tool. El contenido puede ser texto o un array de { "type": "text", "text": "..." }. No se añade historial del servidor ni una personalidad predeterminada. Envía las instrucciones del sistema necesarias y el historial pertinente en cada turno.

bash
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}'
json
{
  "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 admitidos ​

Son obligatorios model y un array messages no vacío. Opcionales: stream (false por defecto), temperature (0–2), top_p (0–1), max_tokens o max_completion_tokens (entero 1–8192, excluyentes), stop (una cadena o 1–4 cadenas), presence_penalty y frequency_penalty (−2–2), seed (entero seguro), n (solo 1). Si se omiten, se usan los valores del servicio; su efecto depende del modelo. stream_options: {"include_usage": true} requiere stream: true. Los valores null opcionales usan los predeterminados. El JSON tiene un límite de 15 MiB; el contexto depende de la capacidad de tokens del modelo.

Streaming y uso ​

SSE usa solo data:, sin eventos personalizados event: delta o event: completed. Lee choices[0].delta.content, el finish_reason final (stop, length, content_filter, tool_calls) y data: [DONE]. Con include_usage: true, un bloque extra con choices: [] y el usage final precede al cierre; los demás llevan usage: null. Sin esta opción se omite usage. Todos los bloques comparten ID local, fecha de creación e ID público del modelo.

json
{"model":"chat-standard","messages":[{"role":"user","content":"Hello!"}],"stream":true,"stream_options":{"include_usage":true}}
text
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]

Errores y alcance ​

Formato de error: { "error": { "message": "...", "type": "invalid_request_error", "param": null, "code": "invalid_request" } }. HTTP 400 indica datos inválidos o no admitidos; 401 clave inválida, 402 saldo insuficiente, 429 límite de solicitudes, 503 fallo temporal y 504 tiempo agotado. Los detalles se anonimizan. Antes del stream se devuelve un error HTTP JSON; después, un bloque data: {"error": ...} lo cierra sin marcador de éxito. Una respuesta parcial no está completa. Límites: 90 segundos hasta el primer texto, 60 segundos sin texto nuevo (reiniciados con cada delta), 60 segundos sin streaming.

No se admiten entradas de imagen/audio, búsqueda o ejecución de código alojadas, los antiguos functions / function_call, tipos de herramientas personalizados, logprobs, múltiples candidatos, store, Responses API ni parámetros no indicados. Se rechazan expresamente. Para voz, usa /v1/chat/speech.

Facturación y ejemplos SDK ​

Se mantienen el saldo, los precios públicos y la facturación de tokens de entrada/salida. Se reservan créditos antes de generar, se liquida el uso real al finalizar y se libera el sobrante. Los fallos, uso inválido o desconexión antes de liquidar liberan la reserva. Cancelar después de liquidar no revierte el cargo. Las llamadas aparecen en el historial de uso y el panel de administración. El JSON estándar incluye usage, sin un billing personalizado. Repetir solicitudes puede generar nuevos cargos; no hay garantía de idempotencia.

bash
pip install openai
npm install openai
python
import 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)
javascript
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);
}

Herramientas de agentes y salida estructurada ​

Consulta models[].capabilities en /v1/chat/catalog: tool_calling, parallel_tool_calls, json_mode, structured_outputs. Las capacidades dependen del modelo; las no admitidas devuelven HTTP 400 antes de generar. Tu aplicación ejecuta las herramientas. La API no ejecuta funciones ni guarda la memoria del agente.

Se admiten tools (hasta 128 funciones), tool_choice (auto, none, required o una función concreta) y parallel_tool_calls (booleano, requiere tools). Las funciones aceptan name, description, parameters de JSON Schema y strict opcional. Lee message.tool_calls; content puede ser null. Añade el mensaje assistant sin cambios y un mensaje role: "tool" por llamada con su tool_call_id. Devuelve todos los resultados, incluidos los errores, antes de la siguiente llamada. Conserva identificadores únicos y el orden.

En streaming, agrupa choices[0].delta.tool_calls por index, concatena los fragmentos de function.arguments y conserva id, type, function.name. Ejecuta solo tras finish_reason: "tool_calls" y el fin correcto del flujo; nunca con length o errores. Los deltas de herramientas reinician el límite de inactividad de 60 segundos; el primer resultado tiene 90 segundos. Valida nombres, argumentos y permisos, y limita las rondas.

response_format admite text, json_object y json_schema con json_schema: {name, schema, strict, description?}. En modo JSON, solicita JSON expresamente en el prompt. Los esquemas estrictos requieren todas las propiedades en required y additionalProperties: false; null permite valores opcionales. No combines JSON Schema con parallel_tool_calls: true. Comprueba refusal, length y errores antes de analizar. El esquema no garantiza la veracidad. Definiciones, argumentos y resultados cuentan como tokens; cada ronda del modelo se factura por separado.

Bucle completo de herramientas ​

python
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")

Ejemplo de salida estructurada ​

python
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)
© 2026 ColdStart. Todos los derechos reservados.