نقدّم CodeGemma، وهي مجموعة من نماذج الرموز البرمجية المفتوحة المستندة إلى نماذج Gemma من Google DeepMind (Gemma Team et al., 2024). CodeGemma هي مجموعة من أحدث النماذج المتطوّرة والخفيفة المتاحة للجميع، والتي تم إنشاؤها بناءً على الأبحاث والتكنولوجيا نفسها المستخدَمة في إنشاء نماذج Gemini.
استنادًا إلى نماذج Gemma المُدرَّبة مسبقًا، يتم تدريب نماذج CodeGemma بشكل إضافي على أكثر من 500 إلى 1,000 مليار رمز برمجي بشكل أساسي، باستخدام البنى الأساسية نفسها المستخدَمة في عائلة نماذج Gemma. نتيجةً لذلك، تحقّق نماذج CodeGemma أفضل أداء للترميز في كلّ من مهام الإنجاز وإنشاء الرموز البرمجية، مع الحفاظ على مهارات قوية للفهم والاستدلال على نطاق واسع.
تتوفّر 3 أنواع من نماذج CodeGemma:
- نموذج مدرَّب مسبقًا لرمز 7B
- نموذج رمز مُعدّ للتعليمات 7B
- نموذج 2B تم تدريبه خصيصًا لملء الرموز البرمجية وإنشاء نصوص مفتوحة.
يرشدك هذا الدليل إلى كيفية استخدام نموذج CodeGemma مع Flax لتنفيذ مهمة إكمال رمز برمجي.
ضبط إعدادات الجهاز
1. إعداد إمكانية الوصول إلى Kaggle من أجل CodeGemma
لإكمال هذا الدليل التعليمي، عليك أولاً اتّباع تعليمات الإعداد في إعداد Gemma، والتي توضّح لك كيفية تنفيذ ما يلي:
- يمكنك الوصول إلى CodeGemma على kaggle.com.
- اختَر بيئة تشغيل Colab تتضمّن موارد كافية (وحدة معالجة الرسومات T4 لا تتضمّن ذاكرة كافية، استخدِم TPU v2 بدلاً من ذلك) لتشغيل نموذج 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 insufficient حاليًا لتشغيل دفتر ملاحظات هذا. إذا كنت تستخدم Colab Pay As You Go أو Colab Pro، انقر على تعديل > إعدادات دفتر الملاحظات > اختَر وحدة معالجة الرسومات A100 > حفظ لتفعيل ميزة "مسرِّع الأجهزة".
بعد ذلك، عليك تثبيت مكتبة gemma
من Google DeepMind من 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.deprecated import params as params_lib
from gemma.deprecated import sampler as sampler_lib
from gemma.deprecated 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.deprecated.transformer.TransformerConfig
. وسيطة cache_size
هي عدد الخطوات الزمنية في ذاكرة التخزين المؤقت Transformer
في CodeGemma. بعد ذلك، أنشئ مثيلًا لنموذج CodeGemma باسم model_2b
باستخدام gemma.deprecated.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'"
بعد ذلك، نُشكّل هذا الطلب على النحو التالي: البادئة-اللاحقة-الوسط (يكون القسم الأوسط الذي يجب ملؤه دائمًا في نهاية الطلب):
"<|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.deprecated.transformer
وgemma.sampler
. - تتوفّر مواقع إلكترونية خاصة بالمستندات لكلّ من المكتبات التالية: JAX الأساسية وFlax وOrbax.
- للاطّلاع على مستندات
sentencepiece
لفاصل الكلمات/أداة إزالة الفواصل، يمكنك الاطّلاع على مستودع GitHub الخاص بـsentencepiece
من Google. - للاطّلاع على مستندات
kagglehub
، يمكنك الاطّلاع علىREADME.md
في مستودع GitHub الخاص بـkagglehub
في Kaggle. - تعرَّف على كيفية استخدام نماذج Gemma مع Google Cloud Vertex AI.
- إذا كنت تستخدم وحدات معالجة TPU من 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.