مستوى المقال: مبتدئ — مكتوب لأي حد لسه بيتعرّف على نماذج اللغة، بالأمثلة الأول وبعدين العلم.
الـ Tokenization: ليه الذكاء الاصطناعي مش بيشوف الحروف زيّك
بعد المقال ده هتفهم بالظبط ليه ChatGPT بيغلط لما تسأله "كام حرف r في كلمة strawberry"، وهتعرف تحسب تكلفة أي نص قبل ما تبعته للنموذج.
المشكلة باختصار
اسأل أي نموذج لغة كبير: "how many r's are in strawberry". لفترة طويلة كان بيرد باتنين، والإجابة الصح تلاتة. الغلطة دي مش لأن النموذج غبي. هي لأنه أصلاً مش بيشوف الحروف. بيشوف حاجة اسمها "توكنات" (tokens). ولو فهمت التوكن، هتفهم نص المشاكل اللي بتقابلك مع الـ AI.
مثال بسيط قبل العلم: الكلمة اللي بتتقطّع
تخيل إنك بتقرأ كلمة طويلة مش شايفها حرف حرف، لكن مقسومة لمقاطع جاهزة. زي ما بتقرأ "مستشفى" على إنها مقطع واحد بسرعة، من غير ما تتهجّى م-س-ت-ش-ف-ى. النموذج بيعمل نفس الحاجة، بس بشكل أعمق: بياخد النص ويقسّمه لقطع شائعة اسمها توكنات، وكل قطعة ليها رقم.
كلمة strawberry مثلاً بتتقسم لتلات قطع: "str" و "aw" و "berry". النموذج بيشوف تلات أرقام، مش عشر حروف. جوه "berry" فيه حرفين r، وجوه "str" فيه واحد. بس النموذج شايف القطعة كوحدة واحدة، مش شايف الـ r اللي جواها. عشان كده عدّ الحروف بيبقى صعب عليه.
الشرح العلمي: التوكن مش الحرف
التوكن هو أصغر وحدة النموذج بيتعامل معاها. مش حرف، ومش كلمة كاملة بالضرورة. غالباً بيبقى "مقطع" (subword). النموذج عنده قاموس ثابت فيه عشرات الآلاف من التوكنات، وكل توكن ليه ID رقمي. أول خطوة في أي نموذج لغة إنه يحوّل نصك لقائمة IDs. ده اسمه Tokenization.
الخوارزمية الأشهر لبناء القاموس ده اسمها Byte Pair Encoding واختصارها BPE. فكرتها بسيطة: ابدأ بالحروف المفردة، وبعدين دمج أكتر زوج حروف بيتكرر مع بعض في توكن واحد، وكرّر. لو "e" و "r" بيجوا ورا بعض كتير، هيبقى عندك توكن "er". وبعدها ممكن "b" مع "er" يبقى "ber". النتيجة قاموس فيه قطع شائعة: الكلمات المشهورة بتتمثّل بتوكن أو اتنين، والنادرة بتتقطّع لأجزاء أصغر.
جرّبها بنفسك: كود بيعدّ التوكنات
ركّز في الكود ده. بيستخدم مكتبة tiktoken بتاعة OpenAI، ونفس الترميز اللي بيستخدمه GPT-4 و GPT-3.5.
import tiktoken
# نفس ترميز GPT-4 / GPT-3.5
enc = tiktoken.get_encoding("cl100k_base")
kalima = "strawberry"
ids = enc.encode(kalima)
print(ids) # أرقام (IDs) مش حروف
print(len(ids)) # عدد التوكنات = 3 غالباً
print([enc.decode([i]) for i in ids]) # ['str', 'aw', 'berry']
# قارن نص إنجليزي بنص عربي بنفس المعنى
en = "artificial intelligence"
ar = "الذكاء الاصطناعي"
print(len(enc.encode(en))) # قليل
print(len(enc.encode(ar))) # أكبر بكثير