مدیریتِ زمینه25 از 37
در درسِ «[فشردهسازی در کد](compaction-in-code)» راهِ ارزانترِ کوتاه کردنِ تاریخچهی یک عامل را دیدید: قدیمیترین نوبتها را دور بریزید و بقیه را کلمه به کلمه نگه دارید. این راه یک قاعده دارد که هرگز نباید بشکند. هر tool_use با tool_result که به آن جواب میدهد همراه است، وگرنه API درخواست را رد میکند. اینجا همین کوتاه کردن را مینویسید.
## ورودی
خطِ اول بودجه است. بعد برای هر پیام یک خط، از قدیمیترین: نقشش، چند توکن دارد، و چه نوع پیامی است (task، text، tool_use یا tool_result):
``text
budget 10000
user 1200 task
assistant 300 tool_use
user 4000 tool_result
assistant 200 tool_use
user 2500 tool_result
assistant 250 tool_use
user 3000 tool_result
assistant 150 tool_use
user 900 tool_result
`
پیامِ ۰ کار است. بعد از آن، تاریخچه از **نوبتها** ساخته شده است: یک پیامِ assistant، و بعد پیامِ user که به آن جواب میدهد. پیامهای ۱ و ۲ یک نوبتاند، ۳ و ۴ نوبتِ بعد، و همینطور تا آخر. فهرست همیشه با یک پیامِ user تمام میشود: جوابِ تازهترین نوبت، که مدل میخواهد بخواندش.
## آنچه باید بنویسید
trim(messages, budget) را کامل کنید. این تابع شمارهی پیامهایی را که باید بمانند برمیگرداند، یا None:
1. **پیامِ ۰، یعنی کار، را همیشه نگه دارید.**
2. **تازهترین نوبت را همیشه نگه دارید**، یعنی دو پیامِ آخر را.
3. **نوبتها را از قدیمیترین دور بریزید**، هر بار یک نوبتِ کامل: اول پیامهای ۱ و ۲، بعد ۳ و ۴، و همینطور.
4. **به محضِ اینکه پیامهای مانده جا شدند، بایستید**: یعنی جمعِ توکنهایشان بودجه یا کمتر شد. بیشتر از لازم دور نریزید.
5. **اگر حتی پیامِ ۰ و تازهترین نوبت از بودجه بیشترند**، None برگردانید.
در نمونهی بالا، کلِ تاریخچه ۱۲٬۵۰۰ توکن است. دور ریختنِ قدیمیترین نوبت (پیامهای ۱ و ۲) آن را به ۸٬۲۰۰ میرساند که جا میشود، پس خروجی این است:
`text
dropped: 1 2
kept: 0 3 4 5 6 7 8 (8,200 tokens)
`
main این را از فهرستی که برمیگردانید چاپ میکند، و برای None عبارتِ cannot fit را چاپ میکند.
<details>
<summary>یک راهنمایی، اگر گیر کردید</summary>
با kept = list(range(len(messages))) شروع کنید. تا وقتی پیامهای مانده از بودجه بیشترند و هنوز نوبتِ قدیمیای برای دور ریختن هست (بیشتر از سه پیام مانده)، دو شمارهی درست بعد از کار را حذف کنید: del kept[1:3].
</details>
ببینید چرا دور ریختنِ نوبتهای کامل برای معتبر ماندنِ تاریخچه کافی است. هر tool_result در همان پیامِ user است که درست بعد از پیامِ assistant دارندهی tool_use آن میآید، پس حذفِ هر دو با هم هرگز یکی را بیدیگری نمیگذارد، و نقشها هنوز نوبتیاند: user، assistant، user`.
ورود برای امتحان این تمرین.