![]() |
![]() |
|
![]() |
Los modelos grandes de lenguaje (LLM), como Gemma, se destacan en la generación de respuestas informativas, lo que los hace ideales para crear asistentes virtuales y chatbots.
De manera convencional, los LLM operan sin estado, lo que significa que carecen de una memoria inherente para almacenar conversaciones pasadas. Cada instrucción o pregunta se procesa de forma independiente, sin tener en cuenta las interacciones anteriores. Sin embargo, un aspecto crucial de la conversación natural es la capacidad de conservar el contexto de las interacciones previas. Para superar esta limitación y permitir que los LLM mantengan el contexto de la conversación, se les debe proporcionar de forma explícita información relevante, como el historial de la conversación (o las partes pertinentes) en cada instrucción nueva que se le presenta al LLM.
En este instructivo, se muestra cómo desarrollar un chatbot usando la variante del modelo ajustado a instrucciones de Gemma.
Configuración
Configuración de Gemma
Para completar este instructivo, primero deberás completar las instrucciones de configuración de Gemma. Las instrucciones de configuración de Gemma te muestran cómo hacer lo siguiente:
- Accede a Gemma en kaggle.com.
- Selecciona un entorno de ejecución de Colab con recursos suficientes para ejecutarlo el modelo Gemma 2B.
- Generar y configurar un nombre de usuario Kaggle y una clave de API.
Después de completar la configuración de Gemma, continúa con la siguiente sección, en la que establecerás variables de entorno para tu entorno de Colab.
Configure las variables de entorno
Configura variables de entorno para KAGGLE_USERNAME
y KAGGLE_KEY
.
import os
from google.colab import userdata
# Note: `userdata.get` is a Colab API. If you're not using Colab, set the env
# vars as appropriate for your system.
os.environ["KAGGLE_USERNAME"] = userdata.get('KAGGLE_USERNAME')
os.environ["KAGGLE_KEY"] = userdata.get('KAGGLE_KEY')
Instala dependencias
Instala Keras y KerasNLP.
# Install Keras 3 last. See https://keras.io/getting_started/ for more details.
pip install -q tensorflow-cpu
pip install -q -U keras-nlp tensorflow-hub
pip install -q -U "keras>=3"
pip install -q -U tensorflow-text
Seleccionar un backend
Keras es una API de aprendizaje profundo de varios marcos de alto nivel diseñada para ofrecer simplicidad y facilidad de uso. Keras 3 te permite elegir el backend: TensorFlow, JAX o PyTorch. Las tres opciones funcionarán en este instructivo.
import os
# Select JAX as the backend
os.environ["KERAS_BACKEND"] = "jax"
# Pre-allocate 100% of TPU memory to minimize memory fragmentation
os.environ["XLA_PYTHON_CLIENT_MEM_FRACTION"] = "1.0"
Importa paquetes
Importar Keras y KerasNLP.
import keras
import keras_nlp
# for reproducibility
keras.utils.set_random_seed(42)
Crea una instancia del modelo
KerasNLP proporciona implementaciones de muchas arquitecturas de modelos populares. En este instructivo, crearás una instancia del modelo con GemmaCausalLM
, un modelo de Gemma de extremo a extremo para el modelado de lenguaje causal. Un modelo de lenguaje causal predice el siguiente token basándose en los anteriores.
Crea una instancia del modelo con el método from_preset
:
gemma_lm = keras_nlp.models.GemmaCausalLM.from_preset("gemma2_instruct_2b_en")
La función GemmaCausalLM.from_preset()
crea una instancia del modelo a partir de una arquitectura y pesos preestablecidos. En el código anterior, la cadena "gemma2_instruct_2b_en"
especifica el ajuste predeterminado del modelo Gemma 2 2B con 2,000 millones de parámetros. También están disponibles los modelos Gemma con parámetros 7B, 9B y 27B. Puedes encontrar las cadenas de código para los modelos de Gemma en sus fichas de Variación del modelo en Kaggle.
Usa el método summary
para obtener más información sobre el modelo:
gemma_lm.summary()
Como puedes ver en el resumen, el modelo tiene 2,600 millones de parámetros entrenables.
Cómo definir funciones auxiliares de formato
from IPython.display import Markdown
import textwrap
def display_chat(prompt, text):
formatted_prompt = "<font size='+1' color='brown'>🙋♂️<blockquote>" + prompt + "</blockquote></font>"
text = text.replace('•', ' *')
text = textwrap.indent(text, '> ', predicate=lambda _: True)
formatted_text = "<font size='+1' color='teal'>🤖\n\n" + text + "\n</font>"
return Markdown(formatted_prompt+formatted_text)
def to_markdown(text):
text = text.replace('•', ' *')
return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))
Compila el chatbot
El modelo gemma2_instruct_2b_en
ajustado a las instrucciones de Gemma está ajustado para comprender los siguientes tokens de turno:
<start_of_turn>user\n ... <end_of_turn>\n
<start_of_turn>model\n ... <end_of_turn>\n
En este instructivo, se usan estos tokens para compilar el chatbot. Consulta Instrucciones de sistema y formato para obtener más información sobre los tokens de control de Gemma.
Crea un asistente de chat para administrar el estado de la conversación
class ChatState():
"""
Manages the conversation history for a turn-based chatbot
Follows the turn-based conversation guidelines for the Gemma family of models
documented at https://ai.google.dev/gemma/docs/formatting
"""
__START_TURN_USER__ = "<start_of_turn>user\n"
__START_TURN_MODEL__ = "<start_of_turn>model\n"
__END_TURN__ = "<end_of_turn>\n"
def __init__(self, model, system=""):
"""
Initializes the chat state.
Args:
model: The language model to use for generating responses.
system: (Optional) System instructions or bot description.
"""
self.model = model
self.system = system
self.history = []
def add_to_history_as_user(self, message):
"""
Adds a user message to the history with start/end turn markers.
"""
self.history.append(self.__START_TURN_USER__ + message + self.__END_TURN__)
def add_to_history_as_model(self, message):
"""
Adds a model response to the history with start/end turn markers.
"""
self.history.append(self.__START_TURN_MODEL__ + message)
def get_history(self):
"""
Returns the entire chat history as a single string.
"""
return "".join([*self.history])
def get_full_prompt(self):
"""
Builds the prompt for the language model, including history and system description.
"""
prompt = self.get_history() + self.__START_TURN_MODEL__
if len(self.system)>0:
prompt = self.system + "\n" + prompt
return prompt
def send_message(self, message):
"""
Handles sending a user message and getting a model response.
Args:
message: The user's message.
Returns:
The model's response.
"""
self.add_to_history_as_user(message)
prompt = self.get_full_prompt()
response = self.model.generate(prompt, max_length=2048)
result = response.replace(prompt, "") # Extract only the new response
self.add_to_history_as_model(result)
return result
Chatea con el modelo
Empieza a chatear con el modelo.
chat = ChatState(gemma_lm)
message = "Tell me, in a few words, how to compute all prime numbers up to 1000?"
display_chat(message, chat.send_message(message))
🙋♂️
Dime, en pocas palabras, ¿cómo calcular todos los números primos hasta el 1,000?⋮.
Luz de Eratóstenes.
Continúa la conversación.
message = "Now in Python! No numpy, please!"
display_chat(message, chat.send_message(message))
🙋♂️
¡Ahora en Python! No, por favor.⋮.
def sieve_of_eratosthenes(n): """Returns a list of prime numbers up to n.""" primes = [True] * (n + 1) primes[0] = primes[1] = False for i in range(2, int(n**0.5) + 1): if primes[i]: for j in range(i * i, n + 1, i): primes[j] = False return [i for i, is_prime in enumerate(primes) if is_prime] primes = sieve_of_eratosthenes(1000) print(primes)
Explicación:
Inicialización:
primes = [True] * (n + 1)
: Crea una listaprimes
de valores booleanos, suponiendo inicialmente que todos los números son primos.primes[0] = primes[1] = False
: Establece 0 y 1 como no primos.Iteración:
for i in range(2, int(n**0.5) + 1):
: Itera de 2 a la raíz cuadrada den
. Solo debemos comprobar hasta la raíz cuadrada porque cualquier número compuesto debe tener un factor primo menor o igual que su raíz cuadrada.if primes[i]:
: Sii
se marca como primo:
for j in range(i * i, n + 1, i):
: Marca todos los múltiplos dei
como no primos.Resultado:
return [i for i, is_prime in enumerate(primes) if is_prime]
: Crea una lista de índices en los queprimes[i]
es verdadero, que representa los números primos.Avísanos si quieres obtener una explicación más detallada de algún aspecto.
message = "Thank you, it works! Can you explain the code in French?"
display_chat(message, chat.send_message(message))
🙋♂️
Gracias, funciona. ¿Puedes explicar el código en francés?⋮.
¡Bien sOrg! Voici une explication du code en français :
def sieve_of_eratosthenes(n): """Retourne une liste de nombres premiers jusqu'à n.""" primes = [True] * (n + 1) primes[0] = primes[1] = False for i in range(2, int(n**0.5) + 1): if primes[i]: for j in range(i * i, n + 1, i): primes[j] = False return [i for i, is_prime in enumerate(primes) if is_prime] primes = sieve_of_eratosthenes(1000) print(primes)
Explicación:
Inicialización:
primes = [True] * (n + 1)
: Crée une listeprimes
de valeurs booléennes, initialement supposant que tous les name aret premiers.primes[0] = primes[1] = False
: Définit 0 y 1 comme no estrenos.Iteración:
for i in range(2, int(n**0.5) + 1):
: Itère de 2 jusqu'à la racine carrée den
. Nous ne devons vérifier que jusqu'à la racine carrée auto tout name composite rita avoir un facteur premier inférieur ou égal à sa racine carrée.if primes[i]:
: Sii
est considéré comme premier:
for j in range(i * i, n + 1, i):
: Marquer tous les multiples dei
compro no estrenos.Resultado:
return [i for i, is_prime in enumerate(primes) if is_prime]
: Crée une liste des indices oùprimes[i]
est vrai, representando a los nombres premiers.N'hésitez pas à me demander si vous avez besoin d'une explication plus détaillée de quelque eligió.
message = "Great! Now add those explanations as comments in the code."
display_chat(message, chat.send_message(message))
🙋♂️
Perfecto. Ahora, agrega las explicaciones como comentarios en el código.↘
def sieve_of_eratosthenes(n): """Retourne une liste de nombres premiers jusqu'à n.""" # Initialise une liste de boolean avec True pour tous les nombres de 0 à n primes = [True] * (n + 1) # Définit 0 et 1 comme non-premiers primes[0] = primes[1] = False # Itère de 2 à la racine carrée de n for i in range(2, int(n**0.5) + 1): # Si i est considéré comme premier if primes[i]: # Itère sur tous les multiples de i for j in range(i * i, n + 1, i): # Définit les multiples de i comme non-premiers primes[j] = False # Retourne la liste des indices des nombres premiers return [i for i, is_prime in enumerate(primes) if is_prime] primes = sieve_of_eratosthenes(1000) print(primes)
Explicación:
- Inicialización:
primes = [True] * (n + 1)
: Crée une listeprimes
de valeurs booléennes, initialement supposant que tous les name aret premiers.primes[0] = primes[1] = False
: Définit 0 y 1 comme no estrenos.- Iteración:
for i in range(2, int(n**0.5) + 1):
: Itère de 2 jusqu'à la racine carrée den
. Nous ne devons vérifier que jusqu'à la racine carrée auto tout name composite rita avoir un facteur premier inférieur ou égal à sa racine carrée.if primes[i]:
: Sii
est considéré comme premier:
for j in range(i * i, n + 1, i):
: Marquer tous les multiples dei
compro no estrenos.- Resultado:
return [i for i, is_prime in enumerate(primes) if is_prime]
: Crée une liste des indices oùprimes[i]
est vrai, representando a los nombres premiers.
Ejecuta el código generado para probar la respuesta generada:
def sieve_of_eratosthenes(n):
"""Retourne une liste de nombres premiers jusqu'à n."""
# Initialise une liste de boolean avec True pour tous les nombres de 0 à n
primes = [True] * (n + 1)
# Définit 0 et 1 comme non-premiers
primes[0] = primes[1] = False
# Itère de 2 à la racine carrée de n
for i in range(2, int(n**0.5) + 1):
# Si i est considéré comme premier
if primes[i]:
# Itère sur tous les multiples de i
for j in range(i * i, n + 1, i):
# Définit les multiples de i comme non-premiers
primes[j] = False
# Retourne la liste des indices des nombres premiers
return [i for i, is_prime in enumerate(primes) if is_prime]
primes = sieve_of_eratosthenes(1000)
print(primes)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
Usa el método get_history
para ver cómo la clase Chat
retuvo todo el contexto.
print(chat.get_history())
<start_of_turn>user Tell me, in a few words, how to compute all prime numbers up to 1000?<end_of_turn> <start_of_turn>model **Sieve of Eratosthenes.** <end_of_turn><start_of_turn>user Now in Python! No numpy, please!<end_of_turn> <start_of_turn>model ```python def sieve_of_eratosthenes(n): """Returns a list of prime numbers up to n.""" primes = [True] * (n + 1) primes[0] = primes[1] = False for i in range(2, int(n**0.5) + 1): if primes[i]: for j in range(i * i, n + 1, i): primes[j] = False return [i for i, is_prime in enumerate(primes) if is_prime] primes = sieve_of_eratosthenes(1000) print(primes) ``` **Explanation:** 1. **Initialization:** - `primes = [True] * (n + 1)`: Creates a list `primes` of boolean values, initially assuming all numbers are prime. - `primes[0] = primes[1] = False`: Sets 0 and 1 as non-prime. 2. **Iteration:** - `for i in range(2, int(n**0.5) + 1):`: Iterates from 2 to the square root of `n`. We only need to check up to the square root because any composite number must have a prime factor less than or equal to its square root. - `if primes[i]:`: If `i` is marked as prime: - `for j in range(i * i, n + 1, i):`: Marks all multiples of `i` as non-prime. 3. **Result:** - `return [i for i, is_prime in enumerate(primes) if is_prime]`: Creates a list of indices where `primes[i]` is True, representing the prime numbers. Let me know if you'd like a more detailed explanation of any part! <end_of_turn><start_of_turn>user Thank you, it works! Can you explain the code in French?<end_of_turn> <start_of_turn>model Bien sûr ! Voici une explication du code en français : ```python def sieve_of_eratosthenes(n): """Retourne une liste de nombres premiers jusqu'à n.""" primes = [True] * (n + 1) primes[0] = primes[1] = False for i in range(2, int(n**0.5) + 1): if primes[i]: for j in range(i * i, n + 1, i): primes[j] = False return [i for i, is_prime in enumerate(primes) if is_prime] primes = sieve_of_eratosthenes(1000) print(primes) ``` **Explication:** 1. **Initialisation:** - `primes = [True] * (n + 1)`: Crée une liste `primes` de valeurs booléennes, initialement supposant que tous les nombres sont premiers. - `primes[0] = primes[1] = False`: Définit 0 et 1 comme non-premiers. 2. **Itération:** - `for i in range(2, int(n**0.5) + 1):`: Itère de 2 jusqu'à la racine carrée de `n`. Nous ne devons vérifier que jusqu'à la racine carrée car tout nombre composite doit avoir un facteur premier inférieur ou égal à sa racine carrée. - `if primes[i]:`: Si `i` est considéré comme premier: - `for j in range(i * i, n + 1, i):`: Marquer tous les multiples de `i` comme non-premiers. 3. **Resultat:** - `return [i for i, is_prime in enumerate(primes) if is_prime]`: Crée une liste des indices où `primes[i]` est vrai, représentant les nombres premiers. N'hésitez pas à me demander si vous avez besoin d'une explication plus détaillée de quelque chose! <end_of_turn><start_of_turn>user Great! Now add those explanations as comments in the code.<end_of_turn> <start_of_turn>model ```python def sieve_of_eratosthenes(n): """Retourne une liste de nombres premiers jusqu'à n.""" # Initialise une liste de boolean avec True pour tous les nombres de 0 à n primes = [True] * (n + 1) # Définit 0 et 1 comme non-premiers primes[0] = primes[1] = False # Itère de 2 à la racine carrée de n for i in range(2, int(n**0.5) + 1): # Si i est considéré comme premier if primes[i]: # Itère sur tous les multiples de i for j in range(i * i, n + 1, i): # Définit les multiples de i comme non-premiers primes[j] = False # Retourne la liste des indices des nombres premiers return [i for i, is_prime in enumerate(primes) if is_prime] primes = sieve_of_eratosthenes(1000) print(primes) ``` **Explication:** * **Initialisation:** * `primes = [True] * (n + 1)`: Crée une liste `primes` de valeurs booléennes, initialement supposant que tous les nombres sont premiers. * `primes[0] = primes[1] = False`: Définit 0 et 1 comme non-premiers. * **Itération:** * `for i in range(2, int(n**0.5) + 1):`: Itère de 2 jusqu'à la racine carrée de `n`. Nous ne devons vérifier que jusqu'à la racine carrée car tout nombre composite doit avoir un facteur premier inférieur ou égal à sa racine carrée. * `if primes[i]:`: Si `i` est considéré comme premier: * `for j in range(i * i, n + 1, i):`: Marquer tous les multiples de `i` comme non-premiers. * **Resultat:** * `return [i for i, is_prime in enumerate(primes) if is_prime]`: Crée une liste des indices où `primes[i]` est vrai, représentant les nombres premiers. <end_of_turn>
Resumen y lecturas adicionales
En este instructivo, aprendiste a chatear con el modelo ajustado para instrucciones de Gemma 2B usando Keras en JAX.
Consulta estos tutoriales y guías para obtener más información sobre Gemma:
- Comienza a usar Keras Gemma.
- Ajusta el modelo de Gemma en la GPU.
- Obtén más información sobre la integración de Gemma en Vertex AI.
- Aprende a usar modelos de Gemma con Vertex AI.