Long-Term Memory Stores
توسعه عاملهای هوشمند (Agentic Ai) با Langchain و Langgraph
- Distinguish thread memory from cross-thread long-term memory.
- Store, namespace, retrieve, and update durable user facts.
- Use semantic search to retrieve relevant memories without leaking unrelated records.
چرا حافظه بلندمدت؟
**تفاوت اصلی**
- Thread memory: وابسته به `thread_id` و مناسب ادامه همان گفتوگو.
- Long-term memory: وابسته به `user_id` و قابل استفاده در threadهای جدا.
- مثال: «پاسخ کوتاه» در Thread A ذخیره میشود و در Thread B دوباره به کار میرود.
```mermaid
flowchart LR
A["Thread A"] --> B["Short-term state"]
C["Thread B"] --> D["Short-term state"]
B --> E["Long-term store"]
D --> E
E --> F["Relevant memories"]
F --> A
F --> C
```
فضای نام؛ مرز ایمنی
**جداسازی گامبهگام**
- گام ۱: دامنه u1 را انتخاب کن.
- گام ۲: رکورد m1 را فقط همانجا بنویس.
- گام ۳: جستوجو در u2 به رکورد u1 دسترسی ندارد.
- نتیجه: namespace یک مرز واقعی برای بازیابی است.
```mermaid
flowchart TD
U1["user_id: u1"] --> N1["memories / u1"]
U2["user_id: u2"] --> N2["memories / u2"]
N1 --> M1["dark mode"]
N2 --> M2["weekly report"]
Q["query: mode"] --> N1
Q -.-> X["رکوردهای u2 خارج از دامنه"]
```
ذخیره پایدار و دو رشته
**از پیام تا پاسخ**
- تشخیص: ترجیح پایدار است.
- ذخیره: `put(N, "m1", ...)`.
- بازیابی: `search(N, ...) → ["m1"]`.
- استفاده: افزودن `info` به `prompt`.
- نتیجه: سبک پاسخ با ترجیح ذخیرهشده هماهنگ میشود.
```mermaid
flowchart LR
A["پیام کاربر"] --> B{"واقعیت پایدار؟"}
B -->|بله| C["اعتبارسنجی"]
C --> D["store.put"]
B -->|خیر| E["فقط پاسخ"]
D --> F["Thread A تمام میشود"]
F --> G["Thread B جدید"]
G --> H["store.search"]
H --> I["افزودن حافظه مرتبط به prompt"]
```
پیادهسازی با LangGraph
**اجرای یک جستوجو**
- ۱. خواندن `runtime.context.user_id`.
- ۲. ساختن `("memories", "u1")`.
- ۳. اجرای `search(..., limit=3)`.
- ۴. اتصال مقدارهای `data`.
- ۵. افزودن اطلاعات به prompt پایه.
**پایداری**
`InMemoryStore` برای نمونه آموزشی مناسب است، اما با پایان فرایند پاک میشود. برای نگهداری بین اجراها از `RedisStore` یا `PostgresStore` استفاده کنید.
بهروزرسانی؛ هر چیزی حافظه نیست
**ذخیره یا عدم ذخیره؟**
- ذخیره: ترجیح پایدار و مفید، مانند «پاسخ کامل میخواهم».
- ذخیره نکن: درخواست موقتی، مانند «همین پاسخ را کوتاهتر کن».
- تعارض: مقدار قدیمی را با update یا جایگزینی اصلاح کن.
**حل تعارض گامبهگام**
- تشخیص کلید مشترک: `response_style`.
- تعیین مقدار تازه: `"detailed"`.
- اجرای update روی همان namespace.
- بررسی با search.
- نتیجه: ترجیح جدید جایگزین ترجیح قدیمی میشود.
**محدودیت semantic search**
شباهت معنایی برابر با تازگی یا درستی نیست. timestamp، version یا سیاست جایگزینی را کنار جستوجوی معنایی قرار دهید.
Back to course