بسیاری از تیمها هنوز اولین خط لوله بازیابی (retrieval pipeline) خود را به همان روش قدیمی میسازند. آنها یک محدودیت توکن ثابت، مثلاً ۵۱۲، انتخاب میکنند، اسناد را به بلوکهای یکسان تقسیم میکنند و آن بلوکها را به یک پایگاه داده برداری (vector database) میفرستند. در یک مجموعه داده کوچک با سوالات ساده، این روش جادویی به نظر میرسد، اما در محیط عملیاتی (production)، از هم میپاشد.
قراردادهای حقوقی وقتی یک بند در میان جمله بریده میشود، به قطعات بیمعنی تبدیل میشوند. مستندات API اگر یک تکه (chunk) سه تابع بیارتباط را در خود جای دهد، به مجموعهای از اطلاعات نویزدار تبدیل میشود. تیکتهای پشتیبانی مشتری بدون همپوشانی (overlap) بین بخشها، تمام رشتهی روایت خود را از دست میدهند. نتیجه قابل پیشبینی است: تأخیر (latency) زیاد، بازیابی (recall) ضعیف و پاسخهایی که مدل مولد را مجبور به توهم (hallucination) میکنند.
ما لایه بازیابی خود را از هم باز کردیم و دوباره آن را ساختیم. نتیجه، جهش در میزان recall از ۷۸ درصد به ۹۵ درصد، کاهش ۶۲ درصدی در latency و خط لولهای بود که بالاخره به جای یک کد سرهمبندی شدهی آخر هفته، مانند یک زیرساخت واقعی رفتار میکند. در اینجا آنچه واقعاً جواب داد را میخوانید.
تکهبندی هوشمند: ساختار بر توکنها اولویت دارد
اولین اشتباه این است که فرض کنیم هر سندی با زبان یکسانی صحبت میکند. یک تکه ۵۱۲ توکنی برای متنهای روایی منطقی است و تقریباً هیچ جای دیگر کاربرد ندارد. ما به سمت استراتژیای رفتیم که به آناتومی منبع احترام میگذارد.
برای اسناد حقوقی، ما از تکهبندی بازگشتی (recursive chunking) استفاده میکنیم. الگوریتم ابتدا سعی میکند بر اساس مرزهای سطح بالا مانند بخشها و مواد تقسیمبندی کند. اگر یک بخش هنوز خیلی طولانی باشد، به دنبال زیربخشها، سپس پاراگرافها و سپس جملات میگردد. این کار سلسلهمراتب منطقی بندها را حفظ میکند. یک توافقنامه عدم رقابت دستنخورده باقی میماند و تعاریف با شرایط غرامت (indemnity) مخلوط نمیشوند.
مستندات API نیازمند تکهبندی آگاه از ساختار (structure-aware chunking) هستند. امضای یک تابع، جدول پارامترهای آن و درخواست نمونهاش همگی باید در کنار هم باشند. تقسیمبندی بر اساس تعداد توکن ثابت، اغلب پارامترها را در یک تکه و مثالها را در تکهای دیگر رها میکند. در عوض، ما بر اساس شیء سند (document object) تکهبندی میکنیم. هر تکه شامل یک endpoint کامل یا یک تابع واحد است. سپس بازیاب (retriever) میتواند یک مرجع خودکفا را برگرداند که واقعاً به سوال پاسخ میدهد.
تیکتهای پشتیبانی به طور طبیعی با تکهبندی معنایی (semantic chunking) سازگار هستند. به جای برش در مرز توکنها، ما تشخیص میدهیم که موضوع کجا تغییر میکند. تیکتی که با شکایت از ورود به سیستم شروع شده و به سوالی درباره صورتحساب تغییر جهت میدهد، به دو بخش منسجم تقسیم میشود. هر بخش متادیتای مورد نیاز خود را به همراه دارد و مدل دیگر مجبور نیست حدس بزند کاربر واقعاً نگران کدام مشکل است.
ویکیهای داخلی آشفتهتر هستند. آنها ترکیبی از متن، جدول، نمودار و رشتههای گرهخورده هستند. برای این موارد، ما از تکهبندی عاملمحور (agentic chunking) استفاده میکنیم. یک مدل زبانی کوچک متن را پیشخوانی کرده و تصمیم میگیرد که یک واحد موضوعی کامل کجا پایان مییابد. این کار در زمان ورود داده (ingestion time) هزینه کمی بیشتر دارد، اما کارهای تکراری انسان برای تنظیم دستی قوانین برای هر فرمت صفحه جدید را حذف میکند.
بازیابی ترکیبی: تمام جوانب را پوشش دهید
جستجوی برداری (Vector search) در درک معانی مبهم عالی است. اگر درباره آپلودهای کند سوال کنید، با خوشحالی پاراگرافهایی درباره latency و پهنای باند برمیگرداند. اما در مدیریت تطبیقهای دقیق (exact matches) بدنام است. اگر توسعهدهندهای به دنبال کد خطای ERR_CONNECTION_REFUSED بگردد، embeddingهای متراکم (dense embeddings) اغلب با آن مانند یک نویز عمومی برخورد میکنند.
الگوریتم BM25، که یک الگوریتم کلاسیک مبتنی بر کلمات کلیدی است، دقیقاً برعکس عمل میکند. این الگوریتم رشتههای دقیق و اصطلاحات نادر را به خوبی پیدا میکند، اما ظرافتهای معنایی را از دست میدهد. پرسوجویی درباره «امضای قرارداد» ممکن است هرگز محتوایی را که با «اجرای قرارداد» برچسبگذاری شده است، پیدا نکند.
