ทีมส่วนใหญ่ยังคงสร้าง retrieval pipeline ครั้งแรกด้วยวิธีเดิมๆ พวกเขาเลือกขีดจำกัดโทเคน (token limit) แบบคงที่ เช่น 512 แบ่งเอกสารออกเป็นบล็อกที่มีขนาดเท่ากัน แล้วป้อนบล็อกเหล่านั้นลงใน vector database สำหรับชุดข้อมูลขนาดเล็กที่มีคำถามง่ายๆ วิธีนี้อาจดูเหมือนได้ผลดีเยี่ยม แต่เมื่อนำไปใช้จริงในระบบ production มันกลับพังไม่เป็นท่า
สัญญาทางกฎหมายจะถูกฉีกออกเป็นเศษเสี้ยวที่ไร้ความหมายเมื่อข้อกำหนดถูกตัดกลางประโยค เอกสาร API จะกลายเป็นข้อมูลที่สับสนวุ่นวายหาก chunk เดียวดันรวมเอาฟังก์ชันที่ไม่เกี่ยวข้องกันสามอย่างเข้าไว้ด้วยกัน ตั๋วสนับสนุนลูกค้า (customer support tickets) จะสูญเสียเนื้อหาที่ต่อเนื่องกันหากไม่มีการทำ overlap ระหว่างส่วนต่างๆ ผลลัพธ์ที่ได้นั้นคาดเดาได้ไม่ยาก นั่นคือ latency ที่สูงขึ้น, recall ที่ต่ำลง และคำตอบที่บีบบังคับให้ตัว generator เกิดอาการ hallucinate
เราได้รื้อเลเยอร์การดึงข้อมูล (retrieval layer) ของเราออกแล้วสร้างมันขึ้นมาใหม่ ผลลัพธ์ที่ได้คือ recall ที่พุ่งจาก 78 เปอร์เซ็นต์ เป็น 95 เปอร์เซ็นต์, latency ลดลง 62 เปอร์เซ็นต์ และได้ pipeline ที่ทำงานเหมือนโครงสร้างพื้นฐานจริงๆ แทนที่จะเป็นแค่โค้ดที่เขียนขึ้นลวกๆ ในช่วงวันหยุด และนี่คือสิ่งที่ใช้งานได้จริง
Smart Chunking: เน้นโครงสร้างมากกว่าจำนวนโทเคน
ความผิดพลาดประการแรกคือการทึกทักเอาเองว่าเอกสารทุกฉบับมีรูปแบบเหมือนกัน การแบ่ง chunk ขนาด 512 โทเคนอาจจะสมเหตุสมผลสำหรับงานเขียนเชิงบรรยาย แต่แทบจะใช้ไม่ได้กับงานประเภทอื่นเลย เราจึงเปลี่ยนมาใช้กลยุทธ์ที่เคารพต่อโครงสร้าง (anatomy) ของแหล่งข้อมูลต้นฉบับ
สำหรับเอกสารทางกฎหมาย เราใช้ recursive chunking โดยอัลกอริทึมจะพยายามแบ่งตามขอบเขตระดับสูงก่อน เช่น ส่วน (sections) และมาตรา (articles) หากส่วนนั้นยังยาวเกินไป มันจะมองหาหัวข้อย่อย (subsections) ตามด้วยย่อหน้า และประโยคตามลำดับ วิธีนี้ช่วยรักษาลำดับชั้นทางตรรกะของข้อกำหนดต่างๆ ไว้ได้ สัญญาไม่แข่งขัน (non-compete agreement) จะยังคงอยู่ครบถ้วน และคำนิยามต่างๆ จะไม่ปนไปกับข้อกำหนดเรื่องการชดใช้ค่าเสียหาย (indemnity terms)
เอกสาร API ต้องการการทำ structure-aware chunking เพราะ function signature, ตารางพารามิเตอร์ และตัวอย่าง request ควรจะอยู่ด้วยกัน การแบ่งตามจำนวนโทเคนแบบคงที่มักจะทำให้พารามิเตอร์อยู่ใน chunk หนึ่ง และตัวอย่างอยู่ในอีก chunk หนึ่ง เราจึงเปลี่ยนมาแบ่งตาม document object แทน โดยหนึ่ง chunk จะประกอบด้วย endpoint ที่สมบูรณ์หรือฟังก์ชันเดียว ซึ่งจะช่วยให้ retriever สามารถส่งคืนข้อมูลอ้างอิงที่สมบูรณ์ในตัวเองและตอบคำถามได้จริงๆ
ตั๋วสนับสนุนลูกค้าเหมาะกับการทำ semantic chunking โดยธรรมชาติ แทนที่จะตัดตามขอบเขตของโทเคน เราจะตรวจจับจุดที่มีการเปลี่ยนหัวข้อ เช่น ตั๋วที่เริ่มด้วยการร้องเรียนเรื่องการเข้าสู่ระบบแล้วเปลี่ยนไปเป็นคำถามเรื่องการเรียกเก็บเงิน จะถูกแบ่งออกเป็นสองส่วนที่สอดคล้องกัน แต่ละส่วนจะพกพา metadata ที่จำเป็นติดไปด้วย ทำให้โมเดลไม่ต้องเดาอีกต่อไปว่าผู้ใช้กำลังกังวลเรื่องปัญหาไหนกันแน่
วิคิภายใน (Internal wikis) นั้นมีความยุ่งเหยิงกว่า เพราะมีการผสมผสานทั้งงานเขียน ตาราง แผนภูมิ และเธรดที่ฝังอยู่ สำหรับกรณีนี้ เราใช้ agentic chunking โดยใช้โมเดลภาษาขนาดเล็กอ่านล่วงหน้าเพื่อตัดสินใจว่าหน่วยเนื้อหาที่สมบูรณ์ตามหัวข้อนั้นสิ้นสุดตรงไหน แม้ว่าจะมีต้นทุนเพิ่มขึ้นเล็กน้อยในช่วงการนำข้อมูลเข้า (ingestion time) แต่มันก็ช่วยลดภาระงานของมนุษย์ในการต้องมานั่งปรับแต่งกฎด้วยมือสำหรับรูปแบบหน้าเว็บใหม่ๆ ทุกครั้ง
Hybrid Retrieval: ครอบคลุมทุกมิติ
Vector search นั้นยอดเยี่ยมในการจับความหมายที่คลุมเครือ (fuzzy meaning) หากคุณถามเรื่องการอัปโหลดที่ล่าช้า มันจะส่งคืนย่อหน้าที่เกี่ยวกับ latency และ bandwidth มาให้ได้อย่างง่ายดาย แต่ในขณะเดียวกัน มันก็มีชื่อเสียเรื่องการจัดการกับคำที่ตรงตัวเป๊ะๆ (exact matches) หากนักพัฒนาค้นหารหัสข้อผิดพลาด ERR_CONNECTION_REFUSED ตัว dense embeddings มักจะมองว่ามันเป็นเพียง noise ทั่วไป
BM25 ซึ่งเป็นอัลกอริทึมคีย์เวิร์ดแบบคลาสสิก ทำงานในทางตรงกันข้าม มันสามารถจับข้อความที่แม่นยำและคำที่หาได้ยากได้อย่างดีเยี่ยม แต่กลับพลาดความละเอียดอ่อนทางความหมาย (semantic nuance) เช่น คำค้นหาเกี่ยวกับการ "ลงนามในสัญญา" (signing the agreement) อาจจะไม่แสดงเนื้อหาที่ติดแท็กว่า "การบังคับใช้สัญญา" (executing the contract) ออกมาเลยก็ได้
