4 puntos por GN⁺ 2025-03-17 | 1 comentarios | Compartir por WhatsApp
  • Biblioteca unificada de IA basada en Ruby, elegante y expresiva
  • Cada proveedor de IA tiene bibliotecas cliente, formatos de respuesta y formas de manejar streaming diferentes; para usar varios modelos de IA hay que lidiar con APIs incompatibles y dependencias complejas
  • RubyLLM ofrece una API unificada para resolver estos problemas

Funciones principales

  • Conversación: compatible con modelos de OpenAI, Anthropic, Gemini y DeepSeek
  • Visión y audio: comprensión de imágenes y audio
  • Análisis de PDF: resumen y análisis de documentos
  • Generación de imágenes: compatible con varios modelos como DALL-E
  • Generación de embeddings: búsqueda vectorial y análisis semántico
  • Provisión de herramientas: permite integrar código Ruby con la IA
  • Integración con Rails: permite guardar el historial de chat con ActiveRecord
  • Streaming: compatible con procesamiento de respuestas en tiempo real

Ventajas de RubyLLM

# Hacer una pregunta de forma simple  
chat = RubyLLM.chat  
chat.ask "¿Cuál es la mejor manera de aprender Ruby?"  
  
# Análisis de imágenes  
chat.ask "¿Qué se ve en esta imagen?", with: { image: "ruby_conf.jpg" }  
  
# Análisis de audio  
chat.ask "¿De qué se habló en esta reunión?", with: { audio: "meeting.wav" }  
  
# Resumen de documentos  
chat.ask "Por favor resume este contrato", with: { pdf: "contract.pdf" }  
  
# Generación de imágenes  
RubyLLM.paint "Pinta un atardecer sobre una montaña en estilo acuarela"  
  
# Generación de embeddings vectoriales  
RubyLLM.embed "Ruby es elegante y muy expresivo"  
  
# La IA puede usar código  
class Weather < RubyLLM::Tool  
  description "Proporciona el clima actual de una ubicación específica"  
  param :latitude, desc: "Latitud (ej.: 52.5200)"  
  param :longitude, desc: "Longitud (ej.: 13.4050)"  
  
  def execute(latitude:, longitude:)  
    url = "https://api.open-meteo.com/v1/forecast/…;  
  
    response = Faraday.get(url)  
    JSON.parse(response.body)  
  rescue => e  
    { error: e.message }  
  end  
end  
  
chat.with_tool(Weather).ask "¿Cómo está el clima en Berlín? (52.5200, 13.4050)"  

Cómo instalarlo

# Agregar al Gemfile  
gem 'ruby_llm'  
  
# Instalar  
bundle install  
  
# O instalar directamente  
gem install ruby_llm  

Configuración de la API key

RubyLLM.configure do |config|  
  config.openai_api_key = ENV['OPENAI_API_KEY']  
  config.anthropic_api_key = ENV['ANTHROPIC_API_KEY']  
  config.gemini_api_key = ENV['GEMINI_API_KEY']  
  config.deepseek_api_key = ENV['DEEPSEEK_API_KEY'] # opcional  
end  

Manejo de conversaciones naturales

# Iniciar un chat con el modelo predeterminado (GPT-4o-mini)  
chat = RubyLLM.chat  
  
# Usar otro modelo  
chat = RubyLLM.chat(model: 'claude-3-7-sonnet-20250219')  
  
# Pregunta simple  
chat.ask "¿Cuál es la diferencia entre attr_reader y attr_accessor?"  
  
# Manejo de conversación de varios turnos  
chat.ask "¿Podrías darme un ejemplo?"  
  
# Respuesta por streaming  
chat.ask "Cuéntame una historia sobre un programador de Ruby" do |chunk|  
  print chunk.content  
end  
  
# Soporte para otros tipos de entrada  
chat.ask "Compara estos dos diagramas", with: { image: ["diagram1.png", "diagram2.png"] }  
chat.ask "Resume este documento", with: { pdf: "contract.pdf" }  
chat.ask "Dime qué se dice en este audio", with: { audio: "meeting.wav" }  
  
# Se puede cambiar de modelo durante la conversación  
chat.with_model('gemini-2.0-flash').ask "¿Cuál es tu algoritmo favorito?"  

Compatibilidad con integración en Rails

# app/models/chat.rb  
class Chat < ApplicationRecord  
  acts_as_chat  
  
  broadcasts_to ->(chat) { "chat_#{chat.id}" }  
end  
  
# app/models/message.rb  
class Message < ApplicationRecord  
  acts_as_message  
end  
  
# app/models/tool_call.rb  
class ToolCall < ApplicationRecord  
  acts_as_tool_call  
end  
  
# Ejemplo de uso en un controlador  
chat = Chat.create!(model_id: "gpt-4o-mini")  
chat.ask("¿Cuál es el gem más útil en Ruby?") do |chunk|  
  Turbo::StreamsChannel.broadcast_append_to(  
    chat,  
    target: "response",  
    partial: "messages/chunk",  
    locals: { chunk: chunk }  
  )  
end  
  
# El historial del chat se guarda automáticamente  

Ejemplo de creación de herramientas

class Search < RubyLLM::Tool  
  description "Realiza búsquedas en la base de conocimiento"  
  
  param :query, desc: "Término de búsqueda"  
  param :limit, type: :integer, desc: "Cantidad máxima de resultados", required: false  
  
  def execute(query:, limit: 5)  
    Document.search(query).limit(limit).map(&:title)  
  end  
end  
  
# Uso de herramientas desde la IA  
chat.with_tool(Search).ask "Busca documentación sobre las nuevas funciones de Ruby 3.3"  

1 comentarios

 
GN⁺ 2025-03-17
Comentarios en Hacker News
  • Esta interfaz necesita mejorar su relación con el streaming. Siempre hay latencia en la respuesta, y mucha gente va a querer streaming en un hilo no bloqueante en lugar de pausar el proceso esperando la respuesta. Puede que sea un problema de documentación, pero de cualquier forma el streaming es de primera clase en todo lo que usa IO y tarda más de unos segundos
    • Fuera de eso, el DSL está bastante bien
  • Hay que tener cuidado al usar los ejemplos: enlace
  • Comparado con bibliotecas de DX incómodas como langchain, se siente como una bocanada de aire fresco
  • ¿Será esto lo que por fin me haga probar Rails? La sintaxis de Ruby de verdad está genial
  • Ruby sigue muy vivo
  • Es una de las APIs más concisas para interactuar con LLM
    • ¡Ojalá sigan adelante! Me alegra ver que ollama acepta PRs
  • Estoy escribiendo app scripts basados en LLM, y esto de verdad se siente muy fluido
  • Guau. Está realmente muy bien pensado
  • Ruby: llegó tarde a la fiesta, pero trajo el barril de cerveza
  • ¿Alguien me puede explicar por qué este paquete es tan bueno? Solo parece hacer llamadas a la API. No es por criticar, simplemente no entiendo bien este espacio y tengo curiosidad genuina
  • Guau, la sintaxis es hermosa