Si pensamos en las tecnologías que definieron una década, podemos mencionar varias. En la primera mitad de los años 2010, probablemente la palabra que más se escuchaba era "smartphone"; en la segunda mitad de la década, probablemente fueron los wearables o la realidad virtual. Ahora, claramente es la inteligencia artificial, basta con ver el boom exponencial que ha tenido los últimos años en Google Trends
Probablemente, esta noticia no sea nueva para muchos. Plataformas como ChatGPT o BingChat han sido ampliamente utilizadas y dependemos cada vez más de ellas. Su valor en distintas áreas de la sociedad es cada vez más evidente, ya sea para facilitar la escritura de informes, mejorar la calidad de las búsquedas para desarrolladores o incluso resumir textos para simplificar la comprensión.
En relación con esto, para los desarrolladores en particular, el procesamiento de lenguaje natural representa un desafío complejo. Imagina, por ejemplo, un chatbot que debe comprender la intención del usuario en su mensaje, como "hacer una reserva" u "obtener información sobre un producto". Incluso debe ser capaz de detectar dialectos locales, como en el caso de la expresión "No me tinca ir mañana en la mañana". Normalmente, este tipo de problemas implica que las aplicaciones tengan limitaciones en el uso del lenguaje natural o requieran algoritmos complejos que demandan muchas horas de desarrollo y grandes volúmenes de datos.
Sin embargo, gracias a la innovación de OpenAI, ahora es posible utilizar sus modelos ya entrenados e integrarlos en nuestras aplicaciones en menos de 10 minutos. En esta mini guía, exploraremos una implementación sencilla en Ruby que nos permitirá aprovechar estas ventajas.
1. Implementando GPT-3.5 en Ruby
Para tener algo entretenido para resolver, trataremos de implementar un símil a ChatGPT utilizando GPT-3.5 (mismo modelo) e interacción mediante consola.
Lo primero que necesitaremos es una API KEY para acceder a OpenAI, para obtener una debemos ir a https://openai.com/api/ y crear una cuenta
Posteriormente, debemos ir al perfil y generar una nueva API Key. Almacena este token en un lugar seguro, ya que no se puede volver a ver.
Ahora se debe crear una carpeta y un archivo Ruby. Además, crearemos un archivo .env (Variable de entorno) para almacenar la API Key recién generada Para esto ejecutaremos el siguiente código en una terminal
mkdir platanus-openai
cd platanus-openai
touch main.rb
touch .env
En el archivo .env escribiremos el token que nos entregó OpenAI
# .env
OPENAI_API_KEY=your-api-key
Para facilitar la implementación en Ruby es recomendable utilizar la gema https://github.com/alexrudall/ruby-openai, porque simplifica el llamado a la API y el manejo de excepciones. Además, instalaremos dotenv para simplificar el manejo de las variables de entorno.
gem install ruby-openai
gem install dotenv
Y añadimos el require
a nuestro archivo .rb
# main.rb
require 'openai'
require 'dotenv/load'
Posteriormente, debemos inicializar nuestro cliente con el token
client = OpenAI::Client.new(access_token: ENV['OPENAI_API_KEY'])
Utilizaremos el modelogpt-3.5-turbo
correspondiente a ChatGPT. Además del modelo, la API recibe como input un historial de mensajes en el siguiente formato
[{ role: ‘ROL’, content: 'message' }, {...}, ...]
Donde los roles pueden ser system
, user
y assistant
. Que corresponden a los distintos “agentes” en la conversación y hacen referencia a instrucciones de sistema, mensajes de usuario y respuestas del asistente respectivamente. Es importante mencionar que el mensaje de sistema posee mayor control sobre como será posteriormente la conversación.
Generamos nuestros mensajes ingresando uno de sistema y luego el del usuario
# main.rb
BASE_PROMPT = 'Soy Ham, un bot inteligente que responde a preguntas generales.'.freeze
TEMPERATURE = 0.1
MAX_TOKENS = 150
def ask_question(question)
return '' if question.empty?
client = OpenAI::Client.new(access_token: ENV['OPENAI_API_KEY'])
result = client.chat(
parameters: {
model: 'gpt-3.5-turbo',
messages: [
{role: 'system', content: BASE_PROMPT},
{role: 'user', content: question}
],
temperature: TEMPERATURE,
max_tokens: MAX_TOKENS
}
)
result.dig("choices", 0, "message", "content")
end
El código anterior define un mensaje inicial, y dos parámetros max_tokens que indica la cantidad máxima de tokens de la respuesta (1 Token es aproximadamente 0.75 Palabra) y temperature que indica el rango de exploración de la IA, en pocas palabras esto indica que tanta prioridad el modelo le da a ‘Inventar’ por sobre simplemente responder con la información que ya posee. Por ejemplo, en este caso el 0.1 indica que la IA intentará inventar lo menos posible.
Finalmente, definimos una función para hacer el llamado a la API y construir el mensaje que le enviaremos. Algo importante que definimos es el model, esto hace referencia a qué modelo de OpenAI queremos utilizar, por ejemplo, el modelo gpt-3.5-turbo
hace referencia a GPT-3.5 el cual es equivalente a ChatGPT. Mientras que existen otros modelos como Whisper, cuya utilización es para procesado de audio.
Finalmente, agregamos un While para que mantenga ciclo de preguntas y respuestas, y probamos nuestro código
# main.rb
require 'openai'
require 'dotenv/load'
BASE_PROMPT = 'Soy Ham, un bot inteligente que responde a preguntas generales.'.freeze
TEMPERATURE = 0.1
def ask_question(question)
return '' if question.empty?
client = OpenAI::Client.new(access_token: ENV['OPENAI_API_KEY'])
result = client.chat(
parameters: {
model: 'gpt-3.5-turbo',
messages: [
{ role: 'system', content: BASE_PROMPT },
{ role: 'user', content: question }
],
temperature: TEMPERATURE,
}
)
result.dig("choices", 0, "message", "content")
end
p 'Realiza una pregunta a Ham'
while true
print 'Pregunta: '
question = gets.chomp
answer = ask_question(question)
puts "Ham: #{answer}"
end
Lo ejecutamos con ruby main.rb
Y listo! Nuestro bot ya responde preguntas
Lo logramos! Ham (el bot) ya puede responder preguntas utilizando ChatGPT mediante API. Sin embargo, una de las funcionalidades más útiles de ChatGPT es su ‘Memoria’, donde puede recordar mensajes anteriores y continuar la conversación desde ahí
2. Agregando Memoria y Persistencia a nuestro bot
# main.rb
require 'openai'
require 'dotenv/load'
BASE_PROMPT = 'Soy Ham, un bot inteligente que responde a preguntas generales.'.freeze
history = [ { role: 'system', content: BASE_PROMPT } ]
def ask_question(question, history)
return '' if question.empty?
history.append({role: 'user', content: question})
client = OpenAI::Client.new(access_token: ENV['OPENAI_API_KEY'])
result = client.chat(
parameters: {
model: 'gpt-3.5-turbo',
messages: history,
temperature: 0.1,
}
)
answer = result.dig("choices", 0, "message", "content")
history.append({role: 'assistant', content: answer})
answer
end
p 'Realiza una pregunta a Ham'
while true
print 'Pregunta: '
question = gets.chomp
answer = ask_question(question, history)
puts "Ham: #{answer}"
end
Nuevamente, Lo ejecutamos con ruby main.rb
Y listo! Nuestro bot es capaz de recordar mensajes anteriores
Con esto nuestro bot ya posee memoria y es capaz de responder preguntas recordando el contexto y mensajes anteriores. Y con eso estamos, tenemos lista una base para hacer que nuestras APPs sean inteligentes!
Así como GPT3.5 o GPT4, existen muchos más modelos disponibles, como Whisper para reconocimiento de voz, dall-e para generar imágenes o modelos para generar embeddings para búsqueda de documentos. Además de este asociado a OpenAI, existen muchos otros modelos OpenSource disponibles en HuggingFace.