الاستنتاج باستخدام CodeGemma باستخدام JAX وFlex

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

نقدّم لك CodeGemma، وهي مجموعة من نماذج الرموز المفتوحة القائمة على نماذج Gemma من Google DeepMind (Gemma Team وآخرون، 2024). CodeGemma هي مجموعة من النماذج المتطوّرة والخفيفة المتاحة للجميع، والتي تم إنشاؤها بناءً على الأبحاث والتكنولوجيا نفسها المستخدَمة في إنشاء نماذج Gemini.

استندًا إلى نماذج Gemma المدرَّبة مسبقًا، وتم تدريب نماذج CodeGemma أيضًا على أكثر من 500 إلى 1000 مليار رمز مميّز من الرموز البرمجية في المقام الأول، وذلك باستخدام نفس البُنى الهندسية لعائلة نموذج جيما. ونتيجةً لذلك، تحقّق نماذج CodeGemma أداءً متطوّرًا للرموز البرمجية عند إكمال كلا الإجراءَين. وإنشاء المهام مع الحفاظ على مهارات الفهم والتحليل على نطاق واسع.

تتوفّر 3 خيارات في CodeGemma:

  • نموذج 7B المدرب مسبقًا
  • نموذج رمز برمجي مضبوط على التعليمات يبلغ 7 مليار
  • هو نموذج ثنائي الأبعاد، تم تدريبه خصيصًا لإدخال الرموز البرمجية والإنشاء المفتوح.

يرشدك هذا الدليل خلال استخدام نموذج CodeGemma مع Flax لتنفيذ مهمة إكمال التعليمات البرمجية.

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

1. إعداد وصول Kaggle لـ CodeGemma

لإكمال هذا البرنامج التعليمي، عليك أولاً اتّباع تعليمات الإعداد في إعداد Gemma، والتي توضِّح لك كيفية إجراء ما يلي:

  • يمكنك الوصول إلى CodeGemma على kaggle.com.
  • اختَر بيئة تشغيل Colab باستخدام موارد كافية (لا تتوفّر ذاكرة كافية في وحدة معالجة الرسومات T4، واستخدِم الإصدار 2 من TPU بدلاً من ذلك) لتشغيل نموذج CodeGemma.
  • إنشاء وتكوين اسم مستخدم ومفتاح واجهة برمجة تطبيقات Kaggle.

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

2. ضبط متغيرات البيئة

ضبط متغيّرات البيئة لكل من KAGGLE_USERNAME وKAGGLE_KEY عندما يُطلب منك عرض رسالة "هل تريد منح إمكانية الوصول؟" أو الموافقة على توفير الوصول السري.

import os
from google.colab import userdata # `userdata` is a Colab API.

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

3- تثبيت مكتبة gemma

إنّ ميزة تسريع أجهزة Colab المجانية غير كافية حاليًا لتشغيل ورقة الملاحظات هذه. في حال استخدام Colab Pay As You Go أو Colab Pro، انقر على تعديل > إعدادات ورقة الملاحظات > اختَر وحدة معالجة رسومات A100 > انقر على حفظ لتفعيل ميزة "تسريع الأجهزة".

بعد ذلك، عليك تثبيت مكتبة Google DeepMind gemma من github.com/google-deepmind/gemma. إذا ظهرت لك رسالة خطأ بشأن "أداة حل التبعية في pip"، يمكنك عادةً تجاهلها.

pip install -q git+https://github.com/google-deepmind/gemma.git

4. استيراد المكتبات

تستخدم ورقة الملاحظات هذه أداة Gemma (التي تستخدم Flax لإنشاء طبقات الشبكة العصبونية) وSentencePiece (للترميز المميز).

import os
from gemma import params as params_lib
from gemma import sampler as sampler_lib
from gemma import transformer as transformer_lib
import sentencepiece as spm

تحميل نموذج CodeGemma

حمِّل نموذج CodeGemma باستخدام kagglehub.model_download، الذي يأخذ ثلاث وسيطات:

  • handle: مؤشر النموذج من Kaggle
  • path: (سلسلة اختيارية) المسار المحلي
  • force_download: (قيمة منطقية اختيارية) تفرض إعادة تنزيل النموذج
GEMMA_VARIANT = '2b-pt' # @param ['2b-pt', '7b-it', '7b-pt', '1.1-2b-pt', '1.1-7b-it'] {type:"string"}
import kagglehub

GEMMA_PATH = kagglehub.model_download(f'google/codegemma/flax/{GEMMA_VARIANT}')
Warning: Looks like you're using an outdated `kagglehub` version, please consider updating (latest version: 0.2.7)
Downloading from https://www.kaggle.com/api/v1/models/google/codegemma/flax/2b-pt/3/download...
100%|██████████| 3.67G/3.67G [00:22<00:00, 173MB/s]
Extracting model files...
print('GEMMA_PATH:', GEMMA_PATH)
GEMMA_PATH: /root/.cache/kagglehub/models/google/codegemma/flax/2b-pt/3

تحقَّق من الموقع الجغرافي لقيم ترجيح النموذج وأداة إنشاء الرموز المميّزة، ثم اضبط متغيّرات المسار. سيكون دليل أداة إنشاء الرموز المميّزة في الدليل الرئيسي الذي نزّلت فيه النموذج، بينما ستكون القيم التقديرية للنموذج في دليل فرعي. على سبيل المثال:

  • سيكون ملف أداة إنشاء الرموز المميّزة spm.model في "/LOCAL/PATH/TO/codegemma/flax/2b-pt/3".
  • ستكون النقطة المرجعية للنموذج في /LOCAL/PATH/TO/codegemma/flax/2b-pt/3/2b-pt.
CKPT_PATH = os.path.join(GEMMA_PATH, GEMMA_VARIANT[-5:])
TOKENIZER_PATH = os.path.join(GEMMA_PATH, 'spm.model')
print('CKPT_PATH:', CKPT_PATH)
print('TOKENIZER_PATH:', TOKENIZER_PATH)
CKPT_PATH: /root/.cache/kagglehub/models/google/codegemma/flax/2b-pt/3/2b-pt
TOKENIZER_PATH: /root/.cache/kagglehub/models/google/codegemma/flax/2b-pt/3/spm.model

إجراء أخذ العينات/الاستنتاج

حمِّل نقطة مراجعة نموذج CodeGemma وتنسيقها باستخدام الطريقة gemma.params.load_and_format_params:

params = params_lib.load_and_format_params(CKPT_PATH)

حمِّل برنامج ترميز CodeGemma المميز، الذي تم إنشاؤه باستخدام sentencepiece.SentencePieceProcessor:

vocab = spm.SentencePieceProcessor()
vocab.Load(TOKENIZER_PATH)
True

لتحميل الإعدادات الصحيحة تلقائيًا من نقطة مراجعة نموذج CodeGemma، استخدِم gemma.transformer.TransformerConfig. الوسيطة cache_size هي عدد الخطوات الزمنية في ذاكرة التخزين المؤقت لـ CodeGemma Transformer. بعد ذلك، يمكنك إنشاء مثيل لنموذج CodeGemma كـ model_2b باستخدام gemma.transformer.Transformer (والذي يُستخدم في flax.linen.Module).

transformer_config = transformer_lib.TransformerConfig.from_params(
    params,
    cache_size=1024
)

transformer = transformer_lib.Transformer(config=transformer_config)

إنشاء sampler باستخدام gemma.sampler.Sampler وهو يستخدم نقطة فحص نموذج CodeGemma وأداة إنشاء الرموز المميّزة.

sampler = sampler_lib.Sampler(
    transformer=transformer,
    vocab=vocab,
    params=params['transformer']
)

قم بإنشاء بعض المتغيرات لتمثيل رموز التعبئة في المنتصف (fim) وإنشاء بعض الدوال المساعدة لتنسيق المطالبة والإخراج الذي تم إنشاؤه.

على سبيل المثال، لنلقِ نظرة على الرمز التالي:

def function(string):
assert function('asdf') == 'fdsa'

نريد ملء function حتى يشمل التأكيد True. في هذه الحالة، تكون البادئة على النحو التالي:

"def function(string):\n"

وستكون اللاحقة على النحو التالي:

"assert function('asdf') == 'fdsa'"

بعد ذلك، ننسق هذا في مطالبة كـ PREFIX- الجوّال-MIDDLE (يكون القسم الأوسط الذي يجب ملؤه دائمًا في نهاية المطالبة):

"<|fim_prefix|>def function(string):\n<|fim_suffix|>assert function('asdf') == 'fdsa'<|fim_middle|>"
# In the context of a code editor,
# the cursor is the location where the text will be inserted
BEFORE_CURSOR = "<|fim_prefix|>"
AFTER_CURSOR = "<|fim_suffix|>"
AT_CURSOR = "<|fim_middle|>"
FILE_SEPARATOR = "<|file_separator|>"

def format_completion_prompt(before, after):
  print(f"\nORIGINAL PROMPT:\n{before}{after}")
  prompt = f"{BEFORE_CURSOR}{before}{AFTER_CURSOR}{after}{AT_CURSOR}"
  print(f"\nFORMATTED PROMPT:\n{repr(prompt)}")
  return prompt
def format_generated_output(before, after, output):
  print(f"\nGENERATED OUTPUT:\n{repr(output)}")
  formatted_output = f"{before}{output.replace(FILE_SEPARATOR, '')}{after}"
  print(f"\nFILL-IN COMPLETION:\n{formatted_output}")
  return formatted_output

إنشاء مطالبة وإجراء الاستنتاج حدِّد نص البادئة before واللاحقة after وأنشِئ طلبًا منسَّقًا باستخدام دالة المساعدة format_completion prompt.

يمكنك تعديل total_generation_steps (عدد الخطوات التي يتم تنفيذها عند إنشاء ردّ، إذ يستخدم هذا المثال 100 للاحتفاظ بذاكرة المضيف).

before = "def function(string):\n"
after = "assert function('asdf') == 'fdsa'"
prompt = format_completion_prompt(before, after)

output = sampler(
    [prompt],
    total_generation_steps=100,
    ).text

formatted_output = format_generated_output(before, after, output[0])
ORIGINAL PROMPT:
def function(string):
assert function('asdf') == 'fdsa'

FORMATTED PROMPT:
"<|fim_prefix|>def function(string):\n<|fim_suffix|>assert function('asdf') == 'fdsa'<|fim_middle|>"

GENERATED OUTPUT:
'    return string[::-1]\n\n<|file_separator|>'

FILL-IN COMPLETION:
def function(string):
    return string[::-1]

assert function('asdf') == 'fdsa'
before = "import "
after = """if __name__ == "__main__":\n    sys.exit(0)"""
prompt = format_completion_prompt(before, after)

output = sampler(
    [prompt],
    total_generation_steps=100,
    ).text

formatted_output = format_generated_output(before, after, output[0])
ORIGINAL PROMPT:
import if __name__ == "__main__":
    sys.exit(0)

FORMATTED PROMPT:
'<|fim_prefix|>import <|fim_suffix|>if __name__ == "__main__":\n    sys.exit(0)<|fim_middle|>'

GENERATED OUTPUT:
'sys\n<|file_separator|>'

FILL-IN COMPLETION:
import sys
if __name__ == "__main__":
    sys.exit(0)
before = """import numpy as np
def reflect(matrix):
  # horizontally reflect a matrix
"""
after = ""
prompt = format_completion_prompt(before, after)

output = sampler(
    [prompt],
    total_generation_steps=100,
    ).text

formatted_output = format_generated_output(before, after, output[0])
ORIGINAL PROMPT:
import numpy as np
def reflect(matrix):
  # horizontally reflect a matrix


FORMATTED PROMPT:
'<|fim_prefix|>import numpy as np\ndef reflect(matrix):\n  # horizontally reflect a matrix\n<|fim_suffix|><|fim_middle|>'

GENERATED OUTPUT:
'  return np.flip(matrix, axis=1)\n<|file_separator|>'

FILL-IN COMPLETION:
import numpy as np
def reflect(matrix):
  # horizontally reflect a matrix
  return np.flip(matrix, axis=1)

مزيد من المعلومات

  • يمكنك معرفة المزيد عن مكتبة gemma في Google DeepMind على GitHub، والتي تحتوي على سلاسل توثيق للوحدات التي استخدمتها في هذا البرنامج التعليمي، مثل gemma.params، gemma.transformer، gemma.sampler.
  • تحتوي المكتبات التالية على مواقع إلكترونية خاصة بها للمستندات: الأساسية JAX وFlax وOrbax.
  • للحصول على مستندات حول أداة ترميز أو أداة إزالة الرموز المميّزة حول sentencepiece، يُرجى الاطّلاع على مستودع GitHub من sentencepiece التابع لشركة Google.
  • للاطّلاع على مستندات kagglehub، يُرجى الاطّلاع على README.md على مستودع GitHub الخاص بـ kagglehub من Kaggle.
  • تعرَّف على كيفية استخدام نماذج Gemma مع Google Cloud Vertex AI.
  • إذا كنت تستخدم وحدات معالجة الموتّرات في Google Cloud (الإصدار 3-8 والإصدارات الأحدث)، احرص أيضًا على تثبيت أحدث حزمة jax[tpu] (!pip install -U jax[tpu] -f https://storage.googleapis.com/jax-releases/libtpu_releases.html) وإعادة تشغيل بيئة التشغيل والتأكّد من تطابق الإصدارَين jax وjaxlib مع (!pip list | grep jax). ويمكن أن يؤدي ذلك إلى منع ظهور RuntimeError بسبب عدم تطابق الإصدارين jaxlib وjax. للحصول على مزيد من تعليمات تثبيت JAX، يُرجى الرجوع إلى مستندات JAX.