در دنیای توسعه عاملهای هوش مصنوعی، لحظاتی پیش میآید که سیستم تقریباً مرتکب یک اشتباه مهلک میشود و موفقیت کاذب را به عنوان حقیقت میپذیرد. اخیراً عامل هوش مصنوعی ما که سیستم حافظه vecmory را میساخت، نزدیک بود نتیجهای درخشان را گزارش دهد که در واقع یک سراب بود. در آخرین لحظه، او با حافظه خود مشورت کرد و رکوردی از جلسه قبلی پیدا کرد: این ایده قبلاً روی دادههای واقعی آزمایش شده بود و شکست خورده بود. عامل قبل از ارسال گزارش، خود را متوقف کرد. این یک داستان تبلیغاتی نیست – این یک لاگ است. در زیر دو لاگ متوالی از این دست آورده شده است، و در دومی، حافظه ما را مجبور کرد ویژگیای را که به آن افتخار میکردیم، کنار بگذاریم. ما در حال نوشتن vecmory هستیم – «حافظه مبتنی بر معنا» برای عامل هوش مصنوعی. این مربوط به جستجوی برداری نیست (که همه دارند)، بلکه در مورد این است که عامل دوبار روی یک چنگک پا نگذارد.
صحنه اول: مسیریاب که «۰.۹۸ را نشان داد»
در یکی از جلسات، عامل پیشنهاد بهبود رتبهبندی نتایج را داد. ایده: ساخت یک مسیریاب که بر اساس درخواست تصمیم میگیرد با چه چیزی رتبهبندی کند – با کسینوس خالص یا روش گرافی (Personalized PageRank). یک بنچمارک مصنوعی جمعآوری کرد. همبستگی پیشبین با انتخاب ایدهآل: ۰.۹۸. تقریباً عالی. فقط گزارش دادن و ادغام کردن باقی مانده بود.
قبل از گزارش، عامل یک یادآوری از حافظه خود انجام داد. و رکوردی از جلسه قبلی پیدا کرد: همین ایده قبلاً روی دادههای واقعی آزمایش شده بود – و شکست خورده بود. سؤال منطقی: چرا اصلاً شروع به ساختن آن کرد – مگر حافظه سر جایش نبود؟ چون یادآوری معنایی است و آنچه بالا میآید به درخواست بستگی دارد. در ابتدا درخواست گسترده بود – «بهبود رتبهبندی» – که یادداشتهای سطح بالا و مرکزی درباره رتبهبندی کلی را بالا میآورد، و یادداشت خاص «این مسیریاب خاص قبلاً آزمایش شده و شکست خورده» زیر آنها دفن میشد. فقط زمانی بالا آمد که زمینه کاری به چیزی خاص محدود شد – «مسیریاب توزیع کسینوس، PPR در مقابل کسینوس، ۰.۹۸»: یادآوری روی این متن بالاخره آن را گرفت. حافظه ساکت نبود – دقیقاً زمانی بالا آمد که درخواست به اندازه کافی دقیق شد تا آن را بازیابی کند.
دادههای مصنوعی فقط به اندازهای صادق هستند که تعبیههای مصنوعی صادق هستند. و در MiniLM چندزبانه که ما بردارها را با آن محاسبه میکنیم، کسینوس در هندسهای کاملاً متفاوت از دادههای مصنوعی زندگی میکند. ما این را مستقیماً روی بدنه حافظه زنده خود (۲۴۶ گره) در حین نوشتن این مقاله اندازهگیری کردیم: جفتهای تصادفی و نامرتبط میانگین کسینوس ۰.۵۳ (p5–p95: ۰.۲۴–۰.۷۶) میدهند؛ نزدیکترین همسایههای واقعی میانگین ۰.۸۰ (p5–p95: ۰.۵۷–۰.۹۱)؛ و روی دادههای مصنوعی از بردارهای تصادفی، جفتهای نامرتبط روی ۰.۰۰ (±۰.۰۸) قرار دارند. تفاوت بلافاصله قابل مشاهده است. روی دادههای مصنوعی، «مشابه» با یک پرتگاه از «نامشابه» جدا شده است – هر آستانه معقولی به طور تمیز برش میخورد. روی دادههای واقعی، ابرهای «همسایهها» و «تصادفی» همپوشانی دارند: جفتهای تصادفی در صدک بالایی (۰.۷۶) بالاتر از همسایهها در صدک پایینی (۰.۵۷) قرار میگیرند. آستانهای که روی دادههای مصنوعی مانند چاقوی جراحی کار میکند، روی بردارهای واقعی درون ابر نویز تصادفی قرار میگیرد و چیزی را جدا نمیکند. رکورد در حافظه دقیقاً در مورد این بود: تعبیههای واقعی کسینوس پایه فشرده بالایی دارند، آستانه مطلق از دادههای مصنوعی قابل انتقال نیست – باید به رتبه (top-k) تکیه کرد، نه به آستانه. عامل یادداشت خود را خواند و ایده را کشت – قبل از اینکه بنویسد «تمام شد، همبستگی ۰.۹۸».
صحنه دوم: عامل، ویژگی خودش را دور انداخت
مورد دوم همان الگو است، اما دردناکتر: حافظه ما را مجبور کرد ویژگیای را که قبلاً در README تحسین کرده بودیم، دور بیندازیم. بهطور پیشفرض، vecmory نتایج را نه تنها بر اساس شباهت کسینوسی، بلکه با افزودن «اهمیت» گره — یعنی درجه ورودی آن در گراف (تعداد رکوردهایی که به آن ارجاع میدهند) — رتبهبندی میکرد. منطق زیبایی داشت: یک واقعیت مرکزی که بارها به آن اشاره شده، بالاتر ظاهر میشود. ما این را بهعنوان پیشفرض پیادهسازی کردیم. سپس آن را اندازهگیری کردیم. نه recall@k (که مربوط به دقت جستجو است)، بلکه دقیقاً کیفیت رتبه را روی جفتهای واقعی «پرسش → پاسخ صحیح»: کسینوس خالص: MRR 0.81؛ ترکیب «هوشمند» ما با اهمیت: MRR 0.41. اهمیت، پاسخهای دقیق را غرق میکرد. یک واقعیت خاص و نادر که هیچکس به آن ارجاع نمیدهد، زیر «هابهای» رایج و پرکاربرد دفن میشد.
بعد از آن، جالبتر شد. روی یک گراف «پیر شده» مصنوعی با هابهای آشکار، همه چیز برعکس بود: کسینوس هاب را دفن کرد (MRR 0.033)، در حالی که اهمیت آن را بیرون کشید (تا 1.0). یعنی علامت سودمندی اهمیت به هدف پرسش بستگی دارد: برای «یک واقعیت دقیق به من بده» مضر است، برای «درباره این موضوع به طور کلی به من بگو» مفید است. هیچ وزن ایستای واحدی که هر دو کلاس را برنده کند وجود ندارد. ما چهار روش برای آشتی دادن سیگنالها امتحان کردیم — مجموع وزنی، گیت، RRF و PPR — و به یک نتیجه ناخوشایند رسیدیم: مسئله به فرمول ترکیب مربوط نیست، بلکه به خود سیگنال مربوط است. اهمیت سراسری گره یک اولویت محبوبیت است، نه مرتبط بودن. نتیجه برای پیشفرض واضح بود: برای مورد استفاده اصلی ما (بازیابی نقطهای)، بهترین رتبهبندی کسینوس خالص است. و ما اهمیت را از رتبهبندی پیشفرض حذف کردیم — ویژگی خودمان را که قبلاً در README دربارهاش نوشته بودیم. روش گرافی (PPR مبتنی بر پرسش) را نگه داشتیم، اما بهعنوان یک گزینه، نه پیشفرض: این روش صادقانه هابها را در پرسشهای گسترده بیرون میکشد و بهدرستی در پرسشهای نقطهای به کسینوس میبازد.
واقعاً چه چیزی درباره «اهمیت» فهمیدیم
اگر محبوبیت سراسری (درجه ورودی) بهعنوان یک سیگنال شکست خورد، سیگنال درست چیست؟ ما به پ réponse بهطور شگفتآوری واضح رسیدیم: مهم نیست که چه چیزی ارجاعات زیادی دارد، بلکه مهم چیزی است که انسان بهطور مکرر آن را تصحیح کرده است. و اینجاست که ارزش پیشنهادی صادقانه میشود. ما «حافظه گرافی» نمیفروشیم (باز هم یک کالای عمومی). ما میفروشیم: عامل دیگر به همان چالههایی که قبلاً اصلاح کردهای، نمیخورد.
هر دو قسمت را میتوان به راحتی به شانس نسبت داد. اما وقتی به اندازه کافی طولانی آشغالهای حافظه را پاک میکنید (ما کل توسعه vecmory را در خود vecmory انجام میدهیم)، مشخص میشود: این نوسانات نیستند، بلکه چند قانون پایدار هستند. اکنون خلاصهای میآید — با سه مکاشفه، بدون داستانهای «یک بار افتادم توی…».
قانون «قبل از «تمام شد» بررسی کن»
حافظهای که آنچه را برایت خوشایند است تأیید میکند، حافظه نیست، بلکه پژواک است. حافظه زمانی ارزش استثنایی پیدا میکند که با نویسنده خود مخالفت کند. قانون «قبل از «تمام شد» بررسی کن» هم روتر (صحنه ۱) و هم ویژگی مورد انتظار ما (صحنه ۲) را لغو کرد — یک مکانیسم، قربانیان متفاوت. زیرا در پاسخ به یک پرسش-علامت، حافظه از طریق یالهای علّی-زمانی (caused_by — «ناشی از»، followed_by — issue→PR) نه «کلمات مشابه»، بلکه علت خاص و رفعکننده قبلی را بیرون میکشد. top-k مسطح این کار را بلد نیست — این همان «نقطهچینها را به هم وصل کردن» است.

چه چیزی به طور مداوم مانع میشود — هر بار، نه یکبار
اولاً، عامل خودش حافظه را فراخوانی نمیکند: بدون هوک اجباری، recall به طور سیستماتیک و در هر جلسه فراخوانی نمیشود. حافظهای که باید «فراموش نکنی بپرسی» کار نمیکند — پرسش باید توسط یک محرک قطعی انجام شود، نه حسن نیت عامل. ثانیاً، آستانه مطلق کسینوس در هیچ جایی قابل انتقال نیست: مصنوعی → واقعی، دیروز → امروز، یک مدل → مدل دیگر، پیکره گسترده → محدود (در پیکره نمایشی یک دامنه که «همه چیز شبیه است»، کسینوس تقریباً قادر به تمایز نیست). درمان همیشه یکسان است: top-k را رتبهبندی کن، آستانهها را حدس نزن.
قانون «سیگنال پرتکرار، سیگنال نادر اما ارزشمند را غرق میکند»
یک قانون که نیمی از مشکلات ما را توضیح میدهد: سیگنال پرتکرار و متراکم، سیگنال نادر اما ارزشمند را غرق میکند. این قانون در سه مکان معمولی ظاهر میشود: محبوبیت جهانی یک گره، حقایق نادر دقیق را غرق میکند — و هر چهار روش ترکیب آن با رتبه (مجموع وزنی، گیت، RRF، PPR) را با شکست مواجه میکند؛ گرههای هاب، حقایق خاص را در رتبه کسینوس دفن میکنند و بالعکس؛ یالهای متراکم auto-similar_to، یالهای علی نادر caused_by را خفه میکنند — به همین دلیل recall علی باید به یک حالت جداگانه و ایزوله منتقل شود. وقتی این را به عنوان یک قانون واحد درک کنید، درمان آشکار است: نادر-اما-ارزشمند را نمیتوان با پرتکرار-اما-عمومی مخلوط کرد — آن را با یک مکانیزم جداگانه (پیمایش ایزوله، رتبه آگاه از گراف) بیرون بکشید، نه اینکه امیدوار باشید خودش در top-k عمومی ظاهر شود. همین قانون پشت سیگنال اهمیت ما نیز قرار دارد: ارزش مربوط به چیز محبوب نیست، بلکه به چیزی است که انسان به طور مکرر اصلاح کرده است.
سوالات متداول
vecmory چیست؟
Vecmory یک سیستم حافظه معنایی برای عاملهای هوش مصنوعی است که بر پایه جستجوی برداری و گراف علی-زمانی ساخته شده است. این سیستم به عامل اجازه میدهد حقایق را به خاطر بسپارد، آنها را بر اساس معنا به یاد آورد و رویدادها را به هم مرتبط کند تا اشتباهات گذشته تکرار نشوند.
vecmory چه تفاوتی با جستجوی برداری معمولی دارد؟
جستجوی برداری ورودیهای مشابه از نظر معنا را پیدا میکند، اما روابط علت و معلولی را در نظر نمیگیرد. Vecmory حافظه گرافی را اضافه میکند: علاوه بر نزدیکی کسینوسی، یالهای «علت-معلول» و «توالی زمانی» را پیمایش میکند، که امکان یافتن حقایق نه فقط مشابه، بلکه مرتبط با زمینه را فراهم میکند — برای مثال، یک آزمایش ناموفق قبلی.
چرا اهمیت گره را از رتبهبندی حذف کردید؟
چگونه کیفیت حافظه را ارزیابی میکنید؟
اندازهگیریها نشان داد که افزودن محبوبیت جهانی (درجه ورودی) MRR را از 0.81 به 0.41 در پرسوجوهای نقطهای کاهش میدهد. اهمیت حقایق دقیق نادر زیر انبوهی از حقایق محبوب اما نامرتبط دفن میشود. برای مورد اصلی (بازیابی دقیق)، کسینوس خالص بهتر عمل کرد.
چگونه کیفیت حافظه را ارزیابی میکنید؟
ما از دادههای واقعی استفاده میکنیم: یک مخزن GitHub با 4299 تیکت، که در آن جفتهای issue→PR با الگوی Closes #N استخراج میشوند. در 300 پرسوجوی علامتی، بازیابی گراف 87% دقت در مقابل 38% برای کسینوس خالص ارائه میدهد. همه اسکریپتها باز و قابل تکرار هستند.
نتیجهگیری
هر دو داستان درباره یک چیز هستند: مانترای «حافظه به عامل کمک میکند» را دور بینداز و بیدار شو: اینجا دو لاگ وجود دارد که در آن حافظه علیه خود ما عمل کرد – علیه خوشبینی ما و علیه ویژگی خودمان. عامل با حافظه با عامل بدون حافظه تفاوت ندارد در اینکه بیشتر میداند، بلکه در این است که میتواند خود را در لحظه «bingo!» درست یک لحظه قبل از گزارش فریبنده بگیرد – چون دفعه قبل این اتفاق افتاده و جواب نداده است. و در این است که آماده است ویژگی خود را دور بیندازد وقتی حقایق نشان میدهند که بدتر است. این اولین مقاله از سه مقاله است. بعدی: «چرا ما یک Bad CaRMa دیگر ننوشتیم» – درباره اینکه چگونه یک مدل داده فوقالعاده جهانی معمولاً به فاجعه تبدیل میشود، و ما چه کردیم تا مدل ما تبدیل نشود. و «ANN را با دست ساختیم – چه زمانی ارزشش را داشت و چه زمانی نه» – بررسی باز درباره اینکه چرا اصلاً HNSW را خودمان نوشتیم و در چه مواردی پاسخ صحیح «pgvector را بردار و لوس نکن» بود. اگر میخواهید عامل شما دیگر روی همان چنگکها پا نگذارد، vecmory را امتحان کنید: با مستندات ما شروع کنید یا مخزن را فورک کنید. حافظهای که مخالفت میکند، تنها حافظهای است که میتوان به آن اعتماد کرد.

Leave a Reply