حافظه خلاصهسازی مکالمه
توسعه عاملهای هوشمند (Agentic Ai) با Langchain و Langgraph
- Generate and update a running conversation summary.
- Combine a summary with recent messages for model context.
- Identify facts that should remain verbatim rather than summarized.
چرا خلاصهسازی حافظه؟
### مسئله
- در 5.2، `context window` بودجهٔ محدودی برای پیامها دارد.
- تاریخچهٔ کامل گفتگو با هر پیام بزرگتر میشود و ممکن است از بودجه عبور کند.
- `Conversation Summarization Memory` یعنی نگهداشتن یک `running summary` بههمراه چند پیام تازه.
```mermaid
flowchart LR
A["پیامهای قدیمی"] --> B["خلاصهٔ فشرده"]
C["پیامهای اخیر"] --> D["context مدل"]
B --> D
D --> E["پاسخ مدل"]
E --> C
```
**Builds on ← Context Window Management:** کاهش توکنهای قدیمی برای ماندن زیر سقف.
**Where this leads → Long-Term Memory Stores:** جداسازی اطلاعات پایدار از حافظهٔ کوتاهمدت.
**مثال:** بهجای ۳۰ پیام کامل، خلاصهٔ تصمیمها و ۲ پیام آخر به مدل داده میشود.
ساخت و بهروزرسانی خلاصه
### تعریف
`summary` گزارشی فشرده از اطلاعات مهم گفتگو است؛ در هر نوبت، خلاصهٔ قبلی با پیامهای جدید گسترش مییابد.
```mermaid
flowchart TD
A["summary موجود؟"] -->|خیر| B["ساخت خلاصه از گفتگو"]
A -->|بله| C["خلاصهٔ قبلی + پیامهای جدید"]
B --> D["فراخوانی مدل خلاصهساز"]
C --> D
D --> E["ذخیرهٔ summary جدید"]
E --> F["حذف پیامهای قدیمی"]
F --> G["نگهداشتن پیامهای اخیر"]
```
**منطق بهروزرسانی:** خلاصهٔ قبلی را دوباره از صفر نمیسازیم؛ آن را با پیامهای تازه امتداد میدهیم.
**مثال مرحلهای:**
1. خلاصهٔ قبلی: «کاربر Python میخواهد.»
2. پیام جدید: «برای پروژه از LangGraph استفاده میکنم.»
3. خلاصهٔ جدید: «کاربر Python میخواهد و پروژهاش با LangGraph است.»
**Builds on ← Conversation State:** `state` شامل `messages` و `summary` است.
ترکیب context برای مدل
### ورودی مؤثر مدل
a) `summary` = فشردهٔ پیامهای قدیمی
b) `recent_messages` = چند پیام آخر، بدون تغییر
display formula:
\[
\text{model\_context} = [\text{summary}] + \text{recent\_messages}
\]
**چرا این شکل؟**
- `summary` گذشتهٔ دور را با توکن کم نگه میدارد.
- پیامهای اخیر لحن، سؤال جاری و جزئیات دقیق را حفظ میکنند.
- ترتیب زمانی پیامهای اخیر باید باقی بماند.
**مثال کامل:**
- خلاصه: «کاربر پاسخهای کوتاه و Python میخواهد.»
- پیام 1: «یک تابع برای جمع بنویس.»
- پیام 2: «با type hint.»
- ورودی مدل: `[summary, پیام 1, پیام 2]`
- نتیجهٔ مورد انتظار: کد Python کوتاه با type hint.
```mermaid
flowchart LR
S[summary] --> I[model_context]
R1["پیام اخیر ۱"] --> I
R2["پیام اخیر ۲"] --> I
I --> M["مدل زبانی"]
```
**Where this leads → Tool Calling and Agent Loops:** مدل باید تصمیمهای تازه و ترجیحات کاربر را هنگام انتخاب ابزار ببیند.
واقعیتهای حساس به متن
### چه چیزی نباید خلاصه شود؟
برخی دادهها باید **verbatim**، یعنی دقیقاً با همان متن، نگه داشته شوند:
- شناسهها: `thread_id`, `user-123`
- نام ابزار، کلیدهای فیلد و نام متغیرها
- مقادیر عددی، واحدها، تاریخها و محدودیتها
- نقلقول، کد و قراردادهای دقیق
**قاعده:**
\[
\text{critical fact} \Rightarrow \text{verbatim storage}
\]
\[
\text{general context} \Rightarrow \text{summary storage}
\]
**مثال متضاد:**
- متن حساس: `thread_id = "user-123"` ✅ همانطور نگه دار.
- متن قابل فشردهسازی: «کاربر دربارهٔ حافظهٔ گفتگو سؤال کرد و سپس نمونهٔ Python خواست.» ✅ خلاصه کن.
- خطر: تبدیل `user-123` به «شناسهٔ کاربر»؛ سیستم ممکن است thread اشتباه را بازیابی کند.
**Builds on ← State و checkpoint:** شناسهٔ دقیق، state درست را به همان گفتگو وصل میکند.
```mermaid
flowchart TD
A["اطلاعات گفتگو"] --> B{"حساس به متن؟"}
B -->|بله| C["ذخیرهٔ verbatim"]
B -->|خیر| D["افزودن به summary"]
```
پیادهسازی راهبرد کامل
### الگوی اجرایی در Python
```python
def summarize_conversation(state: State):
summary = state.get("summary", "")
if summary:
summary_message = (
f"This is a summary of the conversation to date: {summary}\n\n"
"Extend the summary by taking into account the new messages above:"
)
else:
summary_message = "Create a summary of the conversation above:"
messages = state["messages"] + [HumanMessage(content=summary_message)]
response = model.invoke(messages)
delete_messages = [RemoveMessage(id=m.id) for m in state["messages"][:-2]]
return {"summary": response.content, "messages": delete_messages}
```
**ردیابی با 4 پیام:** `[m1, m2, m3, m4]`
- `state["messages"][:-2] = [m1, m2]`
- حذف: `RemoveMessage(id=m1.id)`, سپس `RemoveMessage(id=m2.id)`
- باقیمانده: `[m3, m4]`
- خروجی: `summary = response.content` و پیامهای باقیمانده
**تصمیم زمان اجرا:**
```mermaid
flowchart LR
A["افزودن پیام"] --> B["شمارش token"]
B -->|زیر آستانه| C["ارسال state فعلی"]
B -->|بالای آستانه| D["بهروزرسانی summary"]
D --> E["حذف قدیمیها"]
E --> C
```
**Where this leads → Long-Term Memory Stores:** facts پایدار را جدا ذخیره کن؛ summary برای حافظهٔ کوتاهمدت است.
بازگشت به دوره