درس ۹ از ۱۲، بخش ۳: مهندسی پرامپت

کاربردها (۱): استنتاج، استخراج و دسته‌بندی متن

متنی ۲۵ دقیقه به‌روز شده در ۱۱ آبان ۱۴۰۵

در این درس
  1. تحلیل احساس
  2. هیجان‌ها و خشم
  3. استخراج اطلاعات به JSON
  4. چند کار در یک پرامپت
  5. تشخیص موجودیت‌های نام‌دار (NER)
  6. کلیدواژه، موضوع و دسته‌بندی بدون نمونه
  7. خلاصه

یکی از پرکاربردترین استفاده‌های LLM استنتاج (inferring) است: متن را بخوان و چیزی درباره‌اش بگو. احساس نویسنده، موضوع متن، اسم آدم‌ها و شرکت‌ها. قبل از LLMها برای هر کدام از این کارها باید داده جمع می‌کردیم، برچسب می‌زدیم و یک مدل جداگانه آموزش می‌دادیم. حالا با یک پرامپت انجام می‌شوند و با عوض کردن پرامپت، کار هم عوض می‌شود.

تحلیل احساس#

review = "روشن نشد و مرجوع کردم"

prompt = f"""
What is the sentiment of the following product review in Persian,
which is delimited with triple backticks?

Review text: '''{review}'''
"""
print(get_completion(prompt))
The sentiment of the review "روشن نشد و مرجوع کردم" … – "It didn't work and I returned it" – is **negative**.
Here's a breakdown: …

جواب درست است، اما برای برنامه بی‌فایده است. نمی‌شود این پاراگراف را در یک ستون پایگاه داده نوشت. یک خط به پرامپت اضافه می‌کنیم:

Give your answer as a single word, either "positive" or "negative".
negative

حالا خروجی را مستقیم می‌شود با if بررسی کرد یا در گزارش شمرد.

هیجان‌ها و خشم#

Identify a list of emotions that the writer of the following review is expressing.
Include no more than five items in the list.
Format your answer as a list of lower-case words separated by commas.
نظر خروجی
«بنده از خریدم بسیار راضی هستم … بعد از اتمام واقعاً کالا ناموجود اعلام شد» satisfied, disappointed, frustrated
«اگه حالا این گوشی رو بخریم حتماً آپدیت تا اندروید ۱۳ رو میگیره یا نه؟» uncertainty, anxiety, hope, anticipation

یک کاربرد مهم دیگر، تشخیص خشم است. مثلاً پیام‌های خشمگین زودتر به یک کارشناس انسانی برسند: «Is the writer of the following review expressing anger? Answer with yes or no.»

استخراج اطلاعات به JSON#

Identify the following items from the review text:
- Item purchased by reviewer
- Company that made the item

The review is delimited with triple backticks.
Format your response as a JSON object with "Item" and "Brand" as the keys.
If the information isn't present, use "unknown" as the value.
Make your response as short as possible.

برای نظری درباره‌ی یک چراغ مطالعه خروجی {"Item": "lamp", "Brand": "Lumina"} بود و برای نظری درباره‌ی یک گوشی {"Item": "smartphone", "Brand": "Xiaomi"}.

به جمله‌ی «If the information isn't present, use "unknown"» دقت کنید. این همان تاکتیک بررسی شرط است و جلوی ساختن برند از هیچ را می‌گیرد.

چند کار در یک پرامپت#

لازم نیست برای هر ویژگی یک بار مدل را صدا بزنید. یک فراخوانی ارزان‌تر و سریع‌تر است:

review = "من کلا از شیائومی راضی هستم؛ قبلا ترازو و دستگاه تصفیه هواشو گرفتم، الان مسواکشو خریداری کردم. پیشنهاد میکنم"

prompt = f"""
Identify the following items from the review text:
- Sentiment (positive or negative)
- Is the reviewer expressing anger? (true or false)
- Item purchased by reviewer
- Company that made the item

Format your response as a JSON object with "Sentiment", "Anger", "Item" and "Brand" as the keys.
Format the Anger value as a boolean.

Review text: '''{review}'''
"""
{"Sentiment": "positive", "Anger": false, "Item": "مسواک", "Brand": "شیائومی"}

با یک حلقه روی هزاران نظر، می‌توانید داشبوردی بسازید که نشان دهد مشتری‌ها از کدام محصول کدام برند ناراضی‌اند. بدون اینکه حتی یک داده‌ی برچسب‌خورده داشته باشید.

تشخیص موجودیت‌های نام‌دار (NER)#

NER (Named Entity Recognition) یعنی پیدا کردن اسم آدم‌ها، سازمان‌ها، مکان‌ها و تاریخ‌ها در متن. کاربرد معمولش جستجو در اسناد است، مثلاً «همه‌ی نامه‌هایی که فلان شرکت فرستاده» یا «نامه‌هایی که اسم فلان شخص در آن‌هاست».

Your task is to extract all person names.
Original paragraph: ```{p}```

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

به هیچ عنوان القاب مثل دکتر و ... را ذکر نکن

چرا با regex یا یک فهرست اسم انجامش ندهیم؟ چون اسم‌ها را نمی‌شود فهرست کرد. «اخوان» اسم خانوادگی است، اما در «با تشکر از اخوان موسوی» یعنی «برادران موسوی». فقط فهم کانتکست این دو را از هم جدا می‌کند.

کلیدواژه، موضوع و دسته‌بندی بدون نمونه#

متن نمونه: پاراگراف اول صفحه‌ی ویکی‌پدیای علی دایی.

کلیدواژه:

علی دایی, فوتبال, ایران, لیگ ایران, قطر, آلمان, امارات, گلزن, تیم ملی, کنفدراسیون فوتبال آسیا, …

پنج موضوع، با پرامپت «Determine five topics … Make each item one or two words long … All items should be in Persian»:

علی دایی, فوتبال ایران, لیگ قطر, جام ملت‌ها, مربیگری

قبلاً موضوع‌یابی (topic modeling) با الگوریتم‌های آماری مثل LDA انجام می‌شد که موضوع‌ها را به شکل مجموعه‌ای از کلمه‌ها برمی‌گرداندند و تفسیرشان با انسان بود. حالا مدل مستقیم اسم موضوع را می‌گوید.

دسته‌بندی بدون نمونه (zero-shot)#

اگر دسته‌ها از قبل معلوم باشند، مثلاً می‌خواهید هر خبر به یکی از بخش‌های سایت برود، فهرست را به مدل بدهید:

topic_list = ["سیاست", "مهندسی", "فرهنگ و هنر", "ورزشی", "تاریخ", "دین"]

prompt = f"""
Determine whether each item in the following list of topics is a topic in the text below,
which is delimited with triple backticks.
Give your answer as list with 0 or 1 for each topic.

List of topics: {", ".join(topic_list)}

Text sample: '''{p}'''
"""

برای متن علی دایی فقط «ورزشی» ۱ شد. برای متن زندگی‌نامه‌ی یک سیاستمدار روحانی، «سیاست» و «دین» هر دو ۱ شدند، پس یک متن می‌تواند چند برچسب داشته باشد. به این دسته‌بندی بدون نمونه (zero-shot classification) می‌گویند، چون حتی یک مثال برچسب‌خورده هم ندادیم.

مدل کوچک توضیح اضافه هم داد («Here's the analysis of each topic…»). برای پردازش خودکار بهتر است قالب دقیق‌تری بخواهید، مثلاً JSON با کلید برای هر موضوع، یا مدل بزرگ‌تری به کار ببرید.

خلاصه#

  • با پرامپت می‌شود احساس، هیجان، خشم، موجودیت‌ها، کلیدواژه و موضوع را استخراج کرد، بدون داده‌ی آموزشی.
  • برای برنامه، خروجی را کوتاه و ساخت‌یافته بخواهید: یک کلمه، فهرست جداشده با کاما یا JSON.
  • برای اطلاعاتی که ممکن است در متن نباشد، مقدار پیش‌فرض تعیین کنید (unknown).
  • چند کار را در یک فراخوانی انجام دهید تا هزینه و زمان کم شود.