Afficher sur ai.google.dev | Exécuter dans Google Colab | Consulter le code source sur GitHub |
Présentation
CodeGemma est une variante de Gemma affinée pour les tâches de codage. Ce tutoriel s'appuie sur le guide de démarrage rapide de Keras CodeGemma et montre d'autres façons dont CodeGemma peut vous aider dans vos tâches de programmation.
Configuration
Accéder à CodeGemma
Pour suivre ce tutoriel, vous devez d'abord suivre les instructions de configuration de Gemma. Les instructions de configuration de Gemma vous expliquent comment:
- Accédez à Gemma sur kaggle.com.
- Sélectionnez un environnement d'exécution Colab disposant de suffisamment de ressources pour exécuter le modèle Gemma 7B.
- Générez et configurez un nom d'utilisateur et une clé API Kaggle.
Une fois la configuration de Gemma terminée, passez à la section suivante, dans laquelle vous allez définir des variables d'environnement pour votre environnement Colab.
Sélectionner l'environnement d'exécution
Pour exécuter les modèles CodeGemma 7B, vous devez disposer d'un forfait Colab Pro payant qui fournit un environnement d'exécution avec un GPU A100.
- En haut à droite de la fenêtre Colab, sélectionnez ▾ (Options de connexion supplémentaires).
- Sélectionnez Modifier le type d'environnement d'exécution.
- Dans Accélérateur matériel, sélectionnez GPU A100.
Configurer votre clé API
Pour utiliser Gemma, vous devez fournir votre nom d'utilisateur Kaggle et une clé d'API Kaggle.
Pour générer une clé API Kaggle, accédez à l'onglet Compte de votre profil utilisateur Kaggle et sélectionnez Créer un jeton. Cette opération déclenchera le téléchargement d'un fichier kaggle.json
contenant vos identifiants pour l'API.
Dans Colab, sélectionnez Secrets (pensez) dans le volet de gauche et ajoutez votre nom d'utilisateur Kaggle et votre clé API Kaggle. Stockez votre nom d'utilisateur sous le nom KAGGLE_USERNAME
et votre clé API sous le nom KAGGLE_KEY
.
Définir des variables d'environnement
Définissez les variables d'environnement pour KAGGLE_USERNAME
et KAGGLE_KEY
.
import os
from google.colab import userdata
os.environ["KAGGLE_USERNAME"] = userdata.get('KAGGLE_USERNAME')
os.environ["KAGGLE_KEY"] = userdata.get('KAGGLE_KEY')
Installer des dépendances
pip install -q -U keras-nlp
Sélectionnez un backend
Keras est une API de deep learning multi-framework de haut niveau, conçue pour être simple et facile à utiliser. Avec Keras 3, vous pouvez exécuter des workflows sur l'un des trois backends suivants: TensorFlow, JAX ou PyTorch.
Pour ce tutoriel, configurez le backend pour JAX.
os.environ["KERAS_BACKEND"] = "jax" # Or "tensorflow" or "torch".
Importer des packages
Importer Keras et KerasNLP
import keras_nlp
import keras
# Run at half precision.
keras.config.set_floatx("bfloat16")
Exemples de modèle CodeGemma 7B
Cette section présente des exemples d'utilisation du modèle pré-entraîné CodeGemma 7B pour faciliter les tâches de codage.
Charger le modèle
KerasNLP fournit des implémentations des trois variantes CodeGemma (2 et 7 milliards de variantes pré-entraînées (PT) et 7 milliards d'instructions avec réglage de l'instruction (IT) à l'aide de GemmaCausalLM
, un modèle Gemma de bout en bout destiné à la modélisation du langage causale. Un modèle de langage causal prédit le jeton suivant en fonction des jetons précédents.
Dans cet exemple, chargez le modèle code_gemma_7b_en
à l'aide de la méthode from_preset
.
gemma_lm_7b = keras_nlp.models.GemmaCausalLM.from_preset("code_gemma_7b_en")
Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_7b_en/1/download/config.json... 100%|██████████| 556/556 [00:00<00:00, 790kB/s] Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_7b_en/1/download/model.weights.h5... 100%|██████████| 15.9G/15.9G [02:39<00:00, 107MB/s] Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_7b_en/1/download/tokenizer.json... 100%|██████████| 401/401 [00:00<00:00, 587kB/s] Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_7b_en/1/download/assets/tokenizer/vocabulary.spm... 100%|██████████| 4.04M/4.04M [00:00<00:00, 16.4MB/s]
gemma_lm_7b.summary()
La méthode from_preset
instancie le modèle à partir d'une architecture et de pondérations prédéfinies.
Complétion de code avec FIM multiligne
Les modèles PT CodeGemma sont entraînés sur des tâches de remplissage de code. Cette section présente des exemples qui utilisent la fonctionnalité FIM (fill-in the middle) sur plusieurs lignes de CodeGemma pour saisir automatiquement du code à l'emplacement spécifié du curseur, en fonction du contexte environnant.
Dans un premier temps, définissez des constantes et une fonction d'assistance de mise en forme des requêtes.
# Formatting control tokens to specify cursor location
BEFORE_CURSOR = "<|fim_prefix|>"
AFTER_CURSOR = "<|fim_suffix|>"
AT_CURSOR = "<|fim_middle|>"
FILE_SEPARATOR = "<|file_separator|>"
# Define model stop tokens
END_TOKEN = gemma_lm_7b.preprocessor.tokenizer.end_token
stop_tokens = (BEFORE_CURSOR, AFTER_CURSOR, AT_CURSOR, FILE_SEPARATOR, END_TOKEN)
stop_token_ids = tuple(gemma_lm_7b.preprocessor.tokenizer.token_to_id(x) for x in stop_tokens)
def format_completion_prompt(before, after):
return f"{BEFORE_CURSOR}{before}{AFTER_CURSOR}{after}{AT_CURSOR}"
Exemple 1 : Insérer une condition manquante
L'exemple de code ci-dessous permettant de générer la séquence de Fibonacci ne s'exécutera pas correctement si n=1
:
def fibonacci(n: int) -> int:
if n == 0:
return 0
# The cursor is right before the e in the following line
else:
return fibonacci(n - 1) + fibonacci(n - 2)
En supposant que le curseur se trouve au début de la ligne 4 (où se trouve la clause else
), le contenu avant et après le curseur est le suivant:
before = """def fibonacci(n: int) -> int:\n if n == 0:\n return 0\n""" # Mind the spaces!
after = """\n else:\n return fibonacci(n - 1) + fibonacci(n-2)\n"""
prompt = format_completion_prompt(before, after)
print(prompt)
<|fim_prefix|>def fibonacci(n: int) -> int: if n == 0: return 0 <|fim_suffix|> else: return fibonacci(n - 1) + fibonacci(n-2) <|fim_middle|>
Exécutez la requête.
print(gemma_lm_7b.generate(prompt, stop_token_ids=stop_token_ids, max_length=128))
<|fim_prefix|>def fibonacci(n: int) -> int: if n == 0: return 0 <|fim_suffix|> else: return fibonacci(n - 1) + fibonacci(n-2) <|fim_middle|>elif n == 1: return 1<|file_separator|>
Le modèle insère la condition elif
correcte pour n=1
à l'emplacement du curseur.
Exemple 2 : Algorithme de balayage DFS complet
Code de saisie semi-automatique pour un algorithme de balayage d'arborescence de recherche axée sur la profondeur (DFS)
before = """void dfs(node* root) {
if (root->left) {
dfs(root->left);
}"""
after = """\nprintf("%d", root->value);
}"""
prompt = format_completion_prompt(before, after)
print(prompt)
<|fim_prefix|>void dfs(node* root) { if (root->left) { dfs(root->left); }<|fim_suffix|> printf("%d", root->value); }<|fim_middle|>
Exécutez la requête.
print(gemma_lm_7b.generate(prompt, stop_token_ids=stop_token_ids, max_length=128))
<|fim_prefix|>void dfs(node* root) { if (root->left) { dfs(root->left); }<|fim_suffix|> printf("%d", root->value); }<|fim_middle|> if (root->right) { dfs(root->right); }<|file_separator|>
Génération de code
En plus du remplissage de code, le modèle CodeGemma 7B PT est également entraîné sur des corpus en langage naturel. Vous pouvez l'utiliser pour inviter le modèle à générer du code.
generation_prompt= """Write a rust function to identify non-prime numbers.
Examples:
>>> is_not_prime(2)
False
>>> is_not_prime(10)
True
pub fn is_not_prime(n: i32) -> bool {"""
print(gemma_lm_7b.generate(generation_prompt, max_length=500))
Write a rust function to identify non-prime numbers. Examples: >>> is_not_prime(2) False >>> is_not_prime(10) True pub fn is_not_prime(n: i32) -> bool { if n <= 1 { return true; } for i in 2..n { if n % i == 0 { return true; } } false }
7 Mrds d'exemples de modèles informatiques
Cette section utilise le modèle CodeGemma 7B avec instructions ajustées pour des tâches de codage plus avancées. Le modèle informatique CodeGemma 7B est dérivé du modèle PT de CodeGemma 7B grâce à l'affinage supervisé du code ainsi qu'à l'apprentissage par renforcement avec commentaires humains. Cette section présente des exemples d'utilisation de ce modèle pour une génération ouverte.
Charger le modèle informatique
Chargez le modèle code_gemma_instruct_7b_en
à l'aide de la méthode from_preset
.
gemma_lm_7b_it = keras_nlp.models.GemmaCausalLM.from_preset("code_gemma_instruct_7b_en")
gemma_lm_7b_it.summary()
Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_instruct_7b_en/1/download/config.json... 100%|██████████| 556/556 [00:00<00:00, 754kB/s] Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_instruct_7b_en/1/download/model.weights.h5... 100%|██████████| 15.9G/15.9G [03:18<00:00, 86.2MB/s] Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_instruct_7b_en/1/download/tokenizer.json... 100%|██████████| 401/401 [00:00<00:00, 593kB/s] Downloading from https://www.kaggle.com/api/v1/models/keras/codegemma/keras/code_gemma_instruct_7b_en/1/download/assets/tokenizer/vocabulary.spm... 100%|██████████| 4.04M/4.04M [00:00<00:00, 16.8MB/s]
Les modèles IT sont entraînés avec un outil de mise en forme spécifique qui annote tous les exemples de réglage d'instructions avec des informations supplémentaires pour indiquer les rôles et délimiter les tours de conversation.
Dans un premier temps, définissez des constantes et une fonction d'assistance de mise en forme des requêtes.
# Formatting control tokens for instruction tuning
START_OF_TURN_USER = "<start_of_turn>user"
END_OF_TURN = "<end_of_turn>"
START_OF_TURN_MODEL = "<start_of_turn>model"
# Formatting helper function
def format_instruction_prompt(context):
return f"{START_OF_TURN_USER}\n{context}{END_OF_TURN}\n{START_OF_TURN_MODEL}\n"
Traduction de code
context1 = """
You are an experienced C and Python programmer. Convert the following Python code into C.
```python
def factorial(n):
result = 1
for i in range(2, n + 1):
result *= i
return result
```\n"""
Mettez en forme la requête.
prompt1 = format_instruction_prompt(context1)
print(prompt1)
<start_of_turn>user You are an experienced C and Python programmer. Convert the following Python code into C. ```python def factorial(n): result = 1 for i in range(2, n + 1): result *= i return result ``` <end_of_turn> <start_of_turn>model
Exécutez la requête.
print(gemma_lm_7b_it.generate(prompt1, max_length=500))
<start_of_turn>user You are an experienced C and Python programmer. Convert the following Python code into C. ```python def factorial(n): result = 1 for i in range(2, n + 1): result *= i return result ``` <end_of_turn> <start_of_turn>model Here is the C code equivalent of the Python code: ```c int factorial(int n) { int result = 1; for (int i = 2; i <= n; i++) { result *= i; } return result; } ``` Here is a breakdown of the changes: * The function is declared with the `int` return type, as in Python. * The `for` loop is converted to a `for` loop with an `int` variable `i` initialized to 2 and incremented by 1 in each iteration. * The `range` function is replaced with a simple loop that iterates from 2 to `n` (inclusive). * The `result *= i` statement is used to multiply `result` by `i` in each iteration. * The `return` statement is used to return the final value of `result`.
Détection de vulnérabilité du code
context2 = """
You are an experienced C++ programmer hunting for vulnerable code. Is the following code vulnerable? Explain your reasoning.
```cpp
int i;
unsigned int numWidgets;
Widget **WidgetList;
numWidgets = GetUntrustedSizeValue();
if ((numWidgets == 0) || (numWidgets > MAX_NUM_WIDGETS)) {
ExitError("Incorrect number of widgets requested!");
}
WidgetList = (Widget **) malloc(numWidgets * sizeof(Widget *));
printf("WidgetList ptr=%p\n", WidgetList);
for (i = 0; i < numWidgets; i++) {
WidgetList[i] = InitializeWidget();
}
WidgetList[numWidgets] = NULL;
showWidgets(WidgetList);
```\n"""
Mettez en forme la requête.
prompt2 = format_instruction_prompt(context2)
print(prompt2)
<start_of_turn>user You are an experienced C++ programmer hunting for vulnerable code. Is the following code vulnerable? Explain your reasoning. ```cpp int i; unsigned int numWidgets; Widget **WidgetList; numWidgets = GetUntrustedSizeValue(); if ((numWidgets == 0) || (numWidgets > MAX_NUM_WIDGETS)) { ExitError("Incorrect number of widgets requested!"); } WidgetList = (Widget **) malloc(numWidgets * sizeof(Widget *)); printf("WidgetList ptr=%p ", WidgetList); for (i = 0; i < numWidgets; i++) { WidgetList[i] = InitializeWidget(); } WidgetList[numWidgets] = NULL; showWidgets(WidgetList); ``` <end_of_turn> <start_of_turn>model
print(gemma_lm_7b_it.generate(prompt2, max_length=1000))
<start_of_turn>user You are an experienced C++ programmer hunting for vulnerable code. Is the following code vulnerable? Explain your reasoning. ```cpp int i; unsigned int numWidgets; Widget **WidgetList; numWidgets = GetUntrustedSizeValue(); if ((numWidgets == 0) || (numWidgets > MAX_NUM_WIDGETS)) { ExitError("Incorrect number of widgets requested!"); } WidgetList = (Widget **) malloc(numWidgets * sizeof(Widget *)); printf("WidgetList ptr=%p ", WidgetList); for (i = 0; i < numWidgets; i++) { WidgetList[i] = InitializeWidget(); } WidgetList[numWidgets] = NULL; showWidgets(WidgetList); ``` <end_of_turn> <start_of_turn>model Yes, the code is vulnerable to a memory access error. **Reasoning:** * The code allocates memory for `WidgetList` using `malloc` based on the value of `numWidgets`. * However, the loop iterates from `0` to `numWidgets`, which is one element beyond the allocated memory. * This means that accessing `WidgetList[numWidgets]` will result in a memory access error, as it is outside the bounds of the allocated memory. **Example of Memory Access Error:** When `numWidgets` is 5, the code allocates memory for `WidgetList` as follows: ``` WidgetList = (Widget **) malloc(5 * sizeof(Widget *)); ``` The loop iterates from 0 to 4, accessing the following elements: * `WidgetList[0]` * `WidgetList[1]` * `WidgetList[2]` * `WidgetList[3]` * `WidgetList[4]` However, the code then attempts to access `WidgetList[5]`, which is outside the allocated memory range. This will result in a memory access error. **Solution:** To resolve this vulnerability, the loop should be modified to iterate from 0 to `numWidgets - 1`: ```cpp for (i = 0; i < numWidgets - 1; i++) { WidgetList[i] = InitializeWidget(); } ``` This ensures that the loop does not access elements beyond the allocated memory range.
Le modèle détecte une faille potentielle dans le code et le modifie afin de l'atténuer.
Résumé
Ce tutoriel vous a montré comment utiliser CodeGemma pour diverses tâches de codage. Pour en savoir plus sur CodeGemma:
- Reportez-vous à la fiche de modèle CodeGemma pour connaître les caractéristiques techniques des modèles CodeGemma.
- Pour en savoir plus sur l'utilisation de CodeGemma dans Vertex AI, cliquez ici.
- Consultez le guide de démarrage rapide de Keras CodeGemma.