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

ก้าวข้าม RAG แบบพื้นฐาน

ข้อจำกัดของการดึงข้อมูลพื้นฐาน

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

สิ่งที่ RAG แบบพื้นฐานทำ

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

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

def naive_rag(query, k=5):
    q = embed(query)
    chunks = vector_store.search(q, k)        # top-k by cosine
    context = '\n\n'.join(c.text for c in chunks)
    return llm('Context:\n' + context + '\n\nQ: ' + query)

ความครอบคลุมเทียบกับความแม่นยำของการค้นคืน

การค้นคืน k อันดับแรกแบบพื้นฐานปรับให้เหมาะกับ ความคล้ายคลึง ของเวกเตอร์ดิบ ซึ่งปะปนความเกี่ยวข้องเข้ากับความใกล้เคียงทางความหมายบนผิวภาษา จึงเกิดความขัดแย้งระหว่างสองด้าน: ค่า k ที่น้อยเสี่ยงพลาดคำตอบ (ความครอบคลุมต่ำ) ส่วนค่า k ที่มากทำให้บริบทเต็มไปด้วยสิ่งรบกวน (ความแม่นยำต่ำ)

ความคล้ายคลึงของเวกเตอร์ฝังที่ใช้ขับเคลื่อนการค้นคืนเป็นเพียงตัวแทนความเกี่ยวข้องแบบหยาบ และเป็นต้นเหตุของปัญหาต่อเนื่องหลายประการ

# The core dilemma
# small k -> may miss the gold chunk (recall problem)
# large k -> distractors crowd context (precision + cost problem)
# Advanced RAG decouples 'retrieve many' from 'use few'

ปัญหาความไม่ตรงกันของเวกเตอร์ฝัง

คำค้นและเอกสารมักอยู่ใน ระดับภาษาที่แตกต่างกัน: คำถามสั้น ๆ เทียบกับข้อความบอกเล่าที่ยาว ตัวเข้ารหัสแบบคู่อาจวางคำตอบที่เกี่ยวข้องไว้ห่างจากคำถาม เพราะทั้งสองถูกเขียนด้วยถ้อยคำต่างกัน ซึ่งเป็นปัญหาความไม่ตรงกันของคำศัพท์

ปัญหานี้เป็นที่มาของเทคนิคต่าง ๆ เช่น การเขียนคำค้นใหม่และ HyDE ซึ่งปรับรูปคำค้นให้เข้ากับพื้นที่ของเอกสารก่อนการค้นคืน

# Query:  'how do I revoke a token?'
# Doc:    'Token invalidation is performed via the /sessions endpoint.'
# Lexically and semantically distant -> bi-encoder may miss it
sim = cos(embed('how do I revoke a token?'),
          embed('Token invalidation via /sessions'))  # may be low

ข้อมูลตรงกลางถูกมองข้าม

แม้จะค้นคืนชิ้นข้อมูลที่ถูกต้องได้แล้ว การยัดชิ้นข้อมูลจำนวนมากลงไปก็ทำให้เกิด ผลกระทบจากการหลงลืมข้อมูลตรงกลาง: โมเดลให้ความสนใจกับเนื้อหาที่อยู่ตรงกลางของบริบทยาว ๆ น้อยลง ชิ้นข้อมูลที่ถูกต้องแต่ถูกฝังอยู่ในอันดับ 3 จาก 10 อาจถูกมองข้ามไปโดยสิ้นเชิง

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

# Retrieval rank != attention rank
# Place the highest-relevance chunk at the START or END,
# never stranded in the middle of a large concatenation.

ความไวต่อสิ่งรบกวน

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

นี่คือเหตุผลที่ความแม่นยำมีความสำคัญ บริบทที่กระชับ จัดอันดับใหม่ และบีบอัดแล้ว มักให้ผลดีกว่าการเทชิ้นข้อมูลจำนวนมากที่เกี่ยวข้องกันอย่างหลวม ๆ ลงไป

# Empirically: appending a single highly-similar but WRONG chunk
# can flip a previously-correct answer. RAG quality depends on
# keeping distractors OUT, not just getting the gold chunk IN.

ปัญหาจากการแบ่งชิ้นข้อมูล

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

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

def structure_aware_chunks(doc, max_tokens=400, overlap=50):
    sections = split_by_headings(doc)        # respect document structure
    chunks = []
    for sec in sections:
        for c in sliding_window(sec.text, max_tokens, overlap):
            chunks.append(Chunk(c, meta={'section': sec.title}))
    return chunks

ช่องว่างของการค้นคืนเชิงความหมายเพียงอย่างเดียว

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

การผสานอันดับแบบส่วนกลับเป็นวิธีที่เรียบง่ายและทนทานสำหรับรวมรายการที่จัดอันดับแล้วสองรายการโดยไม่ต้องปรับน้ำหนัก

def rrf(dense_ranks, sparse_ranks, k0=60):
    scores = {}
    for ranks in (dense_ranks, sparse_ranks):
        for rank, doc_id in enumerate(ranks):
            scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k0 + rank)
    return sorted(scores, key=scores.get, reverse=True)

บริบทล้าสมัยและตรวจสอบที่มาไม่ได้

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

ระบบขั้นสูงจะเพิ่มข้อมูลเมตา เช่น เวลา แหล่งที่มา และรุ่น กรองข้อมูลตามข้อมูลเหล่านั้น และกำหนดให้ตัวสร้างอ้างอิงรหัสชิ้นข้อมูล เพื่อให้ตรวจสอบคำตอบได้

def filtered_retrieve(q, after_date):
    cands = vector_store.search(embed(q), k=50)
    fresh = [c for c in cands if c.meta['date'] >= after_date]
    return fresh  # then re-rank; generator must cite c.id

ไม่มีข้อมูลป้อนกลับก็ไม่มีการปรับตัว

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

กระบวนการจึงกลายเป็นวงรอบที่ประเมินตนเอง แทนที่จะเป็นการประมวลผลไปข้างหน้าเพียงรอบเดียว

def adaptive_rag(q):
    chunks = retrieve(q)
    if relevance_score(q, chunks) < 0.4:
        q2 = rewrite_query(q)            # reformulate and retry
        chunks = retrieve(q2)
    if relevance_score(q, chunks) < 0.4:
        return 'I could not find this in the sources.'
    return generate(q, chunks)

ชุดองค์ประกอบ RAG ขั้นสูง

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

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

def advanced_rag(q):
    cands = hybrid_retrieve(rewrite_query(q), k=50)  # high recall
    top = rerank(q, cands)[:8]                       # precision
    ctx = compress(q, top)                            # focus + fit
    return generate_with_citations(q, ctx)            # verifiable

วัดผลก่อนปรับให้เหมาะสม

วินิจฉัยก่อนว่าคุณกำลังพบความล้มเหลวแบบใดจริง ๆ ก่อนเพิ่มกลไกต่าง ๆ วัด ความครอบคลุมของการค้นคืนที่อันดับ k ว่าค้นคืนชิ้นข้อมูลอ้างอิงได้หรือไม่ แยกจาก ความแม่นยำของคำตอบ ว่าตัวสร้างนำชิ้นข้อมูลนั้นไปใช้หรือไม่ ปัญหาด้านความครอบคลุมกับปัญหาด้านความแม่นยำต้องใช้วิธีแก้ต่างกัน

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

def diagnose(eval_set):
    return {
        'recall@5':  recall_at_k(eval_set, k=5),     # retrieval health
        'recall@50': recall_at_k(eval_set, k=50),    # ceiling with rerank
        'answer_acc': answer_accuracy(eval_set),      # generation health
    }

ตรวจสอบอย่างรวดเร็ว

วินิจฉัยรูปแบบความล้มเหลวของ RAG

สรุปทบทวน

ประเด็นสำคัญ:

  • RAG แบบพื้นฐาน (แบ่งชิ้น สร้างเวกเตอร์แทน ค้นคืน k อันดับแรก ยัดลงพรอมต์ แล้วสร้างคำตอบ) เป็นพื้นฐานที่แข็งแกร่งและมีความล้มเหลวที่คาดเดาได้
  • ความคล้ายคลึงของตัวเข้ารหัสแบบคู่เป็นเพียงตัวแทนความเกี่ยวข้องแบบหยาบ ความไม่ตรงกันของระดับภาษาระหว่างคำค้นกับเอกสารทำให้ความครอบคลุมลดลง
  • บริบทที่มากขึ้นไม่ได้ดีกว่าเสมอไป เพราะความไวต่อสิ่งรบกวนและการหลงลืมข้อมูลตรงกลางทำให้คำตอบแย่ลงเมื่อค่า k เพิ่มขึ้น
  • ปัญหาจากการแบ่งชิ้นข้อมูล ช่องว่างของการค้นคืนเชิงความหมายเพียงอย่างเดียว ความล้าสมัย และการขาดข้อมูลป้อนกลับ ล้วนจำกัด RAG แบบพื้นฐาน
  • RAG ขั้นสูงค้นคืนให้กว้างแล้วจึงกรอง ได้แก่ การค้นคืนแบบผสม การจัดอันดับใหม่ การบีบอัด การเขียนคำค้นใหม่ และการคัดกรองความเกี่ยวข้อง ควรวัดความครอบคลุมกับความแม่นยำของคำตอบแยกกันก่อนปรับปรุงระบบ

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

บทเรียน “ก้าวข้าม RAG แบบพื้นฐาน” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “ก้าวข้าม RAG แบบพื้นฐาน”

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

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

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

บทเรียน “ก้าวข้าม RAG แบบพื้นฐาน” ใช้เวลานานแค่ไหน

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

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

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

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

  1. ก้าวข้าม RAG แบบพื้นฐาน
  2. การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่
  3. การบีบอัดบริบท
  4. การเขียนคำสืบค้นใหม่และ HyDE
← กลับไปที่ AI Prompt Engineering