Lập trình có sự hỗ trợ của AI thông qua CodeGemma và KerasNLP

Xem trên ai.google.dev Chạy trong Google Colab Xem nguồn trên GitHub

Tổng quan

CodeGemma là một biến thể của Gemma được tinh chỉnh cho các nhiệm vụ lập trình. Hướng dẫn này được xây dựng dựa trên hướng dẫn bắt đầu nhanh về Keras CodeGemma và chỉ cho bạn thêm nhiều cách mà CodeGemma có thể hỗ trợ bạn thực hiện công việc lập trình.

Thiết lập

Truy cập vào CodeGemma

Để hoàn tất hướng dẫn này, trước tiên bạn cần phải hoàn thành hướng dẫn thiết lập trong phần thiết lập Gemma. Hướng dẫn thiết lập Gemma chỉ cho bạn cách thực hiện những việc sau:

  • Truy cập vào Gemma trên kaggle.com.
  • Chọn một môi trường thời gian chạy Colab có đủ tài nguyên để chạy mô hình Gemma 7B.
  • Tạo và định cấu hình tên người dùng Kaggle và khoá API.

Sau khi thiết lập xong Gemma, hãy chuyển sang phần tiếp theo. Tại đây, bạn sẽ thiết lập các biến môi trường cho môi trường Colab của mình.

Chọn thời gian chạy

Để chạy các mô hình CodeGemma 7B, bạn cần có một gói Colab Pro có tính phí. Gói này cung cấp thời gian chạy với GPU A100.

  1. Ở phía trên bên phải của cửa sổ Colab, hãy chọn ▾ (Các tuỳ chọn kết nối khác).
  2. Chọn Thay đổi loại thời gian chạy.
  3. Trong Trình tăng tốc phần cứng, hãy chọn GPU A100.

Định cấu hình khoá API

Để sử dụng Gemma, bạn phải cung cấp tên người dùng Kaggle và khoá API Kaggle.

Để tạo khoá API Kaggle, hãy chuyển đến thẻ Tài khoản trong hồ sơ người dùng Kaggle rồi chọn Tạo mã thông báo mới. Thao tác này sẽ kích hoạt việc tải tệp kaggle.json chứa thông tin đăng nhập API của bạn xuống.

Trong Colab, hãy chọn Bí mật (🔑) ở ngăn bên trái, rồi thêm tên người dùng Kaggle và khoá API Kaggle. Lưu trữ tên người dùng của bạn dưới tên KAGGLE_USERNAME và khoá API dưới tên KAGGLE_KEY.

Đặt các biến môi trường

Thiết lập các biến môi trường cho KAGGLE_USERNAMEKAGGLE_KEY.

import os
from google.colab import userdata

os.environ["KAGGLE_USERNAME"] = userdata.get('KAGGLE_USERNAME')
os.environ["KAGGLE_KEY"] = userdata.get('KAGGLE_KEY')

Cài đặt phần phụ thuộc

pip install -q -U keras-nlp

Chọn một phần phụ trợ

Keras là một API học sâu cấp cao, đa khung, được thiết kế để mang lại trải nghiệm đơn giản và dễ sử dụng. Khi sử dụng Keras 3, bạn có thể chạy quy trình công việc trên một trong ba phần phụ trợ: TensorFlow, JAX hoặc PyTorch.

Trong hướng dẫn này, hãy định cấu hình phần phụ trợ cho JAX.

os.environ["KERAS_BACKEND"] = "jax"  # Or "tensorflow" or "torch".

Nhập gói

Nhập Keras và KerasNLP.

import keras_nlp
import keras

# Run at half precision.
keras.config.set_floatx("bfloat16")

Ví dụ về mô hình CodeGemma 7B

Phần này trình bày các ví dụ về cách sử dụng mô hình CodeGemma 7B đã được huấn luyện trước để hỗ trợ các nhiệm vụ lập trình.

Tải mô hình

KerasNLP cung cấp cách triển khai cả ba biến thể CodeGemma (2B và 7B được huấn luyện trước (PT) và 7B được tinh chỉnh theo hướng dẫn (IT)) bằng cách sử dụng GemmaCausalLM, một mô hình Gemma toàn diện để lập mô hình ngôn ngữ nhân quả. Mô hình ngôn ngữ nhân quả dự đoán mã thông báo tiếp theo dựa trên mã thông báo trước đó.

Trong ví dụ này, hãy tải mô hình code_gemma_7b_en bằng phương thức 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()

Phương thức from_preset tạo thực thể cho mô hình từ một cấu trúc và trọng số đặt trước.

Hoàn thành mã bằng FIM nhiều dòng

Các mô hình PT CodeGemma được huấn luyện về các tác vụ điền mã. Phần này trình bày các ví dụ sử dụng tính năng điền nhiều dòng vào giữa (FIM) của CodeGemma để tự động điền mã tại vị trí con trỏ được chỉ định dựa trên ngữ cảnh xung quanh.

Bước đầu tiên, hãy xác định các hằng số và một hàm trợ giúp định dạng lời nhắc.

# 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}"

Ví dụ 1 – Chèn điều kiện bị thiếu

Mã ví dụ dưới đây để tạo chuỗi Fibonacci sẽ không thực thi chính xác nếu 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)

Giả sử con trỏ nằm ở đầu dòng 4 (trong đó mệnh đề else), thì nội dung trước và sau con trỏ sẽ là:

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|>

Chạy lời nhắc.

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|>

Mô hình này sẽ chèn đúng cấu hình elif cho n=1 tại vị trí của con trỏ.

Ví dụ 2 – Thuật toán truyền tải DFS hoàn chỉnh

Mã tự động hoàn tất cho thuật toán truyền tải cây theo phương thức tìm kiếm theo chiều sâu (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|>

Chạy lời nhắc.

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|>

Tạo mã

Ngoài việc điền mã, CodeGemma 7B PT là mô hình cũng được huấn luyện dựa trên các nguồn khai thác ngôn ngữ tự nhiên. Bạn có thể sử dụng đoạn mã này để nhắc mô hình tạo mã.

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
}

Ví dụ về mô hình CNTT 7B

Phần này sử dụng mô hình Điều chỉnh hướng dẫn CodeGemma 7B cho các nhiệm vụ lập trình nâng cao hơn. Mô hình CNTT của CodeGemma 7B bắt nguồn từ mô hình CodeGemma 7B PT thông qua hoạt động tinh chỉnh có giám sát trên mã cùng với Reinforcement Learning with Human Feedback. Phần này trình bày các ví dụ về cách sử dụng mô hình này cho thế hệ kết thúc mở.

Tải mô hình CNTT

Tải mô hình code_gemma_instruct_7b_en bằng phương thức 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]

Các mô hình CNTT được huấn luyện bằng một trình định dạng cụ thể chú thích tất cả các ví dụ điều chỉnh hướng dẫn kèm theo thông tin bổ sung để biểu thị vai trò và mô tả các ngã rẽ trong một cuộc trò chuyện.

Bước đầu tiên, hãy xác định các hằng số và một hàm trợ giúp định dạng lời nhắc.

# 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"

Dịch mã

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"""

Định dạng câu lệnh.

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

Chạy lời nhắc.

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`.

Phát hiện lỗ hổng bảo mật mã

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"""

Định dạng câu lệnh.

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.

Mô hình này phát hiện một lỗ hổng tiềm ẩn trong mã và đưa ra các thay đổi mã để giảm thiểu lỗ hổng đó.

Tóm tắt

Hướng dẫn này hướng dẫn bạn cách sử dụng CodeGemma cho nhiều tác vụ lập trình. Cách tìm hiểu thêm về CodeGemma: