پرامپت‌های نرم (Soft Prompts) مجموعه‌ای از بردارهای آموزش‌پذیر در فضای embedding مدل‌های زبانی هستند که به‌جای توکن‌های واقعی، به‌عنوان ورودی به مدل داده می‌شوند.
این بردارها با استفاده از گرادیان‌های مدل بهینه می‌شوند و به دقت بالاتری در وظایف تخصصی منجر می‌شوند.
پرامپت‌های نرم، برخلاف پرامپت‌های سخت، قابل خواندن نیستند اما کارآمدتر عمل می‌کنند.
آموزش پرامپت نرم، نیازمند دسترسی به وزن مدل است.
این راهنما مکانیزم، فرایند آموزش و کاربردهای پرامپت نرم را به‌صورت فنی بررسی می‌کند.

پرامپت‌های نرم (Soft Prompts) یکی از مفاهیم بنیادین در حوزه بهینه‌سازی پارامتر-کارآمد مدل‌های زبانی هستند که برای حل محدودیت‌های پرامپت‌های سخت طراحی شده‌اند. این بردارها، به‌جای استفاده از توکن‌های گسسته، از فضای پیوسته embedding استفاده می‌کنند و همین ویژگی، به دقت بالاتر در وظایف تخصصی منجر می‌شود. برای درک این مفهوم، ابتدا باید با تفاوت پرامپت سخت و نرم و تنظیم پرامپت مبتنی بر گرادیان آشنا باشیم.

در پروژه‌هایی که به تخصصی‌سازی مدل در دامنه‌های خاص نیاز داشتیم، پرامپت‌های نرم ابزار اصلی برای دستیابی به دقت بالا با کمترین پارامتر بوده است. این تکنیک، به‌جای آموزش میلیون‌ها پارامتر، تنها چند هزار بردار را آموزش می‌دهد و همین ویژگی، آن را به گزینه‌ای جذاب برای تیم‌های کوچک تبدیل می‌کند. اگر با الگوریتم‌های بهینه‌سازی پرامپت آشنا هستید، آماده‌اید تا به لایه پرامپت نرم وارد شوید.

پرامپت نرم را می‌توان با استفاده از یک کلید رمزنگاری‌شده برای باز کردن یک قفل مقایسه کرد: کلید قابل خواندن نیست اما می‌تواند قفل را باز کند. در سامانه‌های LLM، این کلید همان بردار آموزش‌پذیر است. برای مطالعه بیشتر درباره مبانی، می‌توانید صفحه Word Embedding را در ویکی‌پدیا ببینید.

پرامپت نرم دقیقاً چیست؟

پرامپت نرم، مجموعه‌ای از بردارهای پیوسته در فضای embedding مدل است که به‌جای توکن‌های واقعی، به‌عنوان ورودی به مدل داده می‌شود. این بردارها، آموزش‌پذیر هستند و با گرادیان بهینه می‌شوند.

پرامپت نرم، برخلاف پرامپت سخت که از توکن‌های گسسته تشکیل شده است، در فضای پیوسته embedding قرار دارد. این ویژگی، امکان بهینه‌سازی با گرادیان را فراهم می‌کند.

نمایش ریاضی

اگر فضای embedding مدل دارای بعد d باشد و پرامپت نرم دارای n بردار باشد، این پرامپت را می‌توان به‌صورت یک ماتریس (n, d) نمایش داد. این ماتریس، به‌عنوان ورودی به مدل داده می‌شود.

تفاوت با پرامپت سخت

پرامپت سخت از توکن‌های واقعی تشکیل شده و قابل خواندن است. پرامپت نرم از بردارهای پیوسته تشکیل شده و قابل خواندن نیست. برای تفاوت‌های کامل، پست تفاوت پرامپت سخت و نرم را ببینید.

پرامپت نرم، یک بردار آموزش‌پذیر است که در فضای پیوسته embedding مدل قرار دارد و با گرادیان بهینه می‌شود.

چرا پرامپت نرم اهمیت دارد؟

پرامپت نرم به چند دلیل اهمیت دارد:

کاهش پارامترهای آموزش‌پذیر

در پرامپت نرم، تنها بخش کوچکی از پارامترها (معمولاً کمتر از ۱ درصد) آموزش می‌بینند. این کاهش، هزینه و زمان آموزش را به‌طور چشمگیری کاهش می‌دهد.

افزایش دقت در وظایف تخصصی

در دامنه‌های تخصصی، پرامپت نرم معمولاً دقت بالاتری از پرامپت سخت ارائه می‌دهد. دلیل این تفاوت، توانایی کشف الگوهای پنهان است.

حفظ عملکرد مدل پایه

در پرامپت نرم، وزن‌های مدل پایه ثابت می‌مانند. این ویژگی، مانع از دست رفتن دانش مدل پایه می‌شود.

امکان تخصصی‌سازی چندگانه

با آموزش چند پرامپت نرم جداگانه، می‌توان یک مدل پایه واحد را برای چند دامنه تخصصی کرد.

کارایی در محیط‌های با منابع محدود

در محیط‌هایی که دسترسی به GPUهای قوی محدود است، پرامپت نرم یک گزینه عملی است.

ویژگیپرامپت سختپرامپت نرم
پارامترهای آموزش‌پذیر۰< ۱٪
دقت در وظایف تخصصیمتوسطبالا
حفظ دانش پایهبلهبله
چند تخصص با یک مدلمحدودگسترده
هزینه آموزشصفرمتوسط

فرایند آموزش پرامپت نرم

فرایند آموزش پرامپت نرم، شامل چند گام اصلی است:

گام اول: آماده‌سازی داده

یک مجموعه داده برچسب‌دار آماده می‌شود. این داده باید نمونه‌هایی از ورودی و خروجی مورد انتظار را شامل شود.

گام دوم: ساخت پرامپت نرم

یک ماتریس تصادفی با ابعاد (n_tokens, hidden_dim) ساخته می‌شود. این ماتریس، به‌عنوان پرامپت نرم اولیه در نظر گرفته می‌شود.

گام سوم: قفل کردن مدل پایه

همه وزن‌های مدل پایه قفل می‌شوند تا در طول آموزش تغییر نکنند. این کار، با تنظیم requires_grad = False انجام می‌شود.

گام چهارم: تزریق پرامپت

پرامپت نرم به ورودی مدل اضافه می‌شود. این تزریق، معمولاً در لایه embedding انجام می‌شود.

گام پنجم: محاسبه گرادیان

برای هر نمونه، خروجی مدل محاسبه می‌شود و تابع هزینه نسبت به پاسخ مرجع محاسبه می‌شود. سپس، گرادیان تابع هزینه نسبت به پرامپت نرم محاسبه می‌شود.

گام ششم: به‌روزرسانی پرامپت

پرامپت با استفاده از یک بهینه‌ساز مانند Adam به‌روزرسانی می‌شود.

پیاده‌سازی

import torch
import torch.nn as nn

class SoftPrompt(nn.Module):
    def __init__(self, n_tokens, hidden_dim, init_std=0.02):
        super().__init__()
        self.embedding = nn.Parameter(
            torch.randn(n_tokens, hidden_dim) * init_std
        )

    def forward(self):
        return self.embedding

این پیاده‌سازی، یک پرامپت نرم ساده می‌سازد که با گرادیان بهینه می‌شود.

انواع پرامپت نرم

پرامپت‌های نرم را می‌توان بر اساس ساختار و محل تزریق، دسته‌بندی کرد:

Prompt Tuning

در این نوع، پرامپت نرم تنها در لایه ورودی اضافه می‌شود. ساده‌ترین و کارآمدترین نوع است.

Prefix Tuning

در این نوع، پرامپت نرم در همه لایه‌ها اضافه می‌شود. دقت بالاتری دارد اما پارامترهای بیشتری آموزش می‌دهد. برای جزئیات، پست تنظیم پیشوند در پرامپت نویسی را ببینید.

P-tuning

در این نوع، پرامپت نرم از یک ساختار پویا تولید می‌شود. برای جزئیات، پست روش P-tuning در پرامپت نویسی را ببینید.

LoRA

در این نوع، ماتریس‌های کم‌رتبه به وزن‌های مدل اضافه می‌شوند. این روش، معمولاً دقت بالاتری ارائه می‌دهد.

نوعمحل تزریقپارامترها
Prompt Tuningلایه ورودی< ۰.۱٪
Prefix Tuningهمه لایه‌ها< ۱٪
P-tuningلایه ورودی با ساختار پویا< ۰.۱٪
LoRAماتریس‌های وزن< ۱٪

مقداردهی اولیه

مقداردهی اولیه پرامپت نرم، بر نتیجه نهایی اثر می‌گذارد. چند روش رایج وجود دارد:

مقداردهی تصادفی

ساده‌ترین روش، مقداردهی تصادفی با توزیع نرمال است. این روش، ممکن است به بهینه‌های محلی ضعیف منجر شود.

مقداردهی از توکن‌های واقعی

در این روش، پرامپت نرم با بردارهای متناظر با توکن‌های واقعی مقداردهی می‌شود. این روش، معمولاً نتایج بهتری می‌دهد.

مقداردهی از توکن‌های دسته

در این روش، از بردارهای توکن‌های دسته‌بندی مانند [CLS] استفاده می‌شود.

مقداردهی از میانگین

در این روش، از میانگین بردارهای یک گروه از توکن‌های مرتبط استفاده می‌شود.

پیاده‌سازی مقداردهی

def init_from_tokens(model, tokenizer, tokens):
    token_ids = tokenizer.encode(tokens)
    embeddings = model.get_input_embeddings()
    return embeddings.weight[token_ids].detach().clone()

بهینه‌سازی و چالش‌ها

بهینه‌سازی پرامپت نرم، چالش‌های خاص خود را دارد:

انتخاب نرخ یادگیری

نرخ یادگیری مناسب، معمولاً بین 1e-3 تا 1e-2 است. نرخ بالاتر ممکن است به ناپایداری منجر شود.

Regularization

استفاده از Weight Decay و Dropout می‌تواند از بیش‌برازش جلوگیری کند.

Early Stopping

توقف آموزش در نقطه مناسب، از بیش‌برازش جلوگیری می‌کند.

حساسیت به مقداردهی

مقداردهی اولیه، بر نتیجه نهایی اثر می‌گذارد. مقداردهی از توکن‌های واقعی معمولاً نتایج بهتری می‌دهد.

ناپایداری در طول آموزش

در برخی موارد، آموزش پرامپت نرم ناپایدار است. استفاده از Warm-up و Gradient Clipping می‌تواند کمک کند.

پیاده‌سازی گام‌به‌گام

پیاده‌سازی کامل پرامپت نرم در چند گام انجام می‌شود:

from transformers import AutoModelForCausalLM, AutoTokenizer

# Load model
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b")

# Freeze model
for param in model.parameters():
    param.requires_grad = False

# Initialize soft prompt
n_tokens = 20
hidden_dim = model.config.hidden_size
soft_prompt = SoftPrompt(n_tokens, hidden_dim)

# Optimizer
optimizer = torch.optim.AdamW(
    soft_prompt.parameters(),
    lr=1e-2,
    weight_decay=0.01
)

# Training loop
for epoch in range(num_epochs):
    for batch in dataloader:
        optimizer.zero_grad()

        # Get prompt embeddings
        prompt_embeds = soft_prompt()

        # Get input embeddings
        input_embeds = model.get_input_embeddings()(batch["input_ids"])

        # Concatenate
        combined = torch.cat([prompt_embeds, input_embeds], dim=0)

        # Forward
        outputs = model(
            inputs_embeds=combined.unsqueeze(0),
            labels=batch["labels"]
        )

        # Backward
        loss = outputs.loss
        loss.backward()
        optimizer.step()

# Save
torch.save(soft_prompt.state_dict(), "soft_prompt.pt")

مقایسه با سایر روش‌ها

پرامپت نرم در مقایسه با سایر روش‌های پارامتر-کارآمد، ویژگی‌های منحصربه‌فردی دارد:

روشپارامتردقتپیچیدگی
Prompt Tuning< ۰.۱٪متوسطپایین
Prefix Tuning< ۱٪بالامتوسط
P-tuning< ۰.۱٪بالامتوسط
LoRA< ۱٪بالامتوسط
Fine-tuning کامل۱۰۰٪بسیار بالابالا

کاربردهای عملی

پرامپت نرم در چند سناریو کاربرد دارد:

مدل‌های متن‌باز محلی

در محیط‌هایی که به وزن مدل دسترسی داریم، پرامپت نرم گزینه اول است.

تخصصی‌سازی دامنه‌ای

در دامنه‌های تخصصی که به دقت بالایی نیاز است، پرامپت نرم عملکرد خوبی دارد.

چند تخصص با یک مدل

با آموزش چند پرامپت نرم جداگانه، می‌توان یک مدل پایه را برای چند دامنه تخصصی کرد.

حریم خصوصی

پرامپت نرم اجازه می‌دهد مدل بدون ارسال داده به سرویس بیرونی تخصصی شود.

پروژه‌های تحقیقاتی

در پژوهش‌هایی که به بررسی رفتار مدل نیاز دارند، پرامپت نرم ابزار مفیدی است.

محدودیت‌ها

پرامپت نرم، محدودیت‌های خاص خود را دارد:

  • نیاز به وزن مدل: برای استفاده از پرامپت نرم، باید به وزن‌های مدل دسترسی داشته باشید.
  • عدم تفسیرپذیری: پرامپت نرم قابل خواندن نیست و تفسیر آن دشوار است.
  • عدم انتقال‌پذیری: پرامپت نرم آموزش‌دیده برای یک مدل، در مدل دیگر قابل استفاده نیست.
  • حساسیت به مقداردهی: مقداردهی اولیه، بر نتیجه نهایی اثر می‌گذارد.
  • ناپایداری در آموزش: در برخی موارد، آموزش ناپایدار است.
  • نیاز به داده برچسب‌دار: برای آموزش، نیازمند داده برچسب‌دار هستید.

پرسش‌های پرتکرار درباره پرامپت نرم

پرامپت نرم چه تفاوتی با پرامپت سخت دارد؟

پرامپت سخت از توکن‌های واقعی و قابل خواندن تشکیل شده است. پرامپت نرم از بردارهای پیوسته آموزش‌پذیر در فضای embedding تشکیل شده است.

آیا پرامپت نرم با API قابل استفاده است؟

خیر. پرامپت نرم نیازمند دسترسی به وزن مدل است.

چند پارامتر در پرامپت نرم آموزش می‌بیند؟

معمولاً کمتر از ۱ درصد پارامترهای مدل پایه. مقدار دقیق به طول پرامپت و روش بستگی دارد.

آیا پرامپت نرم همیشه بهتر از پرامپت سخت است؟

در وظایف تخصصی، معمولاً بله. در وظایف عمومی، پرامپت سخت می‌تواند کافی باشد.

آیا پرامپت نرم قابل انتقال است؟

خیر. پرامپت نرم به مدل خاص خود گره خورده است و در مدل دیگر قابل استفاده نیست.

چطور پرامپت نرم را مقداردهی اولیه کنیم؟

مقداردهی از توکن‌های واقعی معمولاً نتایج بهتری از مقداردهی تصادفی می‌دهد.

آیا پرامپت نرم بر امنیت اثر دارد؟

پرامپت نرم غیرقابل خواندن است و بررسی امنیتی آن دشوارتر است. برای جزئیات، پست بهترین روش‌های امنیت پرامپت را ببینید.

آیا پرامپت نرم جایگزین Fine-tuning است؟

در بسیاری از موارد، بله. پرامپت نرم می‌تواند عملکردی مشابه Fine-tuning کامل با هزینه کمتر ارائه دهد.

آیا پرامپت نرم برای همه مدل‌ها کاربرد دارد؟

برای اکثر مدل‌های transformer کاربرد دارد، اما پیاده‌سازی آن بین مدل‌ها متفاوت است.

چطور پرامپت نرم را ذخیره کنیم؟

تنها پارامترهای پرامپت ذخیره می‌شوند، نه کل مدل. حجم ذخیره‌سازی معمولاً چند مگابایت است.

آیا پرامپت نرم با پرامپت سخت قابل ترکیب است؟

بله. در سامانه‌های عملی، می‌توان از پرامپت سخت برای زمینه و از پرامپت نرم برای هدایت مدل استفاده کرد.

نتیجه‌گیری کاربردی

پرامپت‌های نرم، مجموعه‌ای از بردارهای آموزش‌پذیر در فضای embedding مدل هستند که با گرادیان بهینه می‌شوند و به دقت بالاتری در وظایف تخصصی منجر می‌شوند. این بردارها، برخلاف پرامپت‌های سخت، قابل خواندن نیستند اما کارآمدتر عمل می‌کنند. آموزش پرامپت نرم، نیازمند دسترسی به وزن مدل است اما در عوض، هزینه و زمان کمتری از Fine-tuning کامل نیاز دارد.

پرامپت نرم، یک بردار آموزش‌پذیر است که در فضای پیوسته embedding مدل قرار دارد و با گرادیان بهینه می‌شود.

در پروژه‌هایی که به مدل‌های متن‌باز دسترسی داشتیم، پرامپت نرم ابزار اصلی برای تخصصی‌سازی مدل بوده است. توصیه می‌کنم این روش را با Prefix Tuning و LoRA مقایسه کنید و بر اساس نیاز پروژه، انتخاب کنید. اگر تجربه‌ای در پیاده‌سازی پرامپت نرم در پروژه‌های واقعی دارید، برای ما جالب است بدانید کدام روش مقداردهی اولیه در دامنه شما بهترین عملکرد را داشته است.