برنامه نویسی به کمک هوش مصنوعی با CodeGemma و KerasNLP

مشاهده در ai.google.dev در Google Colab اجرا شود مشاهده منبع در GitHub

بررسی اجمالی

CodeGemma گونه ای از Gemma است که برای کارهای کدنویسی به خوبی تنظیم شده است. این آموزش مبتنی بر شروع سریع Keras CodeGemma است و راه های بیشتری را به شما نشان می دهد که در آن CodeGemma می تواند به وظایف برنامه نویسی شما کمک کند.

برپایی

به CodeGemma دسترسی پیدا کنید

برای تکمیل این آموزش، ابتدا باید دستورالعمل‌های راه‌اندازی را در Gemma setup تکمیل کنید. دستورالعمل های راه اندازی Gemma به شما نشان می دهد که چگونه کارهای زیر را انجام دهید:

  • در kaggle.com به Gemma دسترسی پیدا کنید.
  • یک زمان اجرا Colab با منابع کافی برای اجرای مدل Gemma 7B انتخاب کنید.
  • نام کاربری و کلید API Kaggle را ایجاد و پیکربندی کنید.

پس از تکمیل تنظیمات Gemma، به بخش بعدی بروید، جایی که متغیرهای محیطی را برای محیط Colab خود تنظیم خواهید کرد.

زمان اجرا را انتخاب کنید

برای اجرای مدل‌های CodeGemma 7B، باید یک برنامه پولی Colab Pro داشته باشید که زمان اجرا را با پردازنده گرافیکی A100 فراهم می‌کند.

  1. در سمت راست بالای پنجره Colab، ▾ ( گزینه های اتصال اضافی ) را انتخاب کنید.
  2. تغییر نوع زمان اجرا را انتخاب کنید.
  3. در بخش شتاب دهنده سخت افزار ، A100 GPU را انتخاب کنید.

کلید API خود را پیکربندی کنید

برای استفاده از Gemma، باید نام کاربری Kaggle و یک کلید Kaggle API ارائه دهید.

برای ایجاد یک کلید Kaggle API، به تب Account پروفایل کاربری Kaggle خود بروید و Create New Token را انتخاب کنید. با این کار دانلود فایل kaggle.json حاوی اطلاعات کاربری API شما راه اندازی می شود.

در Colab، Secrets (🔑) را در قسمت سمت چپ انتخاب کنید و نام کاربری Kaggle و کلید Kaggle API را اضافه کنید. نام کاربری خود را با نام KAGGLE_USERNAME و کلید API خود را با نام KAGGLE_KEY ذخیره کنید.

تنظیم متغیرهای محیطی

متغیرهای محیطی را برای KAGGLE_USERNAME و 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')

وابستگی ها را نصب کنید

pip install -q -U keras-nlp

یک باطن انتخاب کنید

Keras یک API یادگیری عمیق چند چارچوبی و سطح بالا است که برای سادگی و سهولت استفاده طراحی شده است. با استفاده از Keras 3، می‌توانید گردش‌های کاری را روی یکی از سه Backend اجرا کنید: TensorFlow، JAX یا PyTorch.

برای این آموزش، Backend را برای JAX پیکربندی کنید.

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

بسته های وارداتی

Keras و KerasNLP را وارد کنید.

import keras_nlp
import keras

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

نمونه های مدل CodeGemma 7B

این بخش نمونه هایی از استفاده از مدل 7B CodeGemma از پیش آموزش دیده را برای کمک به وظایف کدنویسی پوشش می دهد.

مدل را بارگذاری کنید

KerasNLP اجرای هر سه نوع CodeGemma (2B و 7B از پیش آموزش دیده (PT) و 7B دستورالعمل تنظیم شده (IT)) را با استفاده از GemmaCausalLM ، یک مدل Gemma سرتاسر برای مدل‌سازی زبان علی، ارائه می‌کند. یک مدل زبان علی، نشانه بعدی را بر اساس نشانه های قبلی پیش بینی می کند.

برای این مثال، مدل code_gemma_7b_en را با استفاده از روش 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()

متد from_preset مدل را از یک معماری و وزن از پیش تعیین شده نمونه سازی می کند.

تکمیل کد با FIM چند خطی

مدل‌های PT CodeGemma روی وظایف تکمیل کد آموزش داده شده‌اند. این بخش نمونه‌هایی را نشان می‌دهد که از قابلیت چند خطی (FIM) CodeGemma برای تکمیل خودکار کد در مکان مشخص‌شده مکان‌نما بر اساس زمینه اطراف استفاده می‌کنند.

به عنوان اولین گام، ثابت ها و یک تابع کمکی قالب بندی را تعریف کنید.

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

مثال 1 - شرط گم شده را درج کنید

کد مثال زیر برای تولید دنباله فیبوناچی اگر 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)

با فرض اینکه مکان نما در ابتدای خط 4 باشد (جایی که عبارت else قرار دارد)، پس محتوای قبل و بعد از مکان نما به صورت زیر است:

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

دستور را اجرا کنید.

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

این مدل شرط elif صحیح را برای n=1 در محل مکان نما درج می کند.

مثال 2 - الگوریتم پیمایش DFS کامل

تکمیل خودکار کد برای الگوریتم پیمایش درخت در ابتدا در عمق (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|>

دستور را اجرا کنید.

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

تولید کد

علاوه بر تکمیل کد، مدل CodeGemma 7B PT is نیز بر روی پیکره های زبان طبیعی آموزش داده شده است. می توانید از این برای درخواست از مدل برای تولید کد استفاده کنید.

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
}

نمونه های مدل IT 7B

این بخش از مدل CodeGemma 7B Instruction-Tuned برای کارهای کدنویسی پیشرفته تر استفاده می کند. مدل IT CodeGemma 7B از مدل CodeGemma 7B PT از طریق تنظیم دقیق کد به همراه آموزش تقویتی با بازخورد انسانی مشتق شده است. در این بخش نمونه هایی از استفاده از این مدل برای نسل باز را پوشش می دهد.

مدل IT را بارگذاری کنید

مدل code_gemma_instruct_7b_en را با استفاده از روش 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]

مدل‌های IT با یک قالب‌کننده خاص آموزش داده می‌شوند که تمام نمونه‌های تنظیم دستورالعمل را با اطلاعات اضافی برای نشان دادن نقش‌ها و مشخص کردن چرخش‌ها در یک مکالمه حاشیه‌نویسی می‌کند.

به عنوان اولین گام، ثابت ها و یک تابع کمکی قالب بندی را تعریف کنید.

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

ترجمه کد

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

درخواست را فرمت کنید.

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

دستور را اجرا کنید.

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

تشخیص آسیب پذیری کد

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

درخواست را فرمت کنید.

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.

این مدل یک آسیب پذیری بالقوه در کد را شناسایی می کند و تغییرات کد را برای کاهش آن ارائه می دهد.

خلاصه

این آموزش شما را با استفاده از CodeGemma برای انواع وظایف کدنویسی راهنمایی کرد. برای کسب اطلاعات بیشتر در مورد CodeGemma: