Ver em ai.google.dev | Executar no Google Colab | Abrir na Vertex AI | Veja o código-fonte no GitHub |
Os modelos de linguagem grandes (LLMs), como o Gemma, são ótimos para gerar respostas informativas, o que os torna ideais para criar assistentes virtuais e chatbots.
Convencionalmente, os LLMs operam sem estado, o que significa que não têm uma memória inerente para armazenar conversas anteriores. Cada comando ou pergunta é processado de forma independente, desconsiderando as interações anteriores. No entanto, um aspecto crucial da conversa natural é a capacidade de reter o contexto de interações anteriores. Para superar essa limitação e permitir que os LLMs mantenham o contexto da conversa, eles precisam receber explicitamente informações relevantes, como o histórico da conversa (ou partes pertinentes), em cada novo comando apresentado ao LLM.
Neste tutorial, mostramos como desenvolver um chatbot usando a variante de modelo ajustado por instruções do Gemma.
Configuração
Configuração do Gemma
Para concluir este tutorial, primeiro você precisa concluir as instruções de configuração na configuração do Gemma. As instruções de configuração do Gemma mostram como fazer o seguinte:
- Acesse o Gemma em kaggle.com.
- Selecione um ambiente de execução do Colab com recursos suficientes para ser executado o modelo Gemma 2B.
- Gere e configure um nome de usuário e uma chave de API do Kaggle.
Depois de concluir a configuração do Gemma, vá para a próxima seção, em que você definirá variáveis de ambiente para o ambiente do Colab.
Defina as variáveis de ambiente
Defina as variáveis de ambiente para KAGGLE_USERNAME
e 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')
Instalar dependências
Instalar o Keras e o 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
Selecione um back-end
Keras é uma API de aprendizado profundo de alto nível e com vários frameworks projetadas para simplicidade e facilidade de uso. A Keras 3 permite que você escolha o back-end: TensorFlow, JAX ou PyTorch. Os três funcionam para este tutorial.
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"
Importar pacotes
Importe o Keras e o KerasNLP.
import keras
import keras_nlp
# for reproducibility
keras.utils.set_random_seed(42)
Instanciar o modelo
O KerasNLP oferece implementações de várias arquiteturas de modelo conhecidas. Neste tutorial, você instanciará o modelo usando GemmaCausalLM
, um modelo Gemma completo para modelagem de linguagem causal. Um modelo de linguagem causal prevê o próximo token com base em tokens anteriores.
Instancie o modelo usando o método from_preset
:
gemma_lm = keras_nlp.models.GemmaCausalLM.from_preset("gemma2_instruct_2b_en")
A função GemmaCausalLM.from_preset()
instancia o modelo usando uma arquitetura e pesos predefinidos. No código acima, a string "gemma2_instruct_2b_en"
especifica a predefinição do modelo Gemma 2 2B com 2 bilhões de parâmetros. Os modelos Gemma com parâmetros 7B, 9B e 27B também estão disponíveis. Encontre as strings de código dos modelos Gemma nas listagens de Variações de modelos do Kaggle.
Use o método summary
para receber mais informações sobre o modelo:
gemma_lm.summary()
Como mostrado no resumo, o modelo tem 2,6 bilhões de parâmetros treináveis.
Definir funções auxiliares de formatação
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))
Como criar o bot de bate-papo
O modelo gemma2_instruct_2b_en
ajustado por instruções do Gemma foi ajustado para entender os seguintes tokens de turno:
<start_of_turn>user\n ... <end_of_turn>\n
<start_of_turn>model\n ... <end_of_turn>\n
Este tutorial usa esses tokens para criar o bot de bate-papo. Consulte Instruções de formatação e sistema para mais informações sobre os tokens de controle do Gemma.
Criar um assistente de chat para gerenciar o estado da conversa
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
Conversar com o modelo
Converse com o 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))
🙋♂️
Diga-me como calcular todos os números primos até 1.000 em poucas palavras.🤖
Criou de Eratótones.
Continue a conversa.
message = "Now in Python! No numpy, please!"
display_chat(message, chat.send_message(message))
🙋♂️
Agora em Python! Sem enrolação, 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)
Explicação:
Inicialização:
primes = [True] * (n + 1)
: cria uma listaprimes
de valores booleanos, inicialmente supondo que todos os números sejam primos.primes[0] = primes[1] = False
: define 0 e 1 como não primos.Iteração:
for i in range(2, int(n**0.5) + 1):
: itera de 2 até a raiz quadrada den
. Só precisamos verificar a raiz quadrada, porque qualquer número composto deve ter um fator primo menor ou igual à raiz quadrada.if primes[i]:
: sei
estiver marcado como primo:
for j in range(i * i, n + 1, i):
: marca todos os múltiplos dei
como não primos.Resultado:
return [i for i, is_prime in enumerate(primes) if is_prime]
: cria uma lista de índices em queprimes[i]
é "True", representando os números primos.Entre em contato se quiser uma explicação mais detalhada sobre qualquer parte.
message = "Thank you, it works! Can you explain the code in French?"
display_chat(message, chat.send_message(message))
🙋♂️
Obrigado, funciona! Você pode explicar o código em francês?🤖
Bien sûr ! 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)
Explicação:
Inicialização:
primes = [True] * (n + 1)
: Crée une listeprimes
de valeurs booléennes, initialement supposant que tous les nombres sont premiers.primes[0] = primes[1] = False
: Définit 0 et 1 comme não estreias.Itéração:
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 car tout nombre composite Remove 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
não é Estreia.Resultado:
return [i for i, is_prime in enumerate(primes) if is_prime]
: Crée une liste des indices okedprimes[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 escolheu!
message = "Great! Now add those explanations as comments in the code."
display_chat(message, chat.send_message(message))
🙋♂️
Ótimo! Agora, adicione essas explicações como comentários no 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)
Explicação:
- Inicialização:
primes = [True] * (n + 1)
: Crée une listeprimes
de valeurs booléennes, initialement supposant que tous les nombres sont premiers.primes[0] = primes[1] = False
: Définit 0 et 1 comme não estreias.- Itéração:
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 car tout nombre composite Remove 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
não é Estreia.- Resultado:
return [i for i, is_prime in enumerate(primes) if is_prime]
: Crée une liste des indices okedprimes[i]
est vrai, représentant les nombres premiers.
Execute o código gerado para testar a resposta gerada:
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]
Use o método get_history
para ver como todo o contexto foi retido pela classe Chat
.
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>
Resumo e outros materiais de leitura
Neste tutorial, você aprendeu a conversar com o modelo ajustado por instruções Gemma 2B usando o Keras no JAX.
Confira estes guias e tutoriais para saber mais sobre o Gemma:
- Primeiros passos com o Keras Gemma.
- Ajuste o modelo do Gemma na GPU.
- Saiba mais sobre a integração do Gemma com a Vertex AI.
- Saiba como usar modelos do Gemma com a Vertex AI.