تبدیل‌کننده سند

تابع تبدیل‌کننده سند در LangChain عمدتاً برای تقسیم محتوای متن به بخش‌های کوچکتر عمل می‌کند. این کار به دلیل این است که مدل‌های بزرگ معمولاً محدودیت‌هایی در خصوص طول دستورات دارند و نمی‌توانند تمام محتوا را به هوش مصنوعی ارائه دهند. حتی اگر برخی از مدل‌های بزرگ اجازه طول بسیار زیادی را بدهند، از نظر هزینه اقتصادی کاربردی نیست که محتوای طولانی را به هوش مصنوعی منتقل کنیم. با این حال، بالاترین هزینه تماس API (حتی برای مدل‌های منبع باز که محلی پیاده‌سازی شده‌اند، محتوای طولانی نیازمند حافظه GPU بیشتر و نتیجه‌گیری کند‌تر است) می‌شود. روش منطقی این است که قطعات مربوطه از محتوا را به عنوان اطلاعات پس‌زمینه و دستورالعمل‌ها هنگام درخواست مدل هوش مصنوعی پیوند کنیم.

LangChain دارای تعداد زیادی تبدیل‌کننده سند پیش‌فرض است که به راحتی محتوای سند را تقسیم، ترکیب و فیلتر می‌کنند.

جداکننده متن

زمانی که با بلوک‌های بزرگی از متن سر و کار داریم، باید متن را به بخش‌های کوچکتر تقسیم کنیم. هر چند که به نظر می‌آید ساده است، اما اینجا پیچیدگی‌های بسیاری وجود دارد. به طور ایده‌آل، می‌خواهید بلاک‌های مربوط به معنوی با هم در ارتباط باقی بمانند. اصطلاح «معنوی مرتبط» در اینجا ممکن است به متن بستگی داشته باشد.

از دید بالایی، جداکننده متن به شکل زیر عمل می‌کند:

۱. متن را به بلاک‌های کوچک معنوی تقسیم می‌کند (به طور معمول جملات). ۲. این بلاک‌های کوچک را به بلاک‌های بزرگتر ترکیب می‌کند تا به یک اندازه خاص برسد (با استفاده از برخی تابع‌ها). ۳. هنگامی که به این اندازه رسید، بلاک را به عنوان بخش متنی خودش در نظر می‌گیرد و شروع به ایجاد یک بلاک متنی جدید با یک اندازه انتقالی معین می‌کند (برای حفظ زمینه بین بلاک‌ها).

در نتیجه، می‌توانید جداکننده متن را به دو محور مختلف سفارشی‌سازی کنید:

۱. چگونگی تقسیم متن ۲. چگونگی اندازه‌گیری اندازه بلوک‌ها

مثال

جداکننده متن توصیه شده به صورت پیش‌فرض RecursiveCharacterTextSplitter است. این جداکننده متن یک لیستی از کاراکترها را قبول می‌کند. سعی می‌کند بر اساس اولین کاراکتر بلاک‌ها را ایجاد کند، اما اگر هر بلاک بسیار بزرگ باشد، ادامه می‌دهد تا به کاراکتر بعدی برسد و به همین ترتیب. به طور پیش‌فرض، کاراکترهایی که سعی در تقسیم آنها دارد، ["\\\\n\\\\n", "\\\\n", " ", ""] هستند.

علاوه بر کنترل کاراکترهای قابل تقسیم، می‌توانید بر خیلی موارد دیگر نیز کنترل داشته باشید:

  • length_function: چگونگی محاسبه طول یک بلاک. به طور پیش‌فرض، فقط تعداد کاراکترها شمرده می‌شود، اما معمولاً شمارنده‌های توکن در اینجا منتقل می‌شوند.
  • chunk_size: حداکثر اندازه بلاک‌های شما (بر اساس تابع طول).
  • chunk_overlap: حداکثر همپوشانی بین بلاک‌ها. حفظ یک حداقل همپوشانی می‌تواند در حفظ پیوستگی بین بلاک‌ها کمک کند (مانند انجام یک پنجره لغزان).
  • add_start_index: آیا باید جای شروع هر بلاک در سند اصلی را در متادیتا قرار دهد یا خیر.
with open('../../state_of_the_union.txt') as f:
    state_of_the_union = f.read()
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size = 100,
    chunk_overlap  = 20,
    length_function = len,
    add_start_index = True,
)
texts = text_splitter.create_documents([state_of_the_union])
print(texts[0])
print(texts[1])
page_content='..ignored text..' metadata={'start_index': 0}
    page_content='..ignored text..' metadata={'start_index': 82}

تبدیل‌های دیگر

فیلتر کردن سند تکراری، ترجمه سند، استخراج متادیتا و ...

علاوه بر تقسیم سندها، می‌توانیم تبدیل‌های دیگری را نیز بر روی محتوای سند انجام دهیم. با استفاده از EmbeddingsRedundantFilter، می‌توانیم سندهای مشابه را شناسایی کرده و محتوای تکراری را حذف کنیم. از طریق ادغام‌هایی مانند doctran، می‌توانیم عملیاتی مانند ترجمه اسناد از یک زبان به زبان دیگر، استخراج ویژگی‌های مورد نیاز و اضافه کردن آنها به متادیتا، و تبدیل گفتگوها به مجموعه‌ای از سندهای قالب‌بندی شده به صورت پرسش و پاسخ انجام دهیم.