0Pricing
AI Engineering Academy · บทเรียน

เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล

วิเคราะห์ความล้มเหลวจริงในการดึงข้อมูลที่เกิดจากการแบ่งส่วนที่ไม่มีประสิทธิภาพ รวมถึงคำตอบที่ถูกแบ่งข้ามขอบเขตส่วน และบริบทจากหัวข้อกับชื่อส่วนที่สูญหายไป

เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

ต้นทุนของการแบ่งส่วนที่ไม่ดี

การแบ่งส่วน คือกระบวนการแบ่งเอกสารออกเป็นส่วนย่อย ๆ ก่อนฝังลงในคลังเวกเตอร์ วิธีที่คุณแบ่งส่วนจะเป็นตัวกำหนดว่ามีบริบทใดพร้อมใช้งานระหว่างการค้นคืน การแบ่งส่วนที่ไม่ดีเป็นหนึ่งในสาเหตุของความล้มเหลวของระบบ RAG ที่พบได้บ่อยและส่งผลกระทบมากที่สุด

คำตอบถูกแบ่งข้ามขอบเขต

ลองนึกภาพเอกสารที่ระบุว่า: 'นโยบายคืนเงินคือ 30 วันนับจากวันที่ซื้อ ลูกค้าต้องแนบใบเสร็จฉบับจริง' หากตัวแบ่งขนาดตายตัวตัดหลังคำว่า 'ซื้อ' ประโยคทั้งสองจะไปอยู่คนละส่วน คำค้นเกี่ยวกับนโยบายคืนเงินอาจค้นพบเพียงครึ่งแรก ทำให้โมเดลไม่สามารถกล่าวถึงข้อกำหนดเรื่องใบเสร็จได้

บริบทที่สูญหายจากหัวข้อ

เอกสารมักใช้หัวข้อส่วนเพื่อให้ความหมาย ลองพิจารณาตารางที่มีชื่อว่า 'ราคาสำหรับแผน Enterprise' ตามด้วยแถวตัวเลข หากหัวข้อกับตารางไปอยู่คนละส่วน ส่วนตารางที่ค้นคืนมาจะมีแต่ตัวเลขโดยไม่มีป้ายกำกับ ทำให้โมเดลไม่สามารถตอบคำถาม 'ราคา Enterprise เท่าไร' ได้อย่างถูกต้อง

ข้อควรระวังของการแบ่งส่วนขนาดตายตัว

การแบ่งส่วนขนาดตายตัว จะแบ่งข้อความทุก ๆ อักขระหรือโทเค็นจำนวน N รายการ โดยไม่คำนึงถึงขอบเขตประโยค วิธีนี้รวดเร็วและเรียบง่าย แต่บ่อยครั้งจะแบ่งกลางประโยค ส่วนหนึ่งที่ลงท้ายด้วย 'The model was trained on' และส่วนถัดไปที่เริ่มต้นด้วย 'a dataset of 500 billion tokens' ต่างก็ไม่มีความหมายเมื่อขาดอีกส่วนหนึ่ง

from langchain.text_splitter import CharacterTextSplitter

# Naive fixed-size: may break mid-sentence
splitter = CharacterTextSplitter(chunk_size=200, chunk_overlap=0)
chunks = splitter.split_text(document_text)
print(f'Created {len(chunks)} chunks')
print('First chunk:', chunks[0])

การซ้อนทับไม่ได้ช่วยเสมอไป

วิธีแก้ที่ใช้กันทั่วไปคือการเพิ่ม การซ้อนทับระหว่างส่วน — ทำซ้ำโทเค็น N รายการสุดท้ายของส่วนหนึ่งไว้ที่จุดเริ่มต้นของส่วนถัดไป วิธีนี้ช่วยเรื่องประโยคที่ถูกแบ่ง แต่ทำให้เกิดข้อมูลซ้ำ และอาจทำให้ตัวค้นคืนสับสนเมื่อมีการค้นคืนส่วนที่คล้ายกันมากสองส่วน การซ้อนทับเป็นเพียงการแก้ปัญหาชั่วคราว ไม่ใช่การแก้ปัญหาการแบ่งส่วนเชิงโครงสร้างอย่างแท้จริง

# Overlap helps partially but adds redundancy
splitter = CharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50  # last 50 chars repeated in next chunk
)
chunks = splitter.split_text(document_text)

การวัดอัตราความล้มเหลวของการค้นคืน

คุณสามารถวัดว่าการแบ่งส่วนส่งผลเสียต่อการค้นคืนบ่อยเพียงใดด้วยการสร้าง ชุดประเมินมาตรฐาน ขนาดเล็ก ซึ่งเป็นรายการคำถามพร้อมข้อความต้นทางที่ถูกต้องและทราบอยู่แล้ว จากนั้นตรวจสอบว่าข้อความที่ถูกต้องอยู่ในส่วนที่ค้นคืนได้อันดับต้น ๆ จำนวน k บ่อยเพียงใด hit rate ที่ต่ำมักเผยให้เห็นปัญหาการแบ่งส่วนก่อนที่คุณจะตรวจสอบคุณภาพการสร้างคำตอบเสียอีก

def hit_rate(queries_and_answers, retriever, k=5):
    hits = 0
    for query, expected_text in queries_and_answers:
        results = retriever.retrieve(query, k=k)
        retrieved_texts = [r.page_content for r in results]
        if any(expected_text in text for text in retrieved_texts):
            hits += 1
    return hits / len(queries_and_answers)

ปัญหาของโค้ดและข้อมูลที่มีโครงสร้าง

ไฟล์โค้ด, JSON และตารางมี หน่วยเชิงตรรกะ ได้แก่ ฟังก์ชัน ออบเจ็กต์ และแถวตาราง ซึ่งไม่ควรถูกแบ่ง การแบ่งคำจำกัดความของฟังก์ชัน Python ออกเป็นสองส่วนทำให้แต่ละส่วนไม่สามารถทำความเข้าใจได้ด้วยตนเอง ตัวค้นคืนที่พบส่วนที่สองจะเห็นโค้ดที่ไม่มีอาร์กิวเมนต์และไร้บริบท

# Bad: splits code arbitrarily
bad_chunk_1 = 'def calculate_price(item, qty'  # incomplete!
bad_chunk_2 = ', discount):\n    return item.price * qty * (1 - discount)'

# Good: keep the full function together
good_chunk = 'def calculate_price(item, qty, discount):\n    return item.price * qty * (1 - discount)'

เอกสารยาวและการสูญเสียเนื้อหาตรงกลาง

งานวิจัยเกี่ยวกับ LLM แสดงให้เห็นปรากฏการณ์ 'หลงหายในช่วงกลาง': เมื่อมีการค้นคืนหลายส่วนและใส่ทั้งหมดลงในคำสั่ง โมเดลจะให้ความสนใจกับเนื้อหาช่วงต้นและท้าย แต่มีแนวโน้มที่จะมองข้ามช่วงกลาง การแบ่งส่วนที่ไม่ดีซึ่งทำให้เกิดส่วนขนาดเล็กคุณภาพต่ำจำนวนมากจะทำให้ปัญหานี้รุนแรงขึ้น เพราะสัญญาณที่เกี่ยวข้องถูกเจือจาง

วินิจฉัยส่วนที่ไม่ดีด้วยตนเอง

วิธีตรวจสอบอย่างรวดเร็วคือพิมพ์ตัวอย่างแบบสุ่มจากส่วนต่าง ๆ ของคุณออกมาแล้วอ่าน ถามตัวเองว่า: ส่วนนี้มีความหมายเมื่อพิจารณาแยกเดี่ยวหรือไม่ หากผู้ใช้ถามคำถาม โมเดลจะตอบได้จากส่วนนี้เพียงส่วนเดียวหรือไม่ ส่วนที่อ้างถึงสรรพนามที่ไม่ทราบว่าหมายถึงใคร ('เขากล่าวว่า...') มีโค้ดไม่สมบูรณ์ หรือตัวเลขที่ไม่มีบริบท ล้วนเป็นสัญญาณเตือน

import random

def audit_chunks(chunks, sample_size=10):
    sample = random.sample(chunks, min(sample_size, len(chunks)))
    for i, chunk in enumerate(sample):
        print(f'--- Chunk {i+1} ({len(chunk)} chars) ---')
        print(chunk[:300])
        print()

เมื่อขนาดส่วนใหญ่เกินไป

ส่วนที่มีขนาดใหญ่มากจะส่งผลเสียต่อความแม่นยำของการค้นคืน ส่วนขนาด 2,000 โทเค็นเกี่ยวกับหัวข้อกว้าง ๆ อาจตรงกับคำค้นจำนวนมาก แต่ส่งเสียงรบกวนให้ LLM มากเกินไป โมเดลต้องค้นหาเข็มในกองฟางภายในส่วนนั้น ส่วนที่เล็กกว่าและเน้นประเด็นชัดเจนจะเพิ่มความแม่นยำ แต่มีต้นทุนคืออาจพลาดบริบทโดยรอบ

กลยุทธ์ที่แก้ปัญหาเหล่านี้

ทางเลือกที่ดีกว่าการแบ่งส่วนขนาดตายตัวแบบพื้นฐาน ได้แก่ การแบ่งตามขอบเขตประโยค ซึ่งไม่ตัดกลางประโยค การแบ่งส่วนเชิงความหมาย ซึ่งแบ่งตรงขอบเขตหัวข้อ การแบ่งส่วนแบบแม่-ลูก ซึ่งรักษาบริบทที่กว้างกว่า และ การแบ่งส่วนที่คำนึงถึงเอกสาร ซึ่งเคารพฟังก์ชันโค้ด แท็ก HTML และหัวข้อ Markdown บทเรียนถัดไปแต่ละบทจะครอบคลุมแนวทางหนึ่งในนี้

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจเกี่ยวกับรูปแบบความล้มเหลวของการแบ่งส่วนจากบทเรียนนี้

สรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า การแบ่งส่วนขนาดตายตัวแบบพื้นฐานทำลายขอบเขตประโยคและส่วนต่าง ๆ การซ้อนทับเป็นการแก้ปัญหาได้เพียงบางส่วนแต่เพิ่มข้อมูลซ้ำ และ คุณภาพของส่วนเป็นตัวกำหนด hit rate ของการค้นคืนโดยตรง ต่อไปเราจะสำรวจการแบ่งส่วนเชิงความหมาย ซึ่งแบ่งข้อความตรงขอบเขตหัวข้อที่เป็นธรรมชาติโดยใช้ความคล้ายคลึงของการฝัง

คำถามที่พบบ่อย

บทเรียน “เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล”

วิเคราะห์ความล้มเหลวจริงในการดึงข้อมูลที่เกิดจากการแบ่งส่วนที่ไม่มีประสิทธิภาพ รวมถึงคำตอบที่ถูกแบ่งข้ามขอบเขตส่วน และบริบทจากหัวข้อกับชื่อส่วนที่สูญหายไป คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม

ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล
  2. การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง
  3. การดึงข้อมูลแบบส่วนแม่-ส่วนลูกและจากเล็กไปใหญ่
  4. กลยุทธ์เฉพาะเอกสารสำหรับโค้ดและ HTML
← กลับไปที่ AI Engineering Academy