چیتشیت
مهندسی بافتار و حافظه ایجنت
Context Engineering and Agent Memory
بودجهبندی پنجره، ترتیبدهی بافتار، صفحهبندی حافظه به داخل و خارج، تلفیق مخازن حافظه و پایدارسازی وضعیت ایجنت.
فهرست مطالب
بودجهبندی پنجرهی بافتار
معماریاعدادی که اهمیت دارند
مفهومها- گم شدن در میانه (Lost in the middle)
- دقت 85 تا 90 درصد وقتی سند در ابتدا یا انتها باشد؛ دقت 60 تا 70 درصد در موقعیت 10 از 20.
- منطقهی افت
- موقعیتهای 40 تا 70 درصدی بافتار، 10 تا 20 درصد از دقت را از دست میدهند.
- گلچینشده بهتر از فلهای است
- یک بافتار 10 هزار توکنی گلچینشده اغلب از یک بافتار 100 هزار توکنی خام و فلهای بهتر عمل میکند.
- هزینهی ابزار
- 50 تا 200 توکن به ازای هر ابزار. 50 ابزار با میانگین 150 توکن معادل 7,500 توکن است.
- هرس کردن ابزارها
- توکنهای ابزار را 60 تا 80 درصد کاهش میدهد.
- تاریخچه
- 50 نوبت گفتوگو با میانگین 200 توکن یعنی 10,000 توکن.
- خلاصهسازی
- 100 توکن جایگزین 10 نوبت گفتوگو میشود که قبلاً 2,000 توکن فضا میگرفتند.
- تخمین توکن
- تعداد کلمات ضربدر 1.3 در
count_tokens.
سرهمبندی بافتار بر اساس هر پرسش
گامبهگام- طبقهبندیکنندهتابع
classify_intent(query)تعداد تطابق کلمات کلیدی را در هر نیت میشمارد. در صورت عدم تطابق، خروجی["code"]خواهد بود. - انتخابگر ابزارتابع
select_tools(query, token_budget=2000)ابزارهایی را که دستهبندی آنها مطابقت دارد نگه میدارد. - بازیابتابع
score_relevance(query, documents)میزان همپوشانی کلمات را امتیازدهی میکند. اسناد پایینتر ازthresholdحذف میشوند. - بازترتیبتابع
reorder_lost_in_middle(items, scores)بهترین آیتمها را در ابتدا و انتها قرار میدهد. - تاریخچهتا زمانی که تاریخچه فراتر از سقف باشد،
ConversationManagerدو نوبت گفتوگوی قدیمیتر را خلاصه میکند. - بودجهکلاس
ContextBudgetهر بخش را متناسب با سقف آن و فضای باقیمانده کوتاه میکند.
ContextEngine.assemble
کدpython
budget = ContextBudget(max_tokens=128000, generation_reserve=4000)
budget.allocate("system_prompt", self.system_prompt, max_tokens=1000)
tools, tool_tokens = select_tools(query, token_budget=2000)
budget.allocate("tools", tool_text, max_tokens=2000)
budget.allocate("retrieved_context", doc_text, max_tokens=3000)
budget.allocate("conversation_history", history_text, max_tokens=5000)
budget.allocate("user_query", query, max_tokens=500) # پرسش در انتها قرار میگیرد
print(budget.report()) # توکنها و درصد به ازای هر مؤلفه
سطح ابزار حافظه (Memory tool surface)
دستورها| دستور | کاری که انجام میدهد |
|---|---|
core_memory_append(section, text) | در بخش پینشدهی پرامپت مینویسد |
core_memory_replace(section, old, new) | یک بخش پینشده را ویرایش میکند |
archival_memory_insert(text) | در مخزن خارجی قابل جستوجو مینویسد |
archival_memory_search(query, top_k) | فکتها را برای نوبت گفتوگوی بعدی دوباره به بافتار بازمیگرداند (صفحهبندی به داخل) |
conversation_search(query) | نوبتهای گفتوگوی گذشته، از جمله نوبتهای بیرونراندهشده (evicted) را اسکن میکند |
block_append(label, text) | متن را به یک بلوک حافظه اضافه میکند |
block_replace(label, old, new) | یک بلوک حافظه را ویرایش میکند |
block_summarize(label) | بلوکی را که نزدیک به حد نصاب سقف خود باشد فشرده و خلاصه میکند |
مقایسهی رویکردهای طراحی حافظه در کنار هم
مقایسه| عامل | مدل دو سطحی MemGPT | بلوکهای Letta | مدل ترکیبی Mem0 | حافظهی مخزن (Repo memory) |
|---|---|---|---|---|
| مخازن | بافتار اصلی بهعلاوهی آرشیو | هسته (core)، بازخوانی (recall)، آرشیو | برداری، KV و گراف | فایلهای JSON تحت یک اسکیما |
| نوشتن | فراخوانی ابزار حافظه | ابزارهای مبتنی بر بلوک و بازنویسی در محاسبات زمان خواب | فراخوانی add(text, user_id, metadata) روی هر سه مخزن | اعتبارسنجی و سپس نوشتن اتمیک |
| خواندن | archival_memory_search | بلوکهای هسته درون پرامپت باقی میمانند | تابع search(query, user_id) امتیازها را تلفیق میکند | بارگذاری و اعتبارسنجی |
| فکتهای بیات و منسوخ | یکپارچهسازی نودها، بیاعتبارسازی | ایجنت محاسبات زمان خواب آنها را بیاعتبار میکند | یال قدیمی نامعتبر علامتگذاری میشود، نه اینکه حذف شود | فلگ schema_version فایلهای ناشناخته را رد میکند |
| ریسک اصلی | پوسیدگی حافظه، مسمومسازی حافظه | باد کردن بلوک، دریفت بیصدا | انحراف امبدینگ، انفجار ابعاد گراف | نوشتنهای ناقص و نیمهکاره |
| زمان استفاده | حجم دادهها بزرگتر از پنجره باشد | برخی فکتها حتماً باید داخل پرامپت بمانند | پرسشها ترکیبی از شباهت، جستوجوی مستقیم و روابط باشند | وضعیت باید بیشتر از نشست چت زنده بماند |
وظایف در قالب کد
کار و کد| وظیفه | کد |
|---|---|
| ایجاد یک بلوک | create(label, description, limit=300) |
| بررسی شرایط بلوک برای خلاصهسازی | block.near_limit() |
| یکپارچهسازی خارج از مسیر بحرانی | sleep.run(contradictions=[...]) |
| حذف نرم (soft delete) یک فکت بیات | self.archival.invalidate(record.rid) |
| نوشتن در هر سه مخزن | mem.add(text, user_id=..., kv_triples=...) |
| جستوجوی تلفیقی با تعیین دامنه | mem.search(query, user_id=..., top_k=3) |
| پایدارسازی امن وضعیت | atomic_write(path, content) |
| رد کردن یک نوشتن نامعتبر | `mgr.commit(state)` raises `SchemaError` |
پروژهی سرور حافظه
دستورها| دستور | کاری که انجام میدهد |
|---|---|
python3 scripts/project_test.py memory-server --init <dir> | میز کار شما را میسازد. کد اولیهی دستنخورده با شکست مواجه میشود |
python3 scripts/project_test.py memory-server --all --path <dir> --strict | هر چهار مرحله را نمرهدهی و ارزیابی میکند |
node cli.ts --data-dir memory-data --put samples/memory.json | نسخهی 1 از cache-policy را اضافه میکند |
node cli.ts --data-dir memory-data --query "cache policy" | فضای نام docs را جستوجو میکند |
node cli.ts --data-dir memory-data --put samples/memory-updated.json --revision 1 | نسخهی 2 را اضافه میکند. ثبت مجدد نسخهی 0 منجر به خطا و تداخل میشود |
node cli.ts --data-dir memory-data --history cache-policy --html history.html | تمام نسخهها را چاپ کرده و یک جدول مقایسهای مینویسد |
node cli.ts --data-dir memory-data --serve --port 8788 | سرویسدهی از طریق REST و MCP؛ ابتدا مقدار MEMORY_TOKEN را تنظیم کنید |
پیشفرضها
پیشفرضها| تنظیم | پیشفرض | توضیح |
|---|---|---|
max_tokens | 128000 | منهای 4000 توکن سهم generation_reserve |
max_history_tokens | 5000 | نوبتهای گفتوگوی قدیمی بالاتر از آن خلاصه شوند |
token_budget | 2000 | سقف برای تعریف ابزارها |
Relevance `threshold` | 0.05 | نسخهی استفادهشده در مستندات از 0.1 استفاده میکند |
max_messages | 4 | بافتار اصلی MemGPT؛ پیامهای قدیمیتر به evicted منتقل میشوند |
Block `limit` | 300 | بر حسب کاراکتر؛ آستانهی near_limit روی 0.8 فعال میشود |
w_relevance | 0.6 | ضریب w_importance برابر 0.2 و w_recency برابر 0.2 |
recency_halflife_s | 86400.0 | میزان تازگی به ازای هر نیمهعمر 0.5 است |
عیبیابی
عیبیابیمدل یک فکت در میانه را نادیده میگیرد
- علت
- گم شدن در میانه (Lost in the middle)
- راهحل
- فکتهای کلیدی در ابتدا و پرسش در انتها قرار گیرد. نکتهی اصلی را در پایان تکرار کنید
ابزارها کل پنجره را پر میکنند
- علت
- ارسال همهی ابزارها در تکتک فراخوانیها
- راهحل
- نیت را طبقهبندی کرده و ابزارها را هرس کنید
بازیابی در میان فکتهای بیات غرق میشود
- علت
- پوسیدگی حافظه
- راهحل
- یکپارچهسازی نودها و بیاعتبارسازی در فاز پردازش زمان خواب
ایجنت از یک یادداشت تزریقشدهی قدیمی اطاعت میکند
- علت
- مسمومسازی حافظه
- راهحل
- با حافظهی بازیابیشده مانند متن غیرقابل اعتماد رفتار کنید
ایجنت موضوع را به یاد میآورد اما نمیتواند به منبع ارجاع دهد
- علت
- از دست رفتن ارجاع (Citation loss)
- راهحل
- شناسهی نشست و شناسهی نوبت گفتوگو را در هر نوشتن ذخیره کنید
بلوک به سقف تعیینشده میرسد
- علت
- باد کردن بلوک
- راهحل
- قبل از عملیات نوشتنی که باعث رد شدن از سقف میشود خلاصهسازی کنید
یک کاربر فکتهای مربوط به کاربر دیگری را میبیند
- علت
- تداخل و ادغام دامنهها
- راهحل
- برای هر بار نوشتن یک دامنهی مشخص تعیین کنید
نشست روی یک وضعیت مخدوش از سر گرفته میشود
- علت
- نوشتن غیراتمیک
- راهحل
- استفاده از فایل موقت،
fsyncوos.replace
پرسشها
پرسش و پاسخ- پنجرهی بزرگتر، بدون نیاز به حافظه؟
- خطوط مبنا با پنجرهی 128 هزار توکنی باز هم فکتهای دوردست در افق زمانی طولانی را از دست میدهند، در حالی که یک ایجنت با پنجرهی 4 هزار توکنی مجهز به حافظهی خارجی آنها را پیدا میکند.
- چرا محاسبات زمان خواب؟
- نوبتهای گفتوگوی اصلی معطل نمیمانند. ایجنت زمان خواب میتواند از مدلی قویتر و کندتر استفاده کند.
- چرا سه مخزن؟
- یک مخزن واحد برای دو مورد از سه دستهی اصلی پرسشها پاسخگوی نیاز نیست.
- رتبهبندی تلفیقی چگونه کار میکند؟
- یک مجموع وزندار از میزان ارتباط، اهمیت و تازگی؛ که وزنها بر اساس نوع محصول تغییر میکنند.
- چه چیزهایی داخل حافظهی مخزن قرار میگیرد؟
- شناسهی وظیفه، فایلهای تغییریافته، فرضیات، موانع و اقدام بعدی؛ نه متن خام رونوشت گفتوگوها.