البرمجة بمساعدة الذكاء الاصطناعي من خلال برنامجَي CodeGemma وKerasNLP

العرض على ai.google.dev التنفيذ في Google Colab عرض المصدر على GitHub

نظرة عامة

CodeGemma هو أحد إصدارات Gemma التي تم تحسينها لأداء مهام الترميز. يعتمد هذا البرنامج التعليمي على البدء السريع لـ Keras CodeGemma ويوضح لك المزيد من الطرق التي يمكن أن تساعدك بها CodeGemma في مهام البرمجة.

ضبط إعدادات الجهاز

الوصول إلى CodeGemma

لإكمال هذا الدليل التعليمي، ستحتاج أولاً إلى إكمال تعليمات الإعداد في صفحة إعداد Gemma. توضح لك تعليمات إعداد Gemma كيفية إجراء ما يلي:

  • يمكنك الوصول إلى Gemma على kaggle.com.
  • اختَر بيئة تشغيل Colab تتضمّن موارد كافية لتشغيل نموذج Gemma 7B.
  • إنشاء وتكوين اسم مستخدم ومفتاح واجهة برمجة تطبيقات Kaggle.

بعد الانتهاء من إعداد Gemma، انتقِل إلى القسم التالي، حيث يمكنك ضبط متغيّرات البيئة لبيئة Colab.

اختيار بيئة التشغيل

لتشغيل نماذج CodeGemma 7B، يجب أن يكون لديك خطة Colab Pro مدفوعة توفّر بيئة تشغيل مع وحدة معالجة رسومات A100.

  1. في أعلى يسار نافذة Colab، اختَر Other (خيارات الاتصال الإضافية).
  2. اختَر تغيير نوع بيئة التشغيل.
  3. ضِمن مسرِّع الأجهزة، اختَر وحدة معالجة رسومات A100.

ضبط مفتاح واجهة برمجة التطبيقات

لاستخدام Gemma، يجب عليك تقديم اسم مستخدم Kaggle ومفتاح واجهة برمجة تطبيقات Kaggle.

لإنشاء مفتاح واجهة برمجة تطبيقات Kaggle، انتقل إلى علامة التبويب الحساب في الملف الشخصي لمستخدم Kaggle وحدد إنشاء رمز مميز جديد. سيؤدي هذا الإجراء إلى بدء تنزيل ملف kaggle.json يتضمّن بيانات اعتماد واجهة برمجة التطبيقات الخاصة بك.

في Colab، اختَر الأسرار (🔑) في اللوحة اليمنى وأضف اسم مستخدم Kaggle ومفتاح واجهة برمجة تطبيقات Kaggle. يمكنك تخزين اسم المستخدم الخاص بك تحت الاسم KAGGLE_USERNAME ومفتاح واجهة برمجة التطبيقات تحت الاسم 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 هي واجهة برمجة تطبيقات عالية المستوى ومتعددة الإطارات للتعلُّم المعمَّق تم تصميمها لتبسيط عملية الاستخدام وسهولة استخدامها. باستخدام Keras 3، يمكنك تنفيذ مهام سير العمل على إحدى الخلفيات الثلاث التالية: TensorFlow أو JAX أو PyTorch.

في هذا البرنامج التعليمي، يجب تهيئة الخلفية لـ 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 (التكنولوجيا المضبوطة) باستخدام 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 أيضًا على مجموعات اللغات الطبيعية. ويمكنك استخدامها لمطالبة النموذج بإنشاء رمز.

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
}

7B أمثلة على نماذج تكنولوجيا المعلومات

يستخدم هذا القسم نموذج CodeGemma 7B Instruction-Tuned لإجراء مهام ترميز أكثر تقدّمًا. يتم اشتقاق نموذج CodeGemma 7B لتكنولوجيا المعلومات من نموذج CodeGemma 7B PT من خلال الضبط الدقيق للرموز البرمجية إلى جانب التعلّم المعزّز من خلال الملاحظات البشرية. يتناول هذا القسم أمثلة على استخدام هذا النموذج في الجيل المفتوح.

تحميل نموذج تكنولوجيا المعلومات

حمِّل النموذج 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]

يتم تدريب نماذج تكنولوجيا المعلومات باستخدام أداة تنسيق معيّنة تضيف تعليقات توضيحية إلى جميع أمثلة ضبط التعليمات مع معلومات إضافية للإشارة إلى الأدوار وتحديد الأدوار في المحادثة.

كخطوة أولى، حدد الثوابت ودالة مساعد تنسيق المطالبة.

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

  • يُرجى الرجوع إلى بطاقة طراز CodeGemma للاطّلاع على المواصفات الفنية لطُرز CodeGemma.
  • يمكنك الاطّلاع على مزيد من المعلومات حول كيفية استخدام CodeGemma في VertexAI هنا.
  • يمكنك الاطّلاع على مقالة Keras CodeGemma Quickstart.