فاز 5 · درس 29

ردیابی وضعیت گفتگو (DST): تبدیل مکالمه به داده‌های ساختاریافته

نوع
ساختنی
زمان
حدود 75 دقیقه
زبان‌ها
Python
پیش‌نیاز
فاز 5 · درس 17 (چت‌بات‌ها)، فاز 5 · درس 20 (خروجی‌های ساختاریافته)
یک صفحه کلید با نمایشگرهای الکترونیکی کوچک و سوئیچ‌های ساختاریافته که شاخص‌های وضعیت را مرحله به مرحله تنظیم می‌کنند
فهرست مطالب
  1. صورت مسئله
  2. مفاهیم پایه
  3. الگوهای شکست کلاسیک
  4. پیاده‌سازی
  5. مرحله‌ی 1: استخراج‌کننده‌ی قاعده‌محور اسلات
  6. مرحله‌ی 2: حلقه‌ی به‌روزرسانی وضعیت
  7. مرحله‌ی 3: ردیابی وضعیت با LLM و خروجی ساختاریافته
  8. مرحله‌ی 4: ارزیابی با معیار JGA
  9. مرحله‌ی 5: مدیریت اصلاحات کاربر
  10. دام‌های رایج
  11. استفاده‌ی کاربردی
  12. پیاده‌سازی نهایی
  13. تمرین‌ها
  14. اصطلاحات کلیدی
  15. برای مطالعه‌ی بیشتر

وقتی کاربر در چند پیام پیاپی نظرش را تغییر می‌دهد («یه رستوران ارزون می‌خوام... نه در واقع متوسط باشه و پیتزا هم داشته باشه»)، چت‌بات‌های متنی ساده معمولاً گیج می‌شوند یا پارامترهای قبلی را فراموش می‌کنند. سیستم‌های گفتگوی وظیفه‌محور برای فراخوانی API و ثبت سفارش، نمی‌توانند به خروجی‌های متنی غیرقطعی تکیه کنند؛ آن‌ها نیاز دارند تا وضعیت خواسته‌های کاربر در قالب یک دیکشنری ساختاریافته از اسلات‌ها و مقادیر (Slot-Value) همیشه به‌روز و دقیق باقی بماند.

ردیابی وضعیت گفتگو (Dialogue State Tracking یا DST) دقیقاً همین پل میان کلمات کاربر و ورودی قطعی بک‌اند است. این مفهوم حتی در دوران مدل‌های زبانی پیشرفته نقشی کلیدی دارد؛ زیرا ایجنت‌ها برای کار با ابزارها نیازمند آرگومان‌های بدون ابهام هستند و ارزیابی کیفیت آن‌ها معیاری مشخص می‌طلبد.

در این درس، با بررسی الگوهای کلاسیک و خطاهای رایج مانند بازنویسی اسلات‌ها و ارجاعات متنی، یاد می‌گیرید چطور یک پایپ‌لاین مطمئن با رجکس و ترکیب مدل‌های زبانی به همراه خروجی‌های ساختاریافته Pydantic پیاده‌سازی کنید.

«یه رستوران ارزون می‌خوام تو شمال شهر... در واقع قیمتش متوسط باشه... غذای ایتالیایی هم داشته باشه.» سه دور گفتگو (Turn)، سه بار به‌روزرسانی وضعیت. وظیفه‌ی ردیابی وضعیت گفتگو (Dialogue State Tracking یا DST) این است که دیکشنری اسلات-مقدار (Slot-Value) را همگام نگه دارد تا رزرو به‌درستی انجام شود.

صورت مسئله

در سیستم‌های گفتگوی وظیفه‌محور (Task-Oriented Dialogue)، هدف کاربر در قالب مجموعه‌ای از جفت‌های اسلات-مقدار کدگذاری می‌شود: {cuisine: italian, area: north, price: moderate}. کاربر در هر دور از گفتگو می‌تواند اسلاتی اضافه کند، تغییر دهد یا حذف کند. سیستم باید کل گفتگو را بخواند و وضعیت فعلی را دقیق خروجی دهد.

کافی است فقط یک اسلات اشتباه استخراج شود تا سیستم رستوران اشتباهی را رزرو کند، پرواز دیگری را زمان‌بندی کند یا مبلغ را از کارت اشتباهی کسر کند. DST حلقه‌ی وصل میان حرف‌های کاربر و عملیاتی است که در بک‌اند اجرا می‌شود.

چرا در سال 2026 با وجود مدل‌های زبانی بزرگ (LLM) هنوز این موضوع اهمیت دارد:

  • حوزه‌های حساس به انطباق و مقررات (بانکداری، سلامت، رزرو پرواز) نیازمند مقادیر اسلات قطعی هستند، نه تولید متن آزاد و مهارنشده.
  • ایجنت‌های ابزارمحور (Tool-Use Agents) قبل از فراخوانی APIها همچنان به تفکیک و تعیین دقیق اسلات‌ها نیاز دارند.
  • اصلاح حرف‌های قبلی در گفتگوهای چندمرحله‌ای سخت‌تر از چیزی است که به نظر می‌رسد: «راستی نه، بذارش برای پنج‌شنبه.»

پایپ‌لاین امروزی: مفاهیم کلاسیک DST + مدل‌های زبانی استخراج‌گر + چارچوب‌های خروجی ساختاریافته (Structured-Output Guardrails).

مفاهیم پایه

DST: تاریخچه‌ی گفتگو ← وضعیت اسلات-مقدار

ساختار وظیفه. یک شِما (Schema) دامنه‌ها (رستوران، هتل، تاکسی) و اسلات‌های آن‌ها (نوع غذا، منطقه، قیمت، تعداد نفرات) را تعریف می‌کند. هر اسلات می‌تواند خالی باشد، با مقداری از یک مجموعه‌ی بسته پر شود (قیمت: {cheap, moderate, expensive})، یا مقداری آزاد و متنی بگیرد (نام: "The Copper Kettle").

دو فرمول‌بندی برای DST.

  • دسته‌بندی (Classification). برای هر جفت (اسلات، مقدار_کاندید)، یک پیش‌بینی بله/خیر انجام می‌دهد. مناسب برای اسلات‌هایی با واژگان بسته. روش استاندارد پیش از سال 2020.
  • تولید متن (Generation). با دریافت گفتگو، مقادیر اسلات‌ها را به صورت متن آزاد تولید می‌کند. مناسب برای اسلات‌هایی با واژگان باز. رویکرد پیش‌فرض امروزی.

معیار ارزیابی. دقت هدف مشترک (Joint Goal Accuracy یا JGA) — یعنی نسبت دورهایی از گفتگو که در آن‌ها همه‌ی اسلات‌ها کاملاً درست باشند؛ قانونی با منطق صفر و یک. در سال 2026، صدر جدول رتبه‌بندی MultiWOZ 2.4 حدود 83% است.

معماری‌ها.

  1. قاعده‌محور (رجکس اسلات + کلمات کلیدی). بیس‌لاینی بسیار قوی برای دامنه‌های محدود. دیباگ کردن آن ساده است.
  2. TripPy / BERT-DST. روش تولید مبتنی بر کپی (Copy-Based) با انکودر BERT. استاندارد دوران پیش از LLMها.
  3. LDST (مدل LLaMA + LoRA). مدل زبانی آموزش‌دیده با دستورالعمل (Instruction-Tuned) همراه با پرامپت‌های دامنه-اسلات. روی MultiWOZ 2.4 به کیفیتی در سطح ChatGPT می‌رسد.
  4. بدون هستی‌شناسی (Ontology-Free، سال‌های 2024–2026). شِما را کنار می‌گذارد؛ نام‌ها و مقادیر اسلات‌ها را مستقیماً تولید می‌کند و از پس دامنه‌های باز برمی‌آید.
  5. پرامپت + خروجی ساختاریافته (2024–2026). مدل زبانی در ترکیب با شمای Pydantic و دیکودینگ مقید (Constrained Decoding). با 5 خط کد آماده‌ی استفاده در پروداکشن می‌شود.

الگوهای شکست کلاسیک

  • ارجاع به گزینه‌های قبلی (Co-reference) در طول گفتگو. «بریم همون گزینه‌ی اول.» سیستم باید تشخیص دهد منظور دقیقاً کدام گزینه است.
  • بازنویسی در برابر الحاق (Over-write vs Append). کاربر می‌گوید: «ایتالیایی رو هم اضافه کن.» آیا باید نوع غذا جایگزین شود یا به فهرست قبلی اضافه گردد؟
  • تأییدهای ضمنی. «اوکی عالیه» — آیا این یعنی پیشنهاد رزرو قبول شد؟
  • اصلاح حرف‌های قبلی (Correction). «راستی، ساعتش رو بکن 7 عصر.» باید بدون پاک شدن بقیه‌ی اسلات‌ها، فقط زمان به‌روزرسانی شود.
  • ارجاع به گفته‌های قبلی خودِ سیستم. «آره، همونی که گفتی.» کدام مورد؟
ردیابی وضعیت گفتگووضعیت یک دیکشنری است
DIALOGUE STATE TRACKINGThree turns, three edits to one slot-value dictionary: price and area fill first, then a correction overwrites cheap with moderate, then cuisine arrives. Joint goal accuracy scores a turn only when every slot matches, which makes mid-dialogue corrections the hardest part of tracking.نوبت 1«جایی ارزان در شمال»نوبت 2«راستی، قیمتش متوسط باشد»نوبت 3«و ایتالیایی باشد»وضعیت گفتگوpriceareacuisinecheapmoderatenorthitalianJGA: نوبت تنها در صورت درستی همه اسلات‌ها شمرده می‌شود
سه نوبت، سه تغییر در یک دیکشنری اسلات-مقدار: ابتدا price و area پر می‌شوند، سپس یک تصحیح مقدار cheap را به moderate بازنویسی می‌کند و در نهایت cuisine اضافه می‌شود. دقت هدف مشترک (JGA) تنها زمانی به یک نوبت نمره می‌دهد که همه‌ی اسلات‌ها منطبق باشند؛ موضوعی که اصلاحات میان گفتگو را به سخت‌ترین بخش ردیابی تبدیل می‌کند.

پیاده‌سازی

مرحله‌ی 1: استخراج‌کننده‌ی قاعده‌محور اسلات

کد را در code/main.py ببینید. عبارات باقاعده (Regex) به همراه دیکشنری کلمات هم‌معنی، 70% از جملات استاندارد را در دامنه‌های محدود پوشش می‌دهند:

CUISINE_SYNONYMS = {
    "italian": ["italian", "pasta", "pizza", "italy"],
    "chinese": ["chinese", "chow mein", "noodles"],
}


def extract_cuisine(utterance):
    for canonical, synonyms in CUISINE_SYNONYMS.items():
        if any(syn in utterance.lower() for syn in synonyms):
            return canonical
    return None

این رویکرد خارج از واژگان استاندارد شکننده است؛ اما برای تأییدهای قطعی اسلات‌ها به‌خوبی کار می‌کند.

مرحله‌ی 2: حلقه‌ی به‌روزرسانی وضعیت

def update_state(state, utterance):
    new_state = dict(state)
    for slot, extractor in SLOT_EXTRACTORS.items():
        value = extractor(utterance)
        if value is not None:
            new_state[slot] = value
    for slot in NEGATION_CLEARS:
        if is_negated(utterance, slot):
            new_state[slot] = None
    return new_state

سه اصل پایدار که باید رعایت شوند:

  • هیچ‌وقت اسلاتی را که کاربر دست نزده ریست نکنید.
  • رد صریح («اصلاً نوع غذا مهم نیست») باید اسلات را پاک کند.
  • اصلاح از طرف کاربر («راستی...») باید مقدار قبلی را بازنویسی کند، نه این‌که به آن اضافه شود.

مرحله‌ی 3: ردیابی وضعیت با LLM و خروجی ساختاریافته

from pydantic import BaseModel
from typing import Literal, Optional
import instructor

class RestaurantState(BaseModel):
    cuisine: Optional[Literal["italian", "chinese", "indian", "thai", "any"]] = None
    area: Optional[Literal["north", "south", "east", "west", "center"]] = None
    price: Optional[Literal["cheap", "moderate", "expensive"]] = None
    people: Optional[int] = None
    day: Optional[str] = None


def llm_dst(history, llm):
    prompt = f"""You track the slot values of a restaurant booking across turns.
Dialogue so far:
{render(history)}

Update the state based on the latest user turn. Output only the JSON state."""
    return llm(prompt, response_model=RestaurantState)

ترکیب Instructor و Pydantic بازگرداندن یک آبجکت وضعیت معتبر را تضمین می‌کند. بدون دردسرهای رجکس، بدون ناهماهنگی با شِما و بدون اسلات‌های توهم‌شده.

مرحله‌ی 4: ارزیابی با معیار JGA

def joint_goal_accuracy(predicted_states, gold_states):
    correct = sum(1 for p, g in zip(predicted_states, gold_states) if p == g)
    return correct / len(predicted_states)

کالیبراسیون: سیستم در چه نسبتی از دورهای گفتگو همه‌ی اسلات‌ها را درست حدس می‌زند؟ بهترین سیستم‌ها روی MultiWOZ 2.4 در سال 2026 بین 80 تا 83 درصد هستند. سیستم درون‌دامنه‌ای شما باید روی واژگان محدود خودش از این مقدار فراتر برود، وگرنه بیس‌لاین LLM جلوتر از شما خواهد بود.

مرحله‌ی 5: مدیریت اصلاحات کاربر

CORRECTION_CUES = {"actually", "no wait", "on second thought", "change that to"}


def is_correction(utterance):
    return any(cue in utterance.lower() for cue in CORRECTION_CUES)

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

دام‌های رایج

  • هزینه‌ی بازتولید کل تاریخچه. اگر به LLM بسپارید که در هر دور کل وضعیت را دوباره تولید کند، در مجموع O(n2)O(n^2) توکن مصرف خواهد شد. طول تاریخچه را محدود کنید یا دورهای قدیمی‌تر را خلاصه کنید.
  • تغییر تدریجی شِما (Schema Drift). اضافه کردن اسلات‌های جدید پس از اتمام کار، داده‌های آموزشی قبلی را نامعتبر می‌کند. برای شمای خود حتماً نسخه‌بندی داشته باشید.
  • حساسیت به بزرگی و کوچکی حروف. تفاوت میان "Italian" و "italian" و "ITALIAN" — همه‌جا مقادیر را نرمال‌سازی کنید.
  • ارث‌بری ضمنی (Implicit Inheritance). اگر کاربر در دورهای قبلی گفته باشد «برای 4 نفر»، درخواست جدید برای ساعتی دیگر نباید تعداد نفرات را پاک کند. همیشه تاریخچه‌ی کامل را به سیستم بفرستید.
  • اسلات‌های متنی آزاد در برابر مجموعه‌های بسته. نام‌ها، زمان‌ها و آدرس‌ها به اسلات‌های متن آزاد نیاز دارند؛ اما نوع غذا و منطقه مجموعه‌های بسته‌ای هستند. در شِما هر دو نوع را ترکیب کنید.

استفاده‌ی کاربردی

استک سال 2026:

موقعیت رویکرد
دامنه‌ی محدود (یک یا دو قصد) قاعده‌محور + رجکس
دامنه‌ی گسترده، همراه با داده‌های برچسب‌دار مدل LDST (ترکیب LLaMA + LoRA روی داده‌های مشابه MultiWOZ)
دامنه‌ی گسترده، بدون داده‌ی برچسب‌دار، آماده‌ی پروداکشن ترکیب LLM + کتابخانه‌ی Instructor + شمای Pydantic
گفتاری / صوتی سیستم ASR + نرمال‌ساز + LLM-DST
جریان رزرو چنددامنه‌ای مدل زبانی هدایت‌شده با شِما همراه با مدل‌های مجزای Pydantic برای هر دامنه
حساس به قوانین و انطباق سیستم قاعده‌محور در وهله‌ی اول، LLM به‌عنوان پشتیبان همراه با جریان تأیید

پیاده‌سازی نهایی

این خروجی را با نام outputs/skill-dst-designer.md ذخیره کنید:

---
name: dst-designer
description: Design a dialogue state tracker — schema, extractor, update policy, evaluation.
version: 1.0.0
phase: 5
lesson: 29
tags: [nlp, dialogue, task-oriented]
---

Given a use case (domain, languages, vocab openness, compliance needs), output:

1. Schema. Domain list, slots per domain, open vs closed vocabulary per slot.
2. Extractor. Rule-based / seq2seq / LLM-with-Pydantic. Reason.
3. Update policy. Regenerate-whole-state / incremental; correction handling; negation handling.
4. Evaluation. Joint Goal Accuracy on a held-out dialogue set, slot-level precision/recall, confusion on the hardest slot.
5. Confirmation flow. When to explicitly ask the user to confirm (destructive actions, low-confidence extractions).

Refuse LLM-only DST for compliance-sensitive slots without a rule-based secondary check. Refuse any DST that cannot roll back a slot on user correction. Flag schemas without version tags.

تمرین‌ها

  1. ساده. ردیاب وضعیت قاعده‌محور را در code/main.py برای 3 اسلات (cuisine، area، price) بسازید. آن را روی 10 گفتگوی دستی آزمایش کنید و JGA را بسنجید.
  2. متوسط. همان دیتاست را با Instructor + Pydantic و یک LLM کوچک پیاده کنید. JGA را مقایسه کرده و سخت‌ترین دورهای گفتگو را بررسی کنید.
  3. سخت. هر دو روش را پیاده‌سازی و مسیریابی کنید: در حالت پیش‌فرض از روش قاعده‌محور استفاده کنید و اگر با اطمینان کمتر از 2 اسلات استخراج کرد، به سراغ LLM بروید. مقدار JGA ترکیبی و هزینه‌ی استنتاج به ازای هر دور گفتگو را بسنجید.

اصطلاحات کلیدی

اصطلاح در گفتار عامیانه معنای دقیق فنی
DST ردیابی وضعیت گفتگو نگهداری دیکشنری اسلات-مقدار در طول دورهای گفتگو.
Slot واحد نیت کاربر پارامتر نام‌گذاری‌شده‌ای که بک‌اند به آن نیاز دارد (مانند cuisine یا date).
Domain حوزه‌ی وظیفه رستوران، هتل، تاکسی — مجموعه‌ای از اسلات‌ها.
JGA دقت هدف مشترک نسبتی از دورهای گفتگو که همه‌ی اسلات‌ها در آن درست هستند؛ قانونی با منطق صفر و یک.
MultiWOZ بنچ‌مارک مرجع دیتاست چنددامنه‌ای WOZ؛ معیار استاندارد ارزیابی DST.
Ontology-free DST بدون شِما تولید مستقیم نام‌ها و مقادیر اسلات‌ها بدون فهرستی ثابت.
Correction «راستی...» دوری از گفتگو که در آن کاربر مقدار اسلاتی را که قبلاً پر شده بود بازنویسی می‌کند.

برای مطالعه‌ی بیشتر

خودآزمایی

به سؤال‌ها جواب بدهید تا ببینید چقدر از درس در ذهنتان مانده است.

  1. پیش از درسردیابی وضعیت گفتگو (DST) چه چیزی را در طول نوبت‌ها نگهداری می‌کند؟
  2. پیش از درسمعیار دقت هدف مشترک (JGA) چه چیزی را اندازه می‌گیرد؟
  3. حین درسچرا بازتولید کل وضعیت از روی تاریخچه در هر نوبت، تصحیحات کاربر را به‌صورت طبیعی مدیریت می‌کند؟
  4. حین درسکدام الگوی سال 2026 یک دیکشنری اسلاتِ با اعتبارسنجی قطعی را تنها در 5 خط کد ارائه می‌دهد؟
  5. حین درسچرا باید اسکیمای DST را نسخه‌بندی (Version) کرد؟
  6. پس از درسچرا سیستم DST برای دامنه‌های حساس به انطباق و قوانین باید در کنار استخراج LLM شامل بررسی‌های مبتنی بر قانون باشد؟
  7. پس از درسنگرانی هزینه‌ای در خصوص بازتولید وضعیت در هر نوبت از طریق LLM چیست؟
  8. پس از درسچرا قبل از اقدامات مخرب یا برگشت‌ناپذیر در بک‌اند، وجود جریان‌های تأیید صریح الزامی است؟

سؤالات متداول

چرا با وجود LLMها هنوز به DST نیاز داریم؟

چون سیستم‌های حساس مالی، رزرو و سلامت به متغیرهای قطعی و ساختاریافته نیاز دارند و خروجی‌های متنی آزاد مدل‌های زبانی برای صدا زدن مستقیم APIها قابل اطمینان نیستند.

معیار Joint Goal Accuracy (JGA) در ارزیابی DST چیست؟

یک معیار ارزیابی صفر و یکی است که نسبت دورهایی از گفتگو را می‌سنجد که در آن‌ها تمامی اسلات‌های وضعیت بدون هیچ خطایی به‌درستی استخراج شده باشند.

چرا در روش‌های مبتنی بر LLM بازتولید کل وضعیت از روی تاریخچه پیشنهاد می‌شود؟

چون اگر مدل به جای به‌روزرسانی افزایشی، وضعیت را هر بار از روی کل تاریخچه بازتولید کند، اصلاحات کاربر («در واقع ساعتش رو عوض کن») را به شکلی طبیعی و بدون باگ بازنویسی می‌نماید.

ما رو توی گوگل بیشتر ببین

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