Unidad 4.4: Integración de AI Model Hub
Introducción
Está agregando una función de IA a TaskBoard: cuando un usuario envía una descripción de tarea larga, la API llama a un modelo de lenguaje de gran escala para generar un resumen de una línea y, a continuación, almacena ese resumen en PostgreSQL. AI Model Hub expone modelos alojados a través de una API REST compatible con OpenAI, por lo que no ejecuta ninguna GPU y no gestiona los pesos del modelo. Envía un prompt a un punto de inferencia, recibe tokens y paga por token.
Esta unidad comienza con la llamada HTTP. Verá las formas exactas de la solicitud y la respuesta, las integrará en Python tanto con requests como con el cliente de OpenAI, agregará la lógica de reintento y tiempo de espera que la inferencia en producción requiere y, a continuación, conectará la función con el resto de TaskBoard a través de llamadas síncronas y una ruta asíncrona encolada con Kafka. Cada bloque de código apunta al punto de acceso real de IONOS CLOUD y a identificadores de modelo reales, por lo que puede copiarlo, configurar su token y ejecutarlo.
1. El punto de acceso de inferencia y la autenticación
AI Model Hub ofrece dos opciones de API: una API nativa de AI Model Hub y una API compatible con OpenAI. La API compatible con OpenAI replica la estructura de solicitud y respuesta de OpenAI, lo que le permite reutilizar las herramientas y los SDK existentes de OpenAI cambiando únicamente la URL base y las credenciales. Para la integración de aplicaciones, este es el camino que debe seguir, porque las formas de solicitud y respuesta ya son familiares y las bibliotecas de cliente oficiales de OpenAI funcionan sin modificaciones.
La URL base compatible con OpenAI es https://openai.inference.de-txl.ionos.com/v1. La autenticación utiliza un token Bearer, que es un JSON Web Token (JWT) con fecha de vencimiento. Las guías de AI Model Hub asumen que el token se almacena en la variable de entorno IONOS_API_TOKEN. Dado que el token es un JWT con una afirmación exp, una solicitud que de repente devuelve un error de autenticación generalmente significa que el token ha vencido, no que la llamada sea incorrecta. Verifique la afirmación exp y regenere el token si ha vencido.
1.1 Primera llamada con curl
Envíe una finalización de chat para confirmar su token y la conectividad antes de escribir cualquier código de aplicación. El punto de acceso es POST /v1/chat/completions y el cuerpo de la solicitud incluye un identificador model y un arreglo messages.
export IONOS_API_TOKEN="your-jwt-token"
curl -s https://openai.inference.de-txl.ionos.com/v1/chat/completions \
-H "Authorization: Bearer ${IONOS_API_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Llama-3.3-70B-Instruct",
"messages": [
{"role": "user", "content": "Summarize in one sentence: the deploy pipeline failed because the registry token expired."}
],
"temperature": 0.2,
"max_tokens": 60
}'
La respuesta es un objeto de finalización de estilo OpenAI. El texto generado se encuentra en choices[0].message.content, y usage informa prompt_tokens, completion_tokens y total_tokens, que necesita para el seguimiento de costos.
{
"id": "chatcmpl-123",
"object": "chat.completion",
"model": "meta-llama/Llama-3.3-70B-Instruct",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "The deploy pipeline failed because the container registry token had expired."},
"finish_reason": "stop"
}
],
"usage": {"prompt_tokens": 28, "completion_tokens": 14, "total_tokens": 42}
}
1.2 Listado de modelos disponibles
La API compatible con OpenAI expone un punto de finalización de modelos para recuperar la lista de modelos disponibles y sus detalles. Úsela para descubrir las cadenas de identificadores de modelo exactas en lugar de codificar una suposición, ya que el identificador es lo que requiere el campo model.
curl -s https://openai.inference.de-txl.ionos.com/v1/models \
-H "Authorization: Bearer ${IONOS_API_TOKEN}" | python3 -m json.tool
El identificador de modelo que proporcione debe coincidir exactamente con el catálogo. Para los modelos de chat utilizados en esta unidad, los identificadores son meta-llama/Llama-3.3-70B-Instruct, openai/gpt-oss-120b y mistralai/Mistral-Small-24B-Instruct. Un error tipográfico en el identificador es una de las causas más comunes de fallos en la primera llamada.
2. Llamada a Model Hub desde el código de la aplicación
En el servicio de API de TaskBoard, se realiza la inferencia desde Python. Se dispone de dos opciones claras: utilizar directamente la API HTTP mediante requests, o emplear el cliente oficial openai dirigido a la URL base de IONOS CLOUD. Ambas opciones acceden al mismo punto de extremo. La ruta de requests mantiene las dependencias al mínimo; el cliente OpenAI proporciona asistentes tipados, iteradores de transmisión y ganchos de reintentos sin coste adicional.
2.1 HTTP directo con requests
Esta es la integración con menor dependencia. También es la forma más clara de ver exactamente lo que se transmite por la red, lo cual resulta útil durante la depuración.
import os
import requests
BASE_URL = "https://openai.inference.de-txl.ionos.com/v1"
TOKEN = os.environ["IONOS_API_TOKEN"]
def summarize(description: str) -> str:
resp = requests.post(
f"{BASE_URL}/chat/completions",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"model": "meta-llama/Llama-3.3-70B-Instruct",
"messages": [
{"role": "system", "content": "You write one-sentence task summaries."},
{"role": "user", "content": description},
],
"temperature": 0.2,
"max_tokens": 60,
},
timeout=30,
)
resp.raise_for_status()
return resp.json()["choices"][0]["message"]["content"].strip()
Establezca siempre un valor explícito para timeout. La latencia de inferencia varía según la longitud del prompt y el tamaño del modelo, y un socket colgado sin timeout bloqueará un hilo de trabajo en su API.
2.2 El cliente de OpenAI dirigido a IONOS CLOUD
Dado que la API es compatible con OpenAI, el paquete oficial de Python openai funciona cuando se sobrescriben base_url y api_key. Esta es la opción más ergonómica para el código de la aplicación.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://openai.inference.de-txl.ionos.com/v1",
api_key=os.environ["IONOS_API_TOKEN"],
)
def summarize(description: str) -> str:
completion = client.chat.completions.create(
model="meta-llama/Llama-3.3-70B-Instruct",
messages=[
{"role": "system", "content": "You write one-sentence task summaries."},
{"role": "user", "content": description},
],
temperature=0.2,
max_tokens=60,
)
return completion.choices[0].message.content.strip()
2.3 Respuestas en streaming
Para una interfaz de usuario interactiva, puede transmitir tokens a medida que se generan estableciendo stream en true. Al transmitir, las estadísticas de uso no se incluyen de forma predeterminada. Para obtener el uso en el fragmento final, debe establecer explícitamente stream_options con include_usage habilitado.
stream = client.chat.completions.create(
model="openai/gpt-oss-120b",
messages=[{"role": "user", "content": "Explain what a poison message is."}],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
La transmisión finaliza con una línea de datos final que contiene usage seguida de un marcador [DONE]. Si omite stream_options, pierde los recuentos de tokens que necesita para la contabilidad de costos.
3. Elección de un modelo: ventana de contexto y precio
La selección del modelo es una decisión de código impulsada por dos cifras: cuántos tokens acepta el modelo (ventana de contexto) y cuánto cuesta cada millón de tokens. Los resúmenes de TaskBoard son cortos, por lo que el modelo más barato con la capacidad adecuada es el valor predeterminado correcto; reserve los modelos más grandes para tareas que realmente los necesiten.
La siguiente tabla compara los modelos de chat utilizados en esta unidad. Los precios están en EUR por millón de tokens.
| Identificador del modelo | Ventana de contexto (tokens) | Precio de entrada (EUR / 1M) | Precio de salida (EUR / 1M) |
|---|---|---|---|
mistralai/Mistral-Small-24B-Instruct |
128000 | 0.10 | 0.30 |
openai/gpt-oss-120b |
128000 | 0.15 | 0.65 |
meta-llama/Llama-3.3-70B-Instruct |
128000 | 0.65 | 0.65 |
Como se muestra arriba, los tres aceptan una ventana de contexto de 128000 tokens, por lo que para un prompt de resumen corto, el factor decisivo es el precio. mistralai/Mistral-Small-24B-Instruct es el más barato tanto en entrada como en salida y es un valor predeterminado sólido para los resúmenes de TaskBoard. Pase a un modelo más grande solo cuando la calidad del resumen en descripciones de tareas reales sea demostrablemente mejor y justifique el recargo por token.
3.1 Configuración de modelo consciente del costo
Haga que el modelo sea un valor de configuración, no un literal disperso por el código, para que pueda cambiarlo por entorno sin volver a desplegar la lógica.
import os
SUMMARY_MODEL = os.environ.get("SUMMARY_MODEL", "mistralai/Mistral-Small-24B-Instruct")
def estimate_cost_eur(prompt_tokens: int, completion_tokens: int,
in_price: float, out_price: float) -> float:
return (prompt_tokens / 1_000_000) * in_price + (completion_tokens / 1_000_000) * out_price
print(estimate_cost_eur(28, 14, 0.10, 0.30)) # 28 prompt + 14 completion tokens, Mistral-Small pricing
3.2 Embeddings para características semánticas
Cuando TaskBoard necesita búsqueda semántica sobre tareas, usted genera vectores con un modelo de embeddings en lugar de un modelo de chat. El punto de acceso es POST /v1/embeddings. El modelo BAAI/bge-m3 devuelve vectores de 1024 dimensiones y tiene un precio de 0,02 EUR por millón de tokens.
def embed(text: str) -> list[float]:
resp = client.embeddings.create(model="BAAI/bge-m3", input=text)
return resp.data[0].embedding # 1024 floats
vec = embed("Fix the expired registry token in the deploy pipeline")
assert len(vec) == 1024
Guarde los vectores resultantes en la ubicación donde se encuentra su capa de búsqueda. La incrustación es determinista para una entrada y un modelo dados, por lo que un texto idéntico siempre produce el mismo vector, lo que convierte a las incrustaciones en un candidato sólido para la caché.
4. Manejo de errores en producción
Las llamadas de inferencia fallan de maneras que sus puntos finales CRUD no presentan: el modelo se ve limitado por la tasa de peticiones, la solicitud expira bajo carga, o la respuesta es JSON bien formado pero el contenido está vacío o tiene un formato incorrecto. El código de producción debe manejar las tres situaciones. La más importante en IONOS CLOUD es el límite de tasa.
4.1 Límites de tasa y reintentos con retroceso ante el código 429
El límite de tasa general de la API es de 5 peticiones por segundo (base), con un margen de ráfaga de 10. Cuando se supera el límite, el servicio devuelve HTTP 429 Too Many Requests. Debe tratar el código 429 como una señal para aplicar retroceso y reintentar, no como un fallo definitivo. Utilice retroceso exponencial para que una ráfaga de actividad de TaskBoard no sature el punto final.
import time
import requests
def chat_with_retry(payload: dict, max_attempts: int = 5) -> dict:
delay = 1.0
for attempt in range(max_attempts):
resp = requests.post(
f"{BASE_URL}/chat/completions",
headers={"Authorization": f"Bearer {TOKEN}"},
json=payload,
timeout=30,
)
if resp.status_code == 429:
retry_after = float(resp.headers.get("Retry-After", delay))
time.sleep(retry_after)
delay *= 2
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError("inference rate-limited after retries")
Respete la cabecera Retry-After cuando el servicio la proporcione, y recurra a su propio retardo exponencial cuando no la proporcione. Establezca un límite al número de intentos para que una interrupción sostenida se manifieste como un error en lugar de un bucle infinito.
4.2 Tiempos de espera y validación de respuestas
Una respuesta 200 no es una garantía de contenido utilizable. El modelo puede devolver una cadena vacía o texto que incumple sus suposiciones aguas abajo. Valide antes de almacenar.
def safe_summary(description: str) -> str:
payload = {
"model": SUMMARY_MODEL,
"messages": [
{"role": "system", "content": "Reply with exactly one sentence."},
{"role": "user", "content": description},
],
"max_tokens": 60,
}
data = chat_with_retry(payload)
choices = data.get("choices") or []
if not choices:
raise ValueError("no choices in inference response")
content = (choices[0]["message"]["content"] or "").strip()
if not content:
raise ValueError("empty summary returned")
return content
Para la extracción estructurada, la API de completados de chat admite un response_format con un esquema JSON y strict habilitado, lo que restringe el modelo para que emita JSON válido que coincida con su esquema. Esa es la forma confiable de obtener una salida interpretable por la máquina en lugar de texto libre que debe analizarse de manera defensiva.
5. Patrones de integración y control de costos
Puede llamar a la inferencia de dos maneras dentro de TaskBoard. La inferencia síncrona se ejecuta dentro de la solicitud que necesita el resultado. La inferencia asíncrona coloca el trabajo en una cola y lo procesa fuera de banda. La elección adecuada depende de si el usuario está esperando la respuesta.
5.1 Síncrona: resumir al crear
Cuando el usuario envía una tarea y espera recibir el resumen de inmediato, llame a la inferencia dentro del gestor de solicitudes y escriba el resumen en PostgreSQL en la misma transacción.
def create_task(db, description: str) -> int:
summary = safe_summary(description)
row = db.execute(
"INSERT INTO tasks (description, summary) VALUES (%s, %s) RETURNING id",
(description, summary),
).fetchone()
db.commit()
return row[0]
Mantenga la ruta síncrona detrás de un tiempo de espera y un presupuesto de reintentos para que un modelo lento no detenga indefinidamente la solicitud dirigida al usuario.
5.2 Asíncrono: encolar inferencia a través de Kafka
Cuando el resumen no se necesita de inmediato, desacople el proceso. La API escribe la tarea de inmediato y genera un evento de cambio de tarea hacia Kafka (véase la Unidad 4.3); un trabajador consume el evento, llama a inferencia y actualiza la fila. Esto mantiene la solicitud de creación rápida y aísla la latencia de inferencia y los límites de velocidad de la ruta del usuario.
def handle_event(event: dict, db): # worker side: consume task event, summarize, persist
task_id = event["task_id"]
description = event["description"]
try:
summary = safe_summary(description)
except (ValueError, RuntimeError):
# route to a dead-letter topic; do not block the consumer group
produce_dead_letter(event)
return
db.execute("UPDATE tasks SET summary = %s WHERE id = %s", (summary, task_id))
db.commit()
El patrón asincrónico también atenúa los picos de carga: el límite de 5 solicitudes por segundo es mucho más fácil de respetar cuando un único consumidor vacía una cola a un ritmo controlado, en lugar de cuando muchos trabajadores web llaman a inferencia de forma simultánea.
5.3 Caché de resultados en Redis
La inferencia es la llamada más costosa en esta funcionalidad, por lo que no se debe pagar dos veces por ella. Utilice una caché basada en una suma de verificación del modelo más la entrada. Las descripciones idénticas no tienen costo después de la primera llamada. Esto se combina de forma natural con la caché existente de In-Memory DB (Redis) de TaskBoard, descrita en la Unidad 4.1.
import hashlib
import redis
r = redis.Redis(host="taskboard-redis", port=6379, ssl=True)
def cached_summary(description: str) -> str:
key = "sum:" + hashlib.sha256(
(SUMMARY_MODEL + "|" + description).encode()
).hexdigest()
hit = r.get(key)
if hit:
return hit.decode()
summary = safe_summary(description)
r.set(key, summary, ex=86400) # 24h TTL
return summary
Dado que la inferencia es sin estado y los prompts y las salidas se descartan al final de cada sesión, el único registro duradero de un resultado es aquel que usted elige conservar. Por lo tanto, la caché es a la vez una palanca de costos y su almacén de resultados calculados.
5.4 Residencia de datos y privacidad
AI Model Hub opera como un servicio sin estado: los prompts y las salidas se descartan al final de cada sesión, no se registran ni se graban, y no se reutilizan para el entrenamiento de modelos. Los datos del cliente no se utilizan para el entrenamiento bajo ninguna circunstancia. Todos los servicios de AI Model Hub, incluidos los puntos finales de inferencia de modelos y las bases de datos vectoriales administradas, se alojan en centros de datos certificados ISO 27001 en Alemania, y el procesamiento es totalmente conforme al RGPD. Para TaskBoard, esto significa que las descripciones de tareas enviadas para su resumen permanecen dentro del límite del centro de datos alemán y nunca entran en un conjunto de entrenamiento.
5.5 Acceso agéntico de solo lectura con el IONOS CLOUD MCP Server
Cuando la integración que necesita no es "llamar a un modelo" sino "permitir que un agente de IA inspeccione su infraestructura de IONOS CLOUD", el IONOS CLOUD MCP Server es la vía orientada al desarrollador. Es un binario local que implementa el Model Context Protocol (MCP), comunicándose mediante JSON-RPC a través de stdio con un cliente de IA o un agente autónomo. Otorga a dicho cliente acceso de solo lectura a más de 100 herramientas en seis productos: Compute Engine, Object Storage, Cloud DNS, Certificate Manager, Billing y Activity Log. Las herramientas están diseñadas para ser de solo inspección, por lo que el binario no puede crear, actualizar ni eliminar ningún recurso.
El MCP Server es una alternativa a configurar sus propias llamadas directas a la API o al SDK para escenarios de lectura agéntica y de automatización. En lugar de escribir código de cliente para cada API de producto, ejecuta el binario como un subproceso local; el cliente de IA descubre las herramientas y las llama en un bucle agéntico, y el binario llama directamente a la API de IONOS CLOUD a través de HTTPS utilizando su token de API. Para flujos de trabajo totalmente soberanos, se combina con AI Model Hub, de modo que tanto el paso de inferencia como el paso de inspección de infraestructura permanezcan dentro del perímetro de IONOS CLOUD. Considere las salidas de las herramientas como datos que salen de dicho perímetro una vez que el cliente de IA las lee.
Tarjeta rápida de referencia de la API
Puntos finales de la API clave para la integración con AI Model Hub:
| Método | Punto final | Descripción |
|---|---|---|
GET |
/v1/models |
Lista los modelos disponibles y sus detalles |
POST |
/v1/chat/completions |
Genera una finalización de chat (establezca stream para transmisión) |
POST |
/v1/embeddings |
Genera vectores de incrustación para el texto de entrada |
POST |
/v1/images/generations |
Genera imágenes a partir de un prompt de texto |
URL base (compatible con OpenAI): https://openai.inference.de-txl.ionos.com/v1
Documentación nativa de la API: https://api.ionos.com/docs/inference-modelhub/v1
Autenticación: Authorization: Bearer <IONOS_API_TOKEN> (JWT con la afirmación exp)
Laboratorio de código
Objetivo: Agregar la generación de resúmenes con IA a TaskBoard. Llame a AI Model Hub para resumir una descripción de tarea, maneje un código de estado 429 con reintentos con espera progresiva y almacene el resultado en Redis para que un resumen repetido no consuma tokens.
Requisitos previos:
- Una cuenta de IONOS CLOUD con un token de API (JWT) en
IONOS_API_TOKEN - Python 3.10 o superior con
pip install openai requests redis - Una instancia de Redis accesible (o un
redislocal para el laboratorio)
Paso 1: Exporte su token y confirme la conectividad
export IONOS_API_TOKEN="your-jwt-token"
curl -s https://openai.inference.de-txl.ionos.com/v1/models \
-H "Authorization: Bearer ${IONOS_API_TOKEN}" | python3 -m json.tool | head
Salida esperada:
{
"object": "list",
"data": [
{ "id": "meta-llama/Llama-3.3-70B-Instruct", ... }
Paso 2: Realizar una primera llamada de resumen
from openai import OpenAI
import os
client = OpenAI(base_url="https://openai.inference.de-txl.ionos.com/v1",
api_key=os.environ["IONOS_API_TOKEN"])
c = client.chat.completions.create(
model="mistralai/Mistral-Small-24B-Instruct",
messages=[{"role": "user", "content": "Summarize in one sentence: registry token expired so the deploy failed."}],
max_tokens=60, temperature=0.2)
print(c.choices[0].message.content)
print("tokens:", c.usage.total_tokens)
Salida esperada:
The deployment failed because the container registry token had expired.
tokens: 41
Paso 3: Agregar reintento ante el código 429 con retroceso exponencial
import time, requests, os
BASE="https://openai.inference.de-txl.ionos.com/v1"
def call(payload, attempts=5):
delay=1.0
for _ in range(attempts):
r=requests.post(f"{BASE}/chat/completions",
headers={"Authorization":f"Bearer {os.environ['IONOS_API_TOKEN']}"},
json=payload, timeout=30)
if r.status_code==429:
time.sleep(float(r.headers.get("Retry-After", delay))); delay*=2; continue
r.raise_for_status(); return r.json()
raise RuntimeError("rate-limited")
Salida esperada: no se produce ningún error en una llamada normal; un código 429 activa una espera y un reintento en lugar de un fallo.
Paso 4: Validar la respuesta antes de usarla
def summary(text):
data=call({"model":"mistralai/Mistral-Small-24B-Instruct",
"messages":[{"role":"user","content":text}],"max_tokens":60})
out=(data["choices"][0]["message"]["content"] or "").strip()
if not out: raise ValueError("empty summary")
return out
print(summary("The CI job failed on the embeddings step."))
Salida esperada:
The CI job failed during the embeddings step.
Paso 5: Almacenar los resultados en caché en Redis
import hashlib, redis
r=redis.Redis(host="localhost", port=6379)
MODEL="mistralai/Mistral-Small-24B-Instruct"
def cached(text):
k="sum:"+hashlib.sha256((MODEL+"|"+text).encode()).hexdigest()
hit=r.get(k)
if hit: return hit.decode()
s=summary(text); r.set(k, s, ex=86400); return s
Paso 6: Verificar que la caché elimina el costo de la segunda llamada
import time
t=time.time(); cached("Same description here."); print("miss", round(time.time()-t,2))
t=time.time(); cached("Same description here."); print("hit ", round(time.time()-t,2))
Salida esperada:
miss 0.9
hit 0.0
Paso 7: Generar un embedding para la búsqueda semántica
e=client.embeddings.create(model="BAAI/bge-m3", input="Fix the expired registry token")
print(len(e.data[0].embedding))
Salida esperada:
1024
Lista de verificación:
- [ ]
/v1/modelsdevuelve una lista de modelos con su token - [ ] Una finalización de chat devuelve contenido y un recuento de tokens de
usage - [ ] Un 429 activa la espera y el reintentado en lugar de una excepción
- [ ] Un resumen repetido se sirve desde Redis sin costo de tokens
- [ ]
BAAI/bge-m3devuelve un vector de 1024 dimensiones
Limpieza:
redis-cli --scan --pattern 'sum:*' | xargs -r redis-cli del
Errores comunes
Errores de desarrollo a evitar con la integración de AI Model Hub:
-
Tratar un 429 como un error fatal
- Problema: Un pico de actividad en TaskBoard devuelve
HTTP 429 Too Many Requestsy su controlador lanza una excepción, lo que provoca el fallo de las solicitudes de usuario. - Por qué ocurre: El límite general de la API es de 5 solicitudes por segundo (base) con un pico de 10; los trabajadores web concurrentes lo superan fácilmente.
- Solución: Capturar el 429, respetar
Retry-Aftery reintentar con retroceso exponencial. Delegar la inferencia en un trabajador drenado por Kafka para controlar la concurrencia.
- Problema: Un pico de actividad en TaskBoard devuelve
-
Confundir un JWT expirado con un error de código
- Problema: Las llamadas que funcionaban ayer devuelven un error de autenticación hoy, y usted comienza a depurar encabezados y cargas.
- Por qué ocurre: El token Bearer es un JWT con una afirmación
expy una fecha de expiración fija. Cuando esta se supera, todas las llamadas fallan la autenticación. - Solución: Decodificar la afirmación
expdel token y regenerar el token cuando esté expirado. Tratar los fallos de autenticación primero como una verificación del ciclo de vida del token, no como un error de formato de solicitud.
-
Llamar a la inferencia de forma síncrona y pagar por duplicados
- Problema: Picos de latencia en la creación de tareas y la factura de tokens aumenta porque las descripciones idénticas se resumen repetidamente.
- Por qué ocurre: La inferencia se ejecuta dentro de la ruta de la solicitud sin caché, por lo que la misma entrada consume tokens cada vez.
- Solución: Usar caché mediante un hash del modelo más la entrada en Redis con un TTL, y mover los resúmenes no urgentes a un trabajador asincrónico de Kafka para que la solicitud de creación se mantenga rápida.
Resumen
Ahora puede integrar AI Model Hub en el código de la aplicación. Llama al punto de acceso compatible con OpenAI en https://openai.inference.de-txl.ionos.com/v1 con un JWT Bearer, lo controla desde requests o el cliente oficial de OpenAI, transmite la respuesta cuando la interfaz de usuario lo requiere y genera incrustaciones con BAAI/bge-m3. Selecciona modelos según la ventana de contexto y el precio por token, y envuelve cada llamada con un tiempo de espera, reintentos con retroceso ante el código 429 y validación de la respuesta. Integró la funcionalidad en TaskBoard de forma síncrona y a través de un trabajador en cola de Kafka, y almacena los resultados en caché en Redis para que las entradas repetidas no supongan ningún coste.
Puntos clave:
- La API compatible con OpenAI en
/v1/chat/completions,/v1/embeddings,/v1/modelsy/v1/images/generationspermite que el cliente oficial de OpenAI funcione al reemplazarbase_urlyapi_key - La autenticación es un JWT Bearer en
IONOS_API_TOKEN; una afirmaciónexpcaducada es la causa más común de fallos de autenticación repentinos - El límite general de velocidad es de 5 peticiones por segundo como base y 10 en ráfaga; superarlo devuelve HTTP 429, que se gestiona con
Retry-Aftery retroceso exponencial - La elección del modelo es una decisión de coste: los tres modelos de chat comparten una ventana de contexto de 128000 tokens, por lo que el precio los diferencia, siendo
mistralai/Mistral-Small-24B-Instructel más barato - El servicio es sin estado y alojado en Alemania; los prompts y las salidas se descartan por sesión y nunca se utilizan para el entrenamiento, por lo que la caché en Redis es tanto su palanca de coste como su único almacén duradero de resultados
- El IONOS CLOUD MCP Server es un binario local que otorga a los agentes de IA acceso de solo lectura a más de 100 herramientas en Compute Engine, Object Storage, Cloud DNS, Certificate Manager, Facturación y Registro de actividad a través de MCP (JSON-RPC sobre stdio); es una alternativa a las llamadas directas a la API o al SDK para escenarios de lectura de agentes y se combina con AI Model Hub para flujos de trabajo soberanos
Terminología importante:
- API compatible con OpenAI: Un punto de acceso que replica la estructura de solicitud y respuesta de OpenAI, permitiendo que los SDK de OpenAI funcionen contra IONOS CLOUD cambiando la URL base y la clave
- Ventana de contexto: El número máximo de tokens (prompt más finalización) que un modelo acepta en una sola solicitud; 128000 para los modelos de chat de esta unidad
- Precios basados en tokens: Coste cobrado por millón de tokens de entrada y salida; se rastrea mediante el objeto
usageen cada respuesta - Retroceso exponencial: Una estrategia de reintento que duplica la espera entre intentos tras un 429, evitando una tormenta de reintentos masivos
- Inferencia sin estado: Cada solicitud es independiente; AI Model Hub descarta los prompts y las salidas al final de la sesión y no los registra, almacena ni utiliza para el entrenamiento
- IONOS CLOUD MCP Server: Un binario local que implementa el Protocolo de Contexto de Modelo (JSON-RPC sobre stdio) que expone herramientas de inspección de solo lectura en seis productos de IONOS CLOUD a un cliente de IA, llamando directamente a la API de IONOS CLOUD sin ningún proveedor de IA de terceros en la ruta de datos
Próximos pasos
Continuar aprendiendo: Unidad 4.5: Verificación de conocimientos - Integración de servicios
Temas relacionados: