Volver al blog

API y SDKGuía

Primera petición en Ruby con la gema openai: base_url, clave, usage

Un script corto en Ruby: la gema oficial openai, un base_url personalizado y una clave desde env. Imprime el texto de la respuesta y el uso de tokens.

Por CheapTokens TeamPublicado el 5 min de lectura

Script de Ruby con OpenAI::Client.new y un base_url personalizado apuntando a CheapTokens
En esta página
  1. Lo que necesitas antes de empezar
  2. El script
  3. Leer lo que devuelve
  4. Cuánto cuesta una llamada así
  5. Si no se ejecuta
  6. A dónde ir después

Sí, la gema oficial openai funciona con CheapTokens: pasa base_url: "https://api.cheaptokens.dev/v1" y tu clave a OpenAI::Client.new, llama a client.chat.completions.create y lee el texto de choices.first.message.content. El resto de esta página es el script completo, cómo leer lo que devuelve y qué revisar cuando no se ejecuta.

Supón que tienes una tarea de rake que etiqueta tickets de soporte, o un job en segundo plano que resume una nota antes de guardarla. Quieres el SDK oficial, no HTTP hecho a mano, y quieres ver cuántos tokens usó cada llamada. Ese es exactamente este script.

Lo que necesitas antes de empezar#

La página de la gema en RubyGems (consultada el 8 de noviembre de 2026) lista openai 0.120.0, publicada el 5 de noviembre de 2026, Apache-2.0. Requiere Ruby 3.3.0 o superior; si estás atascado en Ruby 3.2, las notas de la propia gema apuntan a la línea 0.75.x. El paquete sigue en 0.x y avanza rápido, así que fija la versión.

En tu Gemfile:

ruby
gem "openai", "~> 0.120.0"

Luego bundle install. Sin Bundler, gem install openai -v 0.120.0 hace lo mismo.

También necesitas una clave de API de tu cuenta de CheapTokens. Mantenla fuera del código: ponla en una variable de entorno, y si la palabra .gitignore es nueva para ti, esta guía sobre cómo mantener las claves seguras es una lectura de cinco minutos.

bash
export CHEAPTOKENS_API_KEY="sk-your-key"

El script#

Crea ask.rb:

ruby
require "openai"

client = OpenAI::Client.new(
  api_key: ENV.fetch("CHEAPTOKENS_API_KEY"),
  base_url: "https://api.cheaptokens.dev/v1"
)

completion = client.chat.completions.create(
  model: "deepseek-ai/DeepSeek-V4-Flash-0731",
  messages: [
    { role: "user", content: "Explain in one sentence what a token is." }
  ]
)

choice = completion.choices.first
puts choice.message.content
puts "finish_reason: #{choice.finish_reason}"
puts completion.usage

Ejecútalo con ruby ask.rb. Hay tres cosas que merecen una segunda mirada.

ENV.fetch en lugar de ENV[...]. Si falta la variable, fetch se detiene de inmediato con un KeyError que la nombra. ENV[...] pasa nil en silencio y obtienes un error de autenticación confuso unas líneas después.

base_url: es la única línea que difiere de los ejemplos de OpenAI en el README de la gema. Todo lo demás es el mismo código, que es justo el objetivo de una API compatible con OpenAI. Si la idea es nueva, qué es base_url y cómo cambiarlo lo explica con una analogía de restaurante.

El id del modelo es el completo, deepseek-ai/DeepSeek-V4-Flash-0731. La API no acepta el nombre corto de una tabla de precios; toma los ids de la documentación de CheapTokens o de GET /v1/models.

Terminal con la línea del Gemfile, la clave exportada y ruby ask.rb
Los tres comandos: fijar la gema, exportar la clave, ejecutar el script.

Leer lo que devuelve#

La respuesta es un objeto, no un hash, así que llamas a métodos sobre él. El texto está en completion.choices.first.message.content; esa es la ruta que usa también el README de la gema.

Hay dos líneas más que vale la pena imprimir desde el primer día:

  • finish_reason te dice por qué se detuvo el modelo. stop es un final normal. length significa que un límite de longitud cortó la respuesta. Si alguna vez lo ves, por qué se cortan las respuestas y cómo solucionarlo.
  • usage contiene los tokens por los que se facturó la llamada: lo que enviaste y lo que escribió el modelo. El script imprime todo el objeto con puts completion.usage, así que ves ambos números tal como los devolvió la API.

¿Por qué registrarlos? Porque los tokens son la factura. Una pregunta de una frase con una respuesta de una frase es minúscula, pero un job que se ejecuta mil veces al día no lo es. Tokens de entrada vs salida explica por qué el segundo número suele costar más por token.

Cuánto cuesta una llamada así#

DeepSeek-V4-Flash en CheapTokens cuesta $0.015 por 1M de tokens de entrada y $0.10 por 1M de tokens de salida, con el mismo precio a cualquier hora del día. Toma un job de etiquetado de tickets: unos 300 tokens de entrada, 150 tokens de salida por ticket. Un ticket cuesta $0.00002. Mil tickets se ven así, con el precio de referencia de OpenRouter en la columna siguiente:

Modelo Por solicitud 1000 solicitudes OpenRouter, 1000 solicitudes
GLM-5.3-Flash $0.000012 $0.012 $0.0225
DeepSeek-V4-Flash $0.00002 $0.0195 $0.042
MiniMax-M2.7 $0.000038 $0.0375 $0.45

300 tokens de entrada y 150 tokens de salida por solicitud. Los precios por 1M de tokens son actuales y cambian junto con nuestras tarifas; la columna de OpenRouter muestra precios de referencia para la misma carga de trabajo.

El modelo admite hasta 380K tokens de contexto y hasta 32,768 tokens en una respuesta, así que un job de resumen rara vez choca con un límite. Si prefieres probar un segundo modelo con el mismo script, cambia solo la cadena model: por zai-org/GLM-5.3-Flash (390K de contexto, hasta 8,192 tokens de salida).

Si no se ejecuta#

La mayoría de los fallos en la primera ejecución son una de cinco cosas. Elige la que coincida con tu pantalla.

Elige tu caso

¿Qué ves?

KeyError: key not found: "CHEAPTOKENS_API_KEY"

La variable no está definida en esta terminal. Ejecuta de nuevo la línea export, o abre un shell nuevo y comprueba con echo $CHEAPTOKENS_API_KEY.

401 Unauthorized

La clave está pero es incorrecta: un espacio o una comilla de más, un pegado truncado o una clave antigua. Cópiala de nuevo desde tu cuenta.

404 Not Found

Revisa primero el base_url: termina en /v1 y no tiene ninguna ruta extra después. Luego revisa el id del modelo: es el id completo con el prefijo deepseek-ai/.

cannot load such file -- openai

La gema no está instalada para este Ruby. Ejecuta bundle install y arranca el script con bundle exec ruby ask.rb.

Bundler can't find a version that works

Revisa ruby -v. La línea 0.120.x necesita Ruby 3.3.0 o superior; en 3.2 fija la línea 0.75.x en su lugar.

Los casos 401 y 404 aparecen con todos los SDK, no solo con Ruby; API 401 o 404: clave, base URL o id de modelo incorrectos los recorre en orden.

Verificación rápida

¿Qué te dice finish_reason "length"?

Mostrar respuesta

Respuesta: La respuesta se cortó por un límite de longitud

stop es un final normal; length significa que la respuesta alcanzó un límite antes de que el modelo terminara.

A dónde ir después#

Ya tienes el bucle útil más pequeño: enviar, leer el texto, registrar los tokens. A partir de aquí, envuelve la llamada en un método y añade los números de usage a tu logger. El mismo patrón existe en otros lenguajes si tu stack es mixto: Go, Java y C#. La lista completa de modelos y precios está en la página de modelos, y la referencia de la API está en la documentación.