TATECHATLAS
◎ हिन्दी
कृत्रिम बुद्धिमत्ता / मार्गदर्शिका

मॉडल कॉन्ट्रैक्ट के हिस्से के रूप में चैट टेम्पलेट्स: भूमिकाएं, स्पेशल टोकन और डबल टोकनाइजेशन

एक चैट टेम्पलेट उस सटीक टोकन अनुक्रम को निर्धारित करता है जिसकी एक चैट मॉडल अपेक्षा करता है, जिसमें रोल कंट्रोल टोकन और स्पेशल बाउंड्री टोकन शामिल होते हैं। इसे कॉन्ट्रैक्ट डेटा के रूप में मानने से गलत फॉर्मेटिंग और डुप्लिकेट स्पेशल टोकन के कारण होने वाली गुणवत्ता हानि को रोका जा सकता है।

इस पृष्ठ पर

चैट टेम्पलेट को मॉडल कॉन्ट्रैक्ट के एक घोषित हिस्से के रूप में मानें: समर्थित भूमिकाओं (system, user, assistant), प्रत्येक भूमिका के लिए मैप किए गए कंट्रोल टोकन, टोकेनाइज़र के स्पेशल टोकन और फॉर्मेटिंग के दौरान उपयोग किए गए सटीक फ्लैग्स को रिकॉर्ड करें। प्रॉम्प्ट बनाने के लिए tokenizer.apply_chat_template का उपयोग करें, और tokenize=True को प्राथमिकता दें ताकि टेम्पलेट के अपने स्पेशल टोकन ही एकमात्र उत्सर्जित टोकन हों। यदि आप पहले इसे स्ट्रिंग में फॉर्मेट करते हैं, तो बाद में टोकनाइज़ करते समय add_special_tokens=False पास करें, क्योंकि टेम्पलेट में पहले से ही आवश्यक बाउंड्री टोकन शामिल होते हैं। add_generation_prompt=True का उपयोग केवल तब करें जब आप एक नया असिस्टेंट रिप्लाई शुरू कर रहे हों, continue_final_message का उपयोग केवल अंतिम संदेश को प्रीफिल करने के लिए करें, और इन दोनों को एक साथ कभी पास न करें। प्रत्येक मॉडल वेरिएंट पर एक संक्षिप्त जनरेशन टेस्ट के साथ कॉन्ट्रैक्ट को सत्यापित करें, क्योंकि एक ही बेस से फाइन-ट्यून किए गए मॉडलों के बीच भी टेम्पलेट्स भिन्न हो सकते हैं।

एक चैट टेम्पलेट मॉडल कॉन्ट्रैक्ट में क्यों होना चाहिए

एक कॉज़ल लैंग्वेज मॉडल कभी भी बातचीत को उसके वास्तविक रूप में प्राप्त नहीं करता है। यह केवल एक फ्लैट टोकन अनुक्रम प्राप्त करता है और भविष्यवाणी करता है कि आगे क्या आएगा। चैट टेम्पलेट वह घटक है जो रोल-एंड-कंटेंट डिक्शनरीज की एक सूची को उस सटीक अनुक्रम में बदल देता है जिसका सामना मॉडल ने चैट फाइन-ट्यूनिंग के दौरान किया था, जिसमें <|user|>, <|assistant|> जैसे कंट्रोल टोकन और एंड-ऑफ-मैसेज मार्कर शामिल होते हैं जो मॉडल को एक्सचेंज की संरचना समझने में मदद करते हैं।

चूंकि एक ही बेस से फाइन-ट्यून किए गए दो मॉडल पूरी तरह से अलग फॉर्मेट का उपयोग कर सकते हैं, इसलिए टेम्पलेट प्रेजेंटेशन के बजाय व्यवहारिक कॉन्ट्रैक्ट डेटा होता है। फॉर्मेट में विसंगति आमतौर पर कोई एक्सेप्शन नहीं देती है; यह चुपचाप रिस्पॉन्स की गुणवत्ता को कम कर देती है, यही कारण है कि कॉन्ट्रैक्ट में टेम्पलेट और उसके टोकन का स्पष्ट उल्लेख होना चाहिए।

अपने इवैल्यूएशन हार्नेस में मॉडल रिवीज़न के साथ रेंडर किए गए प्रॉम्प्ट स्ट्रिंग को स्टोर करें। जब मॉडल या लाइब्रेरी अपग्रेड के बाद आउटपुट क्वालिटी गिरती है, तो स्टोर किए गए प्रॉम्प्ट को डिकोड करें और उसकी तुलना नए रेंडर के साथ करें; यह जनरेशन सेटिंग्स की जांच करने से पहले टेम्पलेट ड्रिफ्ट को मॉडल व्यवहार से अलग करने में मदद करता है।

मानक भूमिकाएं और उनके अर्थ

तीन भूमिकाएं सामान्य मामलों को कवर करती हैं। system उन निर्देशों को ले जाता है कि मॉडल को कैसे कार्य करना चाहिए और सामान्यतः यह सबसे पहले आता है। user मानव क्वेरी को ले जाता है। assistant मॉडल के उत्तर को ले जाता है। टेम्पलेट प्रत्येक भूमिका को कंट्रोल टोकन से मैप करता है, और यह मैपिंग मॉडल-विशिष्ट होती है: Mistral-7B-Instruct यूजर टर्न्स को [INST] और [/INST] में लपेटता है, जबकि Zephyr-7B एंड-ऑफ-सीक्वेंस सेपरेटर के साथ <|user|> और <|assistant|> स्टाइल मार्कर का उपयोग करता है।

इसलिए कॉन्ट्रैक्ट में भूमिकाओं और उनके ठोस टोकन स्पेलिंग को एक साथ बताया जाना चाहिए। केवल भूमिकाओं के नाम बताना पर्याप्त नहीं है, क्योंकि एक ही भूमिका का नाम अलग-अलग चेकपॉइंट्स पर अलग तरह से रेंडर होता है और गलत टोकन सेट ठीक वही विफलता मोड है जिसे रोकने के लिए टेम्पलेट मौजूद है।

टोकेनाइज़र में स्पेशल टोकन को परिभाषित करना

टोकेनाइज़र कॉन्फ़िगरेशन उन हिस्सों को उजागर करता है जिनका टेम्पलेट उपयोग करता है। प्रासंगिक गुणों में chat_template शामिल है, जो एक Jinja टेम्पलेट स्ट्रिंग है जो मैसेज लिस्ट को फॉर्मेट करती है, साथ ही bos_token, eos_token, unk_token, sep_token, pad_token, cls_token और mask_token जैसे स्पेशल टोकन शामिल हैं। टेम्पलेट इनकी स्पेलिंग को हार्ड-कोड करने के बजाय इन गुणों को पढ़ता है, इसलिए टोकेनाइज़र और टेम्पलेट को एक ही मॉडल रिवीज़न से लोड किया जाना चाहिए।

पूर्व-आवश्यकता: टोकेनाइज़र में वास्तव में एक chat_template गुण होना चाहिए। यदि ऐसा नहीं है, तो apply_chat_template के पास रेंडर करने के लिए कुछ नहीं होगा और आपको स्पष्ट रूप से एक टेम्पलेट प्रदान करना होगा या एक अलग चेकपॉइंट चुनना होगा। यह एक एनवायरनमेंट और वर्जन संबंधी चिंता है, न कि इस बात की गारंटी कि कोई भी दिया गया टेम्पलेट किसी दिए गए मॉडल के ट्रेनिंग फॉर्मेट से मेल खाता है।

apply_chat_template के साथ टेम्पलेट लागू करना

कार्य अनुक्रम इस प्रकार है: रोल और कंटेंट कीज़ के साथ डिक्शनरीज की एक सूची बनाएं, apply_chat_template को कॉल करें, और जब आपको generate() के लिए टोकन आईडी चाहिए हों तो tokenize=True चुनें, या जब आपको निरीक्षण या लॉगिंग के लिए फॉर्मेटेड स्ट्रिंग चाहिए हो तो tokenize=False चुनें। add_special_tokens=False केवल तभी सेट करें जब आप बाद में स्वयं स्पेशल टोकन जोड़ना चाहते हों।

नीचे दिया गया उदाहरण एक चैट टेम्पलेट वाले टोकेनाइज़र को लोड करता है, एक सिस्टम और एक यूजर मैसेज को फॉर्मेट करता है, और एक जनरेशन प्रॉम्प्ट का अनुरोध करता है। प्रिंट की गई लाइन एक उदाहरण आउटपुट है: सटीक स्पेसिंग टोकेनाइज़र वर्जन और टेम्पलेट रिवीज़न पर निर्भर करती है।

उदाहरण आउटपुट (आकार, न कि कैप्चर किया गया रन):

<|system|> You are a helpful assistant </s><|user|> What is 2+2? </s><|assistant|>

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained('HuggingFaceH4/zephyr-7b-beta')
messages = [
    {"role": "system", "content": "You are a helpful assistant"},
    {"role": "user", "content": "What is 2+2?"}
]
ids = tokenizer.apply_chat_template(
    messages,
    tokenize=True,
    add_generation_prompt=True,
    return_tensors='pt'
)
print(tokenizer.decode(ids['input_ids'][0]))

डबल टोकनाइजेशन से बचना

चैट टेम्पलेट्स पहले से ही वे स्पेशल टोकन उत्सर्जित करते हैं जिनकी मॉडल को आवश्यकता होती है। यदि आप tokenize=False के साथ रेंडर करते हैं और फिर परिणामी स्ट्रिंग को टोकेनाइज़र के सामान्य कॉल के माध्यम से चलाते हैं, तो डिफ़ॉल्ट add_special_tokens=True पथ दूसरी बार bos या eos टोकन डाल सकता है। यह डुप्लीकेट स्पष्ट रूप से विफल नहीं होता है; यह उस अनुक्रम को बदल देता है जिसकी मॉडल को अपेक्षा थी जिस पर उसे प्रशिक्षित किया गया था।

सुरक्षित पैटर्न apply_chat_template(tokenize=True) है, जो कंट्रोल टोकन सहित IDs लौटाता है। यदि स्ट्रिंग इंटरमीडिएट अपरिहार्य है, तो इसे add_special_tokens=False के साथ टोकनाइज़ करें। यह अंतर उन पाइपलाइनों में सबसे अधिक मायने रखता है जहाँ फॉर्मेटिंग और एन्कोडिंग अलग-अलग सेवाओं में होती है।

जेनरेशन प्रॉम्प्ट और फाइनल-मैसेज हैंडलिंग

add_generation_prompt=True उन टोकन को जोड़ता है जो असिस्टेंट के उत्तर की शुरुआत की घोषणा करते हैं, ताकि मॉडल उपयोगकर्ता के टेक्स्ट को जारी रखने के बजाय उत्तर दे। इसका Llama जैसे उन मॉडलों पर कोई प्रभाव नहीं पड़ता है जिनमें कोई विशेष असिस्टेंट-स्टार्ट टोकन नहीं होता है, इसलिए कॉन्ट्रैक्ट को यह रिकॉर्ड करना चाहिए कि क्या टारगेट मॉडल इसका उपयोग करता है।

continue_final_message इसके विपरीत कार्य करता है: यह एंड-ऑफ-सीक्वेंस टोकन को हटा देता है ताकि जेनरेशन अंतिम संदेश के भीतर जारी रहे, जो एक ज्ञात रिस्पांस प्रीफिक्स या reasoning_content जैसे रीजनिंग फील्ड को प्रीफिल करने के लिए उपयोगी है। ये दोनों फ्लैग परस्पर अनन्य हैं, और इन्हें संयोजित करने पर त्रुटि आती है। ट्रेनिंग के दौरान, add_generation_prompt=False का उपयोग करें, क्योंकि ट्रेनिंग सीक्वेंस में असिस्टेंट-स्टार्ट टोकन सहायक नहीं होते हैं।

मॉडल वेरिएंट्स के खिलाफ कॉन्ट्रैक्ट का परीक्षण

केवल सिंटैक्स सही होने का प्रमाण नहीं है। प्रत्येक मॉडल वेरिएंट के लिए, एक निश्चित दो-टर्न बातचीत रेंडर करें, उसे डिकोड करें, और पुष्टि करें कि कंट्रोल टोकन और बाउंड्री टोकन उस फॉर्मेट से मेल खाते हैं जिसके साथ उस मॉडल को प्रशिक्षित किया गया था। फिर एक छोटा जेनरेशन चलाएं और जांचें कि मॉडल उपयोगकर्ता के संदेश को बढ़ाने के बजाय एक असिस्टेंट के रूप में उत्तर देता है।

जब भी मॉडल रिवीजन, transformers वर्जन, या टोकेनाइज़र सोर्स बदलता है, तो यह जांच चलाएं। एक जैसे दिखने वाले रोल नाम समान टोकन सीक्वेंस का संकेत नहीं देते हैं, और एक टेम्पलेट जो एक फाइन-ट्यून के लिए काम करता है, वह उसी बेस से प्राप्त दूसरे मॉडल पर चुपचाप विफल हो सकता है।

कॉन्ट्रैक्ट में टेम्पलेट का दस्तावेजीकरण

एक पुनरुत्पादनीय कॉन्ट्रैक्ट भूमिकाओं, आवश्यक कंट्रोल टोकन, जेनरेशन-प्रॉम्प्ट व्यवहार, और सटीक टेम्पलेट स्ट्रिंग या इसके अपरिवर्तनीय सोर्स रिवीजन को रिकॉर्ड करता है। नीचे दिया गया स्निपेट आपके दस्तावेजीकरण सिस्टम के लिए एक स्कीमा फ्रैगमेंट है, न कि कोई चलाने योग्य कॉन्फ़िगरेशन: इसमें आपके मॉडल आइडेंटिफायर और टेम्पलेट टेक्स्ट को भरने की आवश्यकता है।

केवल इसके आउटपुट के बजाय टेम्पलेट सोर्स (टोकेनाइज़र एट्रिब्यूट या स्पष्ट स्ट्रिंग) को रिकॉर्ड करें, क्योंकि टोकेनाइज़र लाइब्रेरी वर्जन बदलने पर आउटपुट बदल सकता है।

model_contract:
  model_id: <hugging-face-model-id>
  tokenizer_revision: <revision-or-commit>
  roles:
    system: <role-token-or-pattern>
    user: <role-token-or-pattern>
    assistant: <role-token-or-pattern>
  special_tokens:
    bos: <token>
    eos: <token>
  add_generation_prompt_on_inference: true
  add_generation_prompt_on_training: false
  continue_final_message: prefill-only
  chat_template_source: tokenizer.chat_template
  chat_template_text: <exact-jinja-template>

क्या जाँचें

  • पुष्टि करें कि टोकेनाइज़र उपयोग किए जा रहे सटीक मॉडल रिवीज़न के लिए एक गैर-खाली chat_template गुण प्रदर्शित करता है।
  • एक रेंडर किए गए प्रॉम्प्ट को डिकोड करें और सत्यापित करें कि प्रत्येक भूमिका के कंट्रोल टोकन मॉडल के ट्रेनिंग फॉर्मेट से मेल खाते हैं।
  • सत्यापित करें कि टोकनाइजेशन के बाद प्रति मैसेज बाउंड्री केवल एक bos/eos बाउंड्री दिखाई देती है।
  • यदि पहले स्ट्रिंग में फॉर्मेट कर रहे हैं, तो पुष्टि करें कि बाद का टोकेनाइज़र कॉल add_special_tokens=False का उपयोग करता है।
  • पुष्टि करें कि add_generation_prompt और continue_final_message कभी भी एक साथ पास नहीं किए जाते हैं।
  • रिकॉर्ड करें कि क्या add_generation_prompt का लक्षित मॉडल पर कोई प्रभाव पड़ता है, क्योंकि कुछ मॉडलों में असिस्टेंट-स्टार्ट टोकन नहीं होता है।
  • प्रति मॉडल वेरिएंट एक संक्षिप्त जनरेशन टेस्ट चलाएं और जांचें कि मॉडल उत्तर दे रहा है न कि यूजर टर्न को बढ़ा रहा है।
  • स्टोर किए गए टेम्पलेट टेक्स्ट के साथ transformers वर्जन और टोकेनाइज़र रिवीज़न को पिन करें।

टेम्पलेट्स मॉडल-विशिष्ट होते हैं: एक चेकपॉइंट के लिए लिखा गया कॉन्ट्रैक्ट दूसरे पर लागू नहीं हो सकता है, भले ही दोनों एक ही बेस मॉडल से व्युत्पन्न हों। Llama जैसे मॉडलों के लिए add_generation_prompt अप्रभावी है जिनमें कोई स्पष्ट असिस्टेंट-स्टार्ट टोकन नहीं होता है, और इसे continue_final_message के साथ संयोजित करने पर त्रुटि आती है। उदाहरणों में chat_template गुण वाले Hugging Face टोकेनाइज़र और इंस्टॉल transformers लाइब्रेरी का अनुमान लगाया गया है; सटीक रेंडर स्पेसिंग और टोकन आईडी टोकेनाइज़र और लाइब्रेरी वर्जन पर निर्भर करते हैं, इसलिए यहाँ दिखाया गया डिकोडेड स्ट्रिंग उदाहरण मात्र है। यह लेख केवल प्रॉम्प्ट फॉर्मेटिंग को कवर करता है और जनरेशन क्वालिटी, लेटेंसी या टास्क एक्यूरेसी के बारे में कोई दावा नहीं करता है।

स्रोत

  1. Hugging Face: chat templates ↗
  2. Hugging Face: tokenizers ↗
ऊपर जाएँ ↑