Migración

Una URL base y una clave trasladan un cliente OpenAI. Esta página también indica lo que la API no hace, porque una migración que descubre eso en producción no es una migración.

La forma de sustitución directa

Apunta la URL base del cliente a https://api.llmeu.com/v1 y proporciónale una clave de API desde la consola. La forma de la solicitud no cambia.

from openai import OpenAI

client = OpenAI(base_url="https://api.llmeu.com/v1", api_key="llmeu_live_xxxxxxxx.your-secret")

resp = client.chat.completions.create(
    model="llmeu-auto",
    messages=[{"role": "user", "content": "Say hello from EU hosting."}],
)
print(resp.choices[0].message.content)

Lo que acepta el endpoint de chat

El validador de solicitudes en apps/api/src/app.mjs comprueba lo siguiente; lo que no comprueba se deja pasar o se ignora en lugar de rechazarse, para que un cliente más reciente siga funcionando.

  • model y messages son obligatorios; messages debe ser un array no vacío.
  • Cada mensaje necesita un role (system, user, assistant, tool o developer) y content como una cadena o un array de partes.
  • stream debe ser un booleano cuando esté presente.
  • temperature, top_p, max_tokens, presence_penalty, frequency_penalty, seed y n deben ser números cuando estén presentes.
  • max_tokens debe ser al menos 1.
  • n debe ser exactamente 1; cualquier otro valor se rechaza.
  • stop puede ser una cadena o un array de cadenas.
  • tools debe ser un array cuando esté presente.
  • llmeu debe ser un objeto; nunca es obligatorio.
  • tool_choice y response_format se reenvían al backend junto con los campos anteriores; un campo extra desconocido no se rechaza.

Extras de solicitud bajo llmeu

Un objeto llmeu con espacio de nombres en el cuerpo de la solicitud; un cliente que ignore campos desconocidos puede enviarlo de forma segura.

Campo Valor Efecto
residencyeu-hosted | eu-owned | de | anyRestringe el enrutamiento a endpoints en esa residencia; un conjunto elegible vacío devuelve 409 no_endpoint_for_policy en lugar de ampliar el filtro.
taskun nombre de tareaLa tarea para la que el enrutador ajusta el modelo.
retentionzeroSolo se implementa cero. Pedir más de lo que permite la política devuelve 403 retention_exceeds_policy; un valor efectivo permitido distinto de cero devuelve 501 retention_not_implemented.
data_classpublic | internal | confidential | restrictedSe verifica contra las clases de datos permitidas por la política: una clase fuera de ellas devuelve 403 data_class_not_allowed, y una clase desconocida devuelve 400 invalid_data_class.
policy_iduuidNombra una política de la misma organización; un id desconocido devuelve 404 policy_not_found.
max_usd_per_1mun númeroUn límite de precio por millón de tokens para esta solicitud.
allow_partnerstrue | falseSi se pueden usar endpoints de socios para esta solicitud.

Las claves desconocidas dentro de llmeu se ignoran; una clave conocida con un valor no válido se rechaza, porque un data_class incorrecto debe fallar de forma cerrada en lugar de significar silenciosamente que no hay clase de datos.

curl https://api.llmeu.com/v1/chat/completions \
  -H "Authorization: Bearer $LLMEU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llmeu-auto",
    "messages": [{"role": "user", "content": "Summarise this contract."}],
    "llmeu": {"residency": "eu-owned", "data_class": "confidential", "retention": "zero"}
  }'

Lo que no existe

Estas respuestas son deliberadas, y un cliente que las espera ve el código de error en lugar de una sustitución silenciosa.

Solicitud Resultado
POST /v1/completions501 not_implemented — el endpoint heredado completions no se ofrece; usa /v1/chat/completions.
n > 1400 unsupported_n — solo se admite n = 1.
POST /v1/embeddingsLos embeddings necesitan un modelo de embedding, y el id solicitado predeterminado es bge-m3. Actualmente los sirve el backend local determinista, cuya respuesta incluye llmeu.mock: true y la nota de que se devuelven vectores de marcador de posición deterministas y no se sirven pesos de embedding en esta implementación.
/v1/files, /v1/batches, /v1/assistants, /v1/fine_tuning, /v1/audio, /v1/images404 unknown_route — no se enrutan en absoluto; una ruta /v1 que el enrutador no conoce responde 404 unknown_route, y cualquier otra ruta responde 404 not_found.

Sacar tus datos

La exportación de cuenta me.json contiene campos seleccionados de la cuenta, organizaciones, metadatos de claves de API sin secretos, políticas actuales, las últimas 200 trazas por organización y agregados de uso diario durante 365 días. No es una copia completa de todos los datos personales ni un registro histórico de políticas.

La exportación de auditoría NDJSON tiene un valor predeterminado de 7 días, permite como máximo 90 días y limita las trazas a 5000; su manifiesto incluye counts.truncated, que marca una exportación que alcanzó el límite.

GET /app/exports/me.json
GET /app/exports/audit.ndjson?days=7
GET /app/exports/traces.json
GET /app/exports/usage.json
GET /app/exports/policies.json

La eliminación de la cuenta en sí se realiza en la página de perfil y está sujeta a la regla de propiedad en la página de la consola.

Una cookie de sesión no es una credencial de API

Una sesión de navegador autentica la consola, no la API. Un cliente OpenAI que envíe una es rechazado con 403 api_key_required y tiene que usar una clave de API en su lugar.

Un rechazo aquí nombra un código, por lo que una migración puede ramificar según él, y el bloque llmeu en cada respuesta dice qué ocurrió realmente.