การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่
การจัดอันดับใหม่ด้วยตัวเข้ารหัสไขว้
การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่ เป็นบทเรียน AI Prompt Engineering ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Prompt Engineering และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Prompt Engineering มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดจึงต้องจัดอันดับใหม่
การค้นคืนระยะแรก (แบบหนาแน่นหรือเบาบาง) ปรับให้เหมาะกับ ความครอบคลุม ในการใช้งานขนาดใหญ่ โดยพยายามนำชิ้นข้อมูลอ้างอิงมาไว้ที่ใดที่หนึ่งใน 50 อันดับแรก วิธีนี้รวดเร็วแต่หยาบ จากนั้น ตัวจัดอันดับใหม่ในระยะที่สองจะจัดลำดับรายการคัดสั้นใหม่เพื่อเพิ่ม ความแม่นยำในการคัดเลือก และนำชิ้นข้อมูลที่เกี่ยวข้องจริงขึ้นมาไว้ด้านบน
รูปแบบการค้นคืนให้กว้างก่อนแล้วจึงจัดอันดับใหม่อย่างแม่นยำนี้เป็นแกนหลักของ RAG ขั้นสูง
def two_stage(query, k_retrieve=50, k_final=5):
candidates = first_stage_retrieve(query, k_retrieve) # high recall
reranked = rerank(query, candidates) # high precision
return reranked[:k_final]ตัวเข้ารหัสแบบคู่เทียบกับตัวเข้ารหัสแบบข้าม
ตัวเข้ารหัสแบบคู่จะแปลงคำค้นและเอกสารเป็นเวกเตอร์ แยกกัน แล้วเปรียบเทียบด้วยโคไซน์ จึงรวดเร็วและสร้างดัชนีได้ แต่สูญเสียปฏิสัมพันธ์ระหว่างคำค้นกับเอกสาร ส่วน ตัวเข้ารหัสแบบข้ามจะป้อนคำค้นกับเอกสารตัวเลือก ร่วมกันเข้าโมเดล และให้คะแนนความเกี่ยวข้อง ซึ่งจับปฏิสัมพันธ์ในรายละเอียดได้
ตัวเข้ารหัสแบบข้ามมีความแม่นยำสูงกว่ามาก แต่ไม่สามารถคำนวณล่วงหน้าได้ จึงทำงานเฉพาะกับรายการคัดสั้นเท่านั้น
# Bi-encoder: score = cos(enc(q), enc(d)) -> precomputable
# Cross-encoder: score = model(q, d) -> 0..1 -> per-pair, no index
def cross_encode(query, doc):
return cross_encoder.predict([(query, doc)])[0] # joint attentionการจัดอันดับใหม่ด้วยตัวเข้ารหัสแบบข้าม
ตัวจัดอันดับใหม่จะให้คะแนนตัวเลือกแต่ละรายการเทียบกับคำค้น แล้วเรียงจากมากไปน้อย เนื่องจากตัวเข้ารหัสแบบข้ามพิจารณาคำค้นกับเอกสารร่วมกัน จึงแก้ปัญหาความเกี่ยวข้องละเอียดอ่อนที่ตัวเข้ารหัสแบบคู่พลาดไปได้ เช่น การปฏิเสธ ความต้องการจับคู่แบบตรงตัว และการแยกคำตอบออกจากหัวข้อ
โดยทั่วไปขั้นตอนนี้เพิ่มความแม่นยำของคำตอบได้มากกว่าการปรับปรุง RAG รายการเดียวอื่น ๆ
def rerank(query, candidates):
pairs = [(query, c.text) for c in candidates]
scores = cross_encoder.predict(pairs) # batched
for c, s in zip(candidates, scores):
c.rerank_score = s
return sorted(candidates, key=lambda c: c.rerank_score, reverse=True)LLM ในบทบาทตัวจัดอันดับใหม่
เมื่อไม่มีตัวเข้ารหัสแบบข้ามที่ฝึกมาให้เหมาะกับขอบเขตงานของคุณ LLM ก็สามารถจัดอันดับใหม่ได้ การจัดอันดับ ทั้งรายการใช้พรอมต์เพื่อให้โมเดลเรียงลำดับข้อความหลายส่วนตามความเกี่ยวข้องในการเรียกใช้ครั้งเดียว ส่วนการให้คะแนน ทีละรายการจะให้คะแนนข้อความแต่ละส่วนแยกกัน
การจัดอันดับทั้งรายการจับการเปรียบเทียบระหว่างรายการได้และประหยัดโทเค็น แต่ควรระวังอคติจากตำแหน่ง และตรวจสอบให้แน่ใจว่าการแยกวิเคราะห์ผลลัพธ์รองรับกรณีที่โมเดลละเว้นหรือทำรหัสซ้ำ
def llm_listwise(query, candidates):
passages = '\n'.join(
'[' + str(i) + '] ' + c.text for i, c in enumerate(candidates)
)
prompt = (
'Rank the passages by relevance to the query. '
'Return only IDs, most relevant first.\nQuery: ' + query +
'\n' + passages
)
order = parse_ids(llm(prompt, temperature=0))
return [candidates[i] for i in order]เวลาแฝงกับขนาดรายการคัดสั้น
ต้นทุนของการจัดอันดับใหม่จะเพิ่มขึ้นตามขนาดรายการคัดเลือกเบื้องต้น ตัวเข้ารหัสไขว้ที่ประมวลผลตัวเลือก 50 รายการมีต้นทุนต่ำกว่าการประมวลผล 500 รายการมาก โปรดเลือกค่า k ในขั้นตอนแรกให้มากพอที่จะครอบคลุมส่วนข้อมูลเป้าหมาย (ตรวจสอบอัตราการเรียกคืน@k) แต่ต้องไม่มากเกินไปจนไม่สามารถจัดอันดับใหม่ได้ภายในงบประมาณเวลาแฝงของคุณ
โปรดจัดกลุ่มการให้คะแนนเป็นคู่และเรียกใช้บนฮาร์ดแวร์เร่งความเร็ว เนื่องจากตัวเข้ารหัสไขว้สามารถประมวลผลคู่ต่าง ๆ แบบขนานได้ดี
def tune_shortlist(eval_set, ks=(20, 50, 100, 200)):
# find smallest k where recall@k saturates -> rerank fewer pairs
return {k: (recall_at_k(eval_set, k), rerank_latency(k)) for k in ks}ขั้นแรกแบบไฮบริดร่วมกับการจัดอันดับใหม่
การเรียกคืนที่ครอบคลุมที่สุดมาจากขั้นแรกแบบ ไฮบริด (การค้นหาแบบหนาแน่นและ BM25 ผสานกัน) ซึ่งส่งรายการสั้นที่ตัดรายการซ้ำแล้วเพียงรายการเดียวไปยังตัวจัดอันดับใหม่ การค้นหาแบบหนาแน่นช่วยกู้คืนข้อความที่ถอดความได้ การค้นหาแบบเบาบางช่วยกู้คืนตัวระบุที่ตรงกันทุกประการ จากนั้นตัวเข้ารหัสไขว้จะเรียงลำดับผลรวมตามความเกี่ยวข้องจริง
การผสมผสานนี้ใช้งานได้อย่างแข็งแกร่งกับคำค้นหลากหลายประเภท ตั้งแต่คำถามภาษาธรรมชาติไปจนถึงการค้นหาข้อมูลตามตัวอักษร
def hybrid_then_rerank(query, k_final=6):
dense = dense_retrieve(query, 50)
sparse = bm25_retrieve(query, 50)
fused = dedup(rrf(dense, sparse)) # reciprocal rank fusion
return rerank(query, fused)[:k_final]เกณฑ์คะแนนและจุดตัด
คะแนนของตัวจัดอันดับใหม่สามารถปรับเทียบได้ แทนที่จะเลือก n อันดับแรกเสมอ ให้ใช้ เกณฑ์ความเกี่ยวข้อง: เก็บชิ้นส่วนที่มีคะแนนสูงกว่าเกณฑ์ และหากไม่มีชิ้นส่วนใดผ่านเกณฑ์ ให้ส่งคืนคำตอบอย่างตรงไปตรงมาว่าไม่มีคำตอบ วิธีนี้ป้องกันการยัดข้อมูลเติมที่มีความเกี่ยวข้องต่ำลงในพรอมต์
ปรับเกณฑ์โดยใช้ชุดตรวจสอบเพื่อสร้างสมดุลระหว่างความครอบคลุมของคำถามที่ตอบได้กับการรวมข้อมูลที่ชวนเขว
def threshold_select(reranked, tau=0.3, max_n=8):
kept = [c for c in reranked if c.rerank_score >= tau][:max_n]
if not kept:
return None # signal: no sufficiently relevant context
return keptความหลากหลายหลังการจัดอันดับใหม่
การเรียงลำดับตามความเกี่ยวข้องเพียงอย่างเดียวอาจส่งคืนชิ้นส่วนที่เกือบซ้ำกันหลายชิ้นจากเอกสารเดียว ทำให้ใช้งบประมาณบริบทอย่างสิ้นเปลือง ให้ใช้ MMR หรือกำหนดเพดานต่อเอกสารหลังการจัดอันดับใหม่ เพื่อให้ชุดสุดท้ายครอบคลุมแง่มุมและแหล่งข้อมูลที่แตกต่างกัน
เรื่องนี้สำคัญสำหรับคำถามแบบหลายขั้น ซึ่งคำตอบครอบคลุมเอกสารหลายฉบับ
def diversify(reranked, max_per_doc=2, k=6):
out, per_doc = [], {}
for c in reranked:
d = c.meta['doc_id']
if per_doc.get(d, 0) < max_per_doc:
out.append(c)
per_doc[d] = per_doc.get(d, 0) + 1
if len(out) == k:
break
return outการจัดลำดับสำหรับตัวสร้างผลลัพธ์
หลังจากเลือกชิ้นส่วนอันดับต้น ๆ แล้ว ให้ วาง ชิ้นส่วนเหล่านั้นเพื่อใช้ประโยชน์จากกลไกความสนใจ เนื่องจากปัญหาข้อมูลตรงกลางบริบทถูกลืม ให้ใส่ชิ้นส่วนที่มีคะแนนสูงสุดไว้ที่ต้นหรือท้ายบริบท อย่าฝังไว้ท่ามกลางชิ้นส่วนอื่น
pipeline บางแบบเรียงชิ้นส่วนตามความเกี่ยวข้องจากน้อยไปมาก เพื่อให้ชิ้นส่วนที่ดีที่สุดอยู่ใกล้คำถามที่สุด ซึ่งเลียนแบบกลยุทธ์การใช้ตัวอย่างจำนวนน้อยที่ใหม่กว่า
def order_for_llm(chunks):
chunks = sorted(chunks, key=lambda c: c.rerank_score) # ascending
return chunks # most relevant chunk ends up last,
# nearest the trailing questionการประเมินตัวจัดอันดับใหม่
วัดผลตัวจัดอันดับใหม่ด้วยเมตริกการจัดอันดับ โดยใช้ NDCG และ MRR เป็นหลัก กับความเกี่ยวข้องระหว่างคำค้นกับชิ้นส่วนที่มีป้ายกำกับ จากนั้นวัด ความถูกต้องของ answer ในขั้นตอนปลายทางด้วย ตัวจัดอันดับใหม่ที่ทำให้ NDCG ดีขึ้นแต่ไม่ทำให้คำตอบดีขึ้น อาจเพียงจัดลำดับชิ้นส่วนใหม่ในแบบที่ตัวสร้างผลลัพธ์จัดการไว้แล้ว
ตรวจสอบคุณภาพของงานปลายทางให้ครบวงจรเสมอ ไม่ใช่ดูแค่เมตริกการจัดอันดับ
import math
def ndcg_at_k(relevances, k):
dcg = sum(r / math.log2(i + 2) for i, r in enumerate(relevances[:k]))
ideal = sorted(relevances, reverse=True)
idcg = sum(r / math.log2(i + 2) for i, r in enumerate(ideal[:k]))
return dcg / idcg if idcg else 0.0pipeline การจัดอันดับใหม่สำหรับใช้งานจริง
ตั้งแต่ต้นจนจบ: ค้นหาแบบไฮบริดเพื่อสร้างรายการสั้นที่มีผู้สมัคร 50 รายการ ตัดรายการซ้ำ จัดอันดับใหม่ด้วยตัวเข้ารหัสไขว้ ใช้เกณฑ์คะแนน สร้างความหลากหลายตามเอกสาร จัดลำดับเพื่อกลไกความสนใจ และสร้างผลลัพธ์พร้อมการอ้างอิง ใช้เกณฑ์เป็นเงื่อนไขเพื่อส่งคืนคำตอบอย่างตรงไปตรงมาว่าไม่มีคำตอบ
แคชเวกเตอร์ฝังและคะแนนของตัวจัดอันดับใหม่แยกตาม (คำค้น, ชิ้นส่วน) เมื่อมีคำขอซ้ำ เพื่อลดต้นทุน
def pipeline(query):
shortlist = hybrid_then_rerank(query, k_final=20)
kept = threshold_select(shortlist, tau=0.3, max_n=8)
if kept is None:
return 'No relevant information found.'
ctx = order_for_llm(diversify(kept))
return generate_with_citations(query, ctx)ตรวจสอบอย่างรวดเร็ว
เลือกสถาปัตยกรรมการจัดอันดับใหม่ที่เหมาะสม
สรุปทบทวน
ประเด็นสำคัญ:
- เรียกคืนข้อมูลให้ครอบคลุมเพื่อให้ได้ความครอบคลุมสูง แล้วจัดอันดับรายการสั้นใหม่เพื่อเพิ่มความแม่นยำ
- ตัวเข้ารหัสไขว้ให้คะแนนคู่คำค้นกับเอกสารร่วมกัน (แม่นยำแต่จัดทำดัชนีไม่ได้) ส่วนตัวเข้ารหัสแบบสองทางทำงานเร็วแต่หยาบกว่า
- การจัดอันดับใหม่แบบรายการหรือแบบรายรายการด้วย LLM เป็นทางเลือกสำรอง ควรระวังอคติจากตำแหน่งและการแยกวิเคราะห์
- ปรับขนาดรายการสั้นให้ความครอบคลุมอิ่มตัวภายในงบประมาณเวลาแฝง และผสานกับการเรียกคืนแบบไฮบริดในขั้นแรก
- ใช้เกณฑ์คะแนน สร้างความหลากหลายตามเอกสาร จัดลำดับชิ้นส่วนเพื่อกลไกความสนใจ และประเมินด้วย NDCG ร่วมกับความถูกต้องของ answer ในขั้นตอนปลายทาง
คำถามที่พบบ่อย
บทเรียน “การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Prompt Engineering ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Prompt Engineering มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่”
การจัดอันดับใหม่ด้วยตัวเข้ารหัสไขว้ คุณปฏิบัติ AI Prompt Engineering ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Prompt Engineering หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Prompt Engineering บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Prompt Engineering นี้ได้ไหม
ได้ บทเรียน AI Prompt Engineering ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ก้าวข้าม RAG แบบพื้นฐาน
- การจัดอันดับชิ้นส่วนข้อมูลที่ดึงมาใหม่
- การบีบอัดบริบท
- การเขียนคำสืบค้นใหม่และ HyDE