การวัดผลกระทบของการจัดอันดับใหม่
ทำการทดสอบเปรียบเทียบก่อนและหลัง โดยเทียบการดึงข้อมูลขั้นเดียวกับการดึงข้อมูลสองขั้นตอนที่มีการจัดอันดับใหม่ พร้อมวัด NDCG, MRR และคุณภาพคำตอบตั้งแต่ต้นจนจบ
การวัดผลกระทบของการจัดอันดับใหม่ เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดจึงต้องวัดผลกระทบของการจัดอันดับใหม่
การจัดอันดับใหม่เพิ่มเวลาแฝงและค่าใช้จ่ายให้กับไปป์ไลน์ของคุณ หากไม่มีการวัดผล คุณจะไม่สามารถตอบได้ว่าความซับซ้อนที่เพิ่มขึ้นนั้นคุ้มค่าหรือไม่ การทดสอบประสิทธิภาพช่วยวัดปริมาณการปรับปรุงทั้งคุณภาพการค้นคืนและคุณภาพคำตอบตั้งแต่ต้นจนจบ ทำให้คุณตัดสินใจได้อย่างมีข้อมูล นอกจากนี้ยังเผยให้เห็นว่า ประเภทคำค้นใดได้รับประโยชน์มากที่สุด ซึ่งช่วยให้คุณใช้การจัดอันดับใหม่เฉพาะบางกรณี แทนที่จะใช้กับทุกคำขอ
การสร้างชุดแบบทดสอบมาตรฐานอ้างอิง
การทดสอบประสิทธิภาพที่น่าเชื่อถือต้องมี ชุดแบบทดสอบมาตรฐานอ้างอิง ซึ่งเป็นชุดคำค้นที่จับคู่กับรหัสเอกสารซึ่งทราบว่าเกี่ยวข้อง สร้างชุดนี้โดยสุ่มตัวอย่างคำค้นจริงของผู้ใช้จากบันทึกการใช้งาน ระบุเอกสารที่เกี่ยวข้องด้วยตนเองหรือใช้ผู้เชี่ยวชาญทำคำกำกับ และจัดระเบียบให้อยู่ในรูปแบบที่มีโครงสร้าง ชุดแบบทดสอบจำนวน 50-200 คำค้นเพียงพอสำหรับวัตถุประสงค์การประเมิน RAG ส่วนใหญ่
golden_test_set = [
{
'query': 'How does pgvector HNSW indexing improve search speed?',
'relevant_doc_ids': ['doc_042', 'doc_107'],
},
{
'query': 'What is the difference between BM25 and dense retrieval?',
'relevant_doc_ids': ['doc_015'],
},
{
'query': 'How to implement reciprocal rank fusion in Python?',
'relevant_doc_ids': ['doc_093', 'doc_094'],
},
# ... 47 more entries
]
print(f'Test set size: {len(golden_test_set)} queries')
print(f'Avg relevant docs per query: {sum(len(e["relevant_doc_ids"]) for e in golden_test_set) / len(golden_test_set):.1f}')เมตริกการค้นคืน: NDCG, MRR และอัตราการพบ
ใช้เมตริกสามรายการที่ส่งเสริมกันเพื่อประเมินคุณภาพการค้นคืน อัตราการพบที่ Kวัดว่ามีเอกสารที่เกี่ยวข้องอย่างน้อยหนึ่งฉบับปรากฏในผลลัพธ์ K อันดับแรกหรือไม่ MRR (อันดับผกผันเฉลี่ย)วัดค่าเฉลี่ยของอันดับผกผันของเอกสารที่เกี่ยวข้องฉบับแรก NDCG ที่ K (ผลรวมกำไรสะสมแบบลดทอนที่ปรับเป็นมาตรฐาน)วัดคุณภาพการจัดอันดับ โดยให้น้ำหนักตำแหน่งที่สูงกว่ามากกว่าตำแหน่งที่ต่ำกว่า
def compute_retrieval_metrics(results: list[str], relevant_ids: set, k: int = 5):
results_at_k = results[:k]
relevant_found = [r for r in results_at_k if r in relevant_ids]
# Hit rate
hit = 1 if relevant_found else 0
# MRR
rr = 0
for i, doc_id in enumerate(results_at_k, start=1):
if doc_id in relevant_ids:
rr = 1.0 / i
break
# NDCG (binary relevance)
import math
dcg = sum(
1.0 / math.log2(i + 1)
for i, doc_id in enumerate(results_at_k, start=1)
if doc_id in relevant_ids
)
ideal = sum(1.0 / math.log2(i + 1) for i in range(1, min(len(relevant_ids), k) + 1))
ndcg = dcg / ideal if ideal > 0 else 0
return {'hit': hit, 'rr': rr, 'ndcg': ndcg}ค่าพื้นฐาน: การค้นคืนแบบหนาแน่นขั้นตอนเดียว
ก่อนวัดผลกระทบของการจัดอันดับใหม่ ให้กำหนด ค่าพื้นฐานโดยใช้การค้นคืนแบบหนาแน่นขั้นตอนเดียว เรียกใช้ตัวค้นคืนแบบเข้ารหัสสองทางกับคำค้นทุกคำในชุดแบบทดสอบ รวบรวมรหัสเอกสารที่จัดอันดับแล้ว และคำนวณค่าเฉลี่ย NDCG, MRR และอัตราการพบ ค่าพื้นฐานนี้บอกให้ทราบว่าคุณเริ่มต้นจากระดับใด — หากค่าพื้นฐานของคุณอยู่ที่ NDCG@5 เท่ากับ 0.95 อยู่แล้ว การจัดอันดับใหม่ก็มีพื้นที่ให้ปรับปรุงได้ไม่มาก
def evaluate_pipeline(retriever_fn, test_set: list[dict], k: int = 5) -> dict:
all_metrics = []
for entry in test_set:
query = entry['query']
relevant = set(entry['relevant_doc_ids'])
results = retriever_fn(query, top_k=k)
result_ids = [r['id'] for r in results]
metrics = compute_retrieval_metrics(result_ids, relevant, k)
all_metrics.append(metrics)
n = len(all_metrics)
return {
f'hit_rate@{k}': sum(m['hit'] for m in all_metrics) / n,
f'mrr@{k}': sum(m['rr'] for m in all_metrics) / n,
f'ndcg@{k}': sum(m['ndcg'] for m in all_metrics) / n,
}การทดสอบประสิทธิภาพก่อนและหลัง
ใช้ฟังก์ชันประเมินผลเดียวกันกับทั้งตัวค้นคืนขั้นตอนเดียวและตัวค้นคืนสองขั้นตอนที่มีการจัดอันดับใหม่ พิมพ์ผลลัพธ์ไว้เคียงข้างกันเพื่อให้เห็นการปรับปรุง (หรือการไม่ปรับปรุง) ได้ทันที ติดตามเวลาแฝงต่อคำค้นควบคู่กับเมตริกคุณภาพ — การเพิ่มขึ้นของคุณภาพการค้นคืน 5 เปอร์เซ็นต์อาจไม่คุ้มกับเวลาแฝงที่เพิ่มขึ้น 400 มิลลิวินาที ทั้งนี้ขึ้นอยู่กับข้อกำหนด SLA ของแอปพลิเคชัน
import time
def evaluate_with_latency(retriever_fn, test_set, k=5):
metrics_list = []
latencies = []
for entry in test_set:
t0 = time.perf_counter()
results = retriever_fn(entry['query'], top_k=k)
latencies.append((time.perf_counter() - t0) * 1000)
result_ids = [r['id'] for r in results]
metrics_list.append(compute_retrieval_metrics(
result_ids, set(entry['relevant_doc_ids']), k
))
n = len(metrics_list)
return {
f'hit_rate@{k}': sum(m['hit'] for m in metrics_list) / n,
f'ndcg@{k}': sum(m['ndcg'] for m in metrics_list) / n,
'p50_latency_ms': sorted(latencies)[n // 2],
'p99_latency_ms': sorted(latencies)[int(n * 0.99)],
}
baseline = evaluate_with_latency(dense_retrieval_fn, golden_test_set)
two_stage = evaluate_with_latency(two_stage_fn, golden_test_set)
print('Baseline:', baseline)
print('Two-stage:', two_stage)การตีความการปรับปรุง NDCG
โดยทั่วไป การเพิ่มการจัดอันดับใหม่ด้วยตัวเข้ารหัสไขว้ให้กับการค้นคืนแบบหนาแน่นจะเพิ่มค่า NDCG@5 แบบสัมบูรณ์ 0.05 ถึง 0.15 ซึ่งคิดเป็นประมาณ 5-15 จุดเปอร์เซ็นต์ การปรับปรุงจะมากขึ้นเมื่อ: (1) คำค้นของคุณมีความหลากหลายและมีการถอดความหลายรูปแบบ (2) คลังข้อมูลของคุณมีส่วนข้อมูลที่เกือบเกี่ยวข้องจำนวนมาก หรือ (3) ตัวค้นคืนขั้นตอนแรกของคุณมีประสิทธิภาพต่ำ หากการปรับปรุง NDCG น้อยกว่า 0.02 ประโยชน์ที่ได้อาจไม่คุ้มกับความซับซ้อนที่เพิ่มขึ้น
# Interpreting benchmark results
example_results = {
'baseline': {'hit_rate@5': 0.78, 'ndcg@5': 0.64, 'p99_latency_ms': 35},
'two_stage': {'hit_rate@5': 0.89, 'ndcg@5': 0.77, 'p99_latency_ms': 287},
}
delta_ndcg = example_results['two_stage']['ndcg@5'] - example_results['baseline']['ndcg@5']
delta_latency = example_results['two_stage']['p99_latency_ms'] - example_results['baseline']['p99_latency_ms']
print(f'NDCG improvement: +{delta_ndcg:.2f} (+{delta_ndcg/example_results["baseline"]["ndcg@5"]*100:.0f}%)')
print(f'Latency increase: +{delta_latency}ms')
# NDCG improvement: +0.13 (+20%) — clearly worth the 252ms latency costการวัดคุณภาพคำตอบตั้งแต่ต้นจนจบ
เมตริกการค้นคืนวัดว่าเอกสารที่ถูกต้องถูกค้นคืนมาหรือไม่ แต่ตัวชี้วัดสูงสุดคือ คุณภาพคำตอบตั้งแต่ต้นจนจบ ใช้ผู้ตัดสินที่เป็น LLM เพื่อประเมินว่าคำตอบที่สร้างจากบริบทที่จัดอันดับใหม่มีความถูกต้องและสอดคล้องกับข้อมูลมากกว่าคำตอบจากบริบทขั้นตอนเดียวหรือไม่ ให้คะแนนความถูกต้อง ความสอดคล้องกับข้อมูล และความเกี่ยวข้องในระดับ 1-5 จากนั้นหาค่าเฉลี่ยตลอดชุดแบบทดสอบ
from openai import OpenAI
client = OpenAI()
JUDGE_PROMPT = '''
Rate the following answer on a scale of 1-5 for correctness and faithfulness to the context.
Question: {question}
Context: {context}
Answer: {answer}
Ground truth: {ground_truth}
Return a JSON with fields: {"correctness": int, "faithfulness": int, "explanation": str}
'''
def judge_answer(question, context, answer, ground_truth):
prompt = JUDGE_PROMPT.format(
question=question, context=context,
answer=answer, ground_truth=ground_truth,
)
response = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'},
)
import json
return json.loads(response.choices[0].message.content)การวิเคราะห์แยกตามประเภทคำค้น
เมตริกค่าเฉลี่ยอาจซ่อนความแตกต่างสำคัญระหว่างประเภทคำค้น แบ่งชุดแบบทดสอบของคุณออกเป็นหมวดหมู่ — การค้นหาข้อเท็จจริง (ใคร อะไร เมื่อใด), คำค้นเชิงกระบวนการ (วิธีทำ), คำค้นเชิงแนวคิด (เหตุใด อธิบาย) และ คำค้นเชิงเทคนิค (รหัสข้อผิดพลาด ชื่อ API) — แล้วคำนวณเมตริกแยกสำหรับแต่ละกลุ่ม การจัดอันดับใหม่มักช่วยได้มากที่สุดกับคำค้นเชิงแนวคิดและเชิงกระบวนการ ซึ่งความเข้าใจเชิงความหมายมีความสำคัญมากกว่าการจับคู่คำสำคัญ
def stratified_eval(retriever_fn, test_set, k=5):
groups = {'factual': [], 'procedural': [], 'conceptual': [], 'technical': []}
for entry in test_set:
q = entry['query'].lower()
if any(w in q for w in ['how to', 'how do', 'steps to']):
groups['procedural'].append(entry)
elif any(w in q for w in ['why', 'explain', 'what is the reason']):
groups['conceptual'].append(entry)
elif any(c.isupper() for c in q.split()) or 'error' in q:
groups['technical'].append(entry)
else:
groups['factual'].append(entry)
for group_name, group_entries in groups.items():
if group_entries:
metrics = evaluate_pipeline(retriever_fn, group_entries, k)
print(f'{group_name} ({len(group_entries)} queries): ndcg@{k}={metrics[f"ndcg@{k}"]:.3f}')การทดสอบการถดถอยร่วมกับการผสานรวมอย่างต่อเนื่อง
เรียกใช้การทดสอบประสิทธิภาพการค้นคืนของคุณเป็น การทดสอบการถดถอยในการผสานรวมอย่างต่อเนื่อง กำหนดค่าเกณฑ์ขั้นต่ำที่ยอมรับได้สำหรับ NDCG@5, MRR และอัตราการพบ การเปลี่ยนแปลงใด ๆ ในไปป์ไลน์ที่ทำให้เมตริกลดลงต่ำกว่าเกณฑ์จะทำให้การสร้างระบบล้มเหลว ป้องกันไม่ให้การถดถอยของคุณภาพการค้นคืนถูกนำขึ้นสู่ระบบใช้งานจริง เรื่องนี้สำคัญอย่างยิ่งหลังจากเปลี่ยนขนาดส่วนข้อมูล โมเดลเวกเตอร์ฝังตัว หรือโมเดลจัดอันดับใหม่
# pytest integration for retrieval quality gates
import pytest
MIN_NDCG_5 = 0.70
MIN_HIT_RATE_5 = 0.85
def test_retrieval_quality_meets_threshold():
metrics = evaluate_pipeline(production_retriever_fn, golden_test_set, k=5)
assert metrics['ndcg@5'] >= MIN_NDCG_5, (
f'NDCG@5 {metrics["ndcg@5"]:.3f} below threshold {MIN_NDCG_5}'
)
assert metrics['hit_rate@5'] >= MIN_HIT_RATE_5, (
f'Hit rate {metrics["hit_rate@5"]:.3f} below threshold {MIN_HIT_RATE_5}'
)
# Run with: pytest tests/test_retrieval.py -vการแสดงภาพเมตริกการค้นคืน
ตัวเลขดิบตีความได้ยากเมื่อมีการทดลองหลายครั้ง สร้าง ตารางเปรียบเทียบอย่างง่ายหรือแผนภูมิแท่งที่แสดง NDCG, MRR, อัตราการพบ และเวลาแฝงไว้เคียงข้างกันสำหรับไปป์ไลน์พื้นฐาน ไปป์ไลน์แบบผสมเท่านั้น และไปป์ไลน์แบบผสมร่วมกับการจัดอันดับใหม่ การติดตามเมตริกเหล่านี้ตลอดเวลาขณะปรับปรุงระบบจะสร้างประวัติการปรับปรุงการค้นคืน ซึ่งช่วยชี้นำการตัดสินใจเพิ่มประสิทธิภาพในอนาคต
def print_comparison_table(results: dict[str, dict]):
headers = ['Pipeline', 'NDCG@5', 'MRR@5', 'Hit@5', 'P99 ms']
print('|'.join(f'{h:20}' for h in headers))
print('-' * (len(headers) * 21))
for pipeline_name, metrics in results.items():
row = [
pipeline_name,
f'{metrics.get("ndcg@5", 0):.3f}',
f'{metrics.get("mrr@5", 0):.3f}',
f'{metrics.get("hit_rate@5", 0):.3f}',
f'{metrics.get("p99_latency_ms", 0):.0f}',
]
print('|'.join(f'{v:20}' for v in row))
results = {
'Dense only': {'ndcg@5': 0.64, 'mrr@5': 0.68, 'hit_rate@5': 0.78, 'p99_latency_ms': 35},
'Hybrid RRF': {'ndcg@5': 0.71, 'mrr@5': 0.74, 'hit_rate@5': 0.84, 'p99_latency_ms': 55},
'Hybrid + Rerank': {'ndcg@5': 0.77, 'mrr@5': 0.81, 'hit_rate@5': 0.89, 'p99_latency_ms': 287},
}
print_comparison_table(results)การดำเนินการตามผลการทดสอบประสิทธิภาพ
หลังจากเรียกใช้การทดสอบประสิทธิภาพแล้ว ให้ใช้ผลลัพธ์เพื่อตัดสินใจอย่างเป็นรูปธรรม หากการจัดอันดับใหม่เพิ่ม NDCG ได้น้อยกว่า 0.03 ให้ข้ามขั้นตอนนี้และมุ่งปรับปรุงขั้นตอนแรก หากอัตราการพบต่ำ แสดงว่าขั้นตอนแรกพลาดเอกสารที่เกี่ยวข้อง — ให้เพิ่มขนาดชุดตัวเลือกหรือเปลี่ยนไปใช้การค้นคืนแบบผสม หากคุณภาพคำตอบตั้งแต่ต้นจนจบดีขึ้นอย่างมีนัยสำคัญแม้คุณภาพการค้นคืนจะเพิ่มขึ้นเพียงเล็กน้อย ตัวจัดอันดับใหม่อาจกำลังนำเสนอประโยคที่เกี่ยวข้องอย่างมาก ซึ่ง LLM นำไปใช้ได้อย่างมีประสิทธิภาพ แม้ตำแหน่งอันดับจะไม่เปลี่ยนแปลง
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับการวัดผลกระทบของการค้นคืนและการจัดอันดับใหม่จากบทเรียนนี้
ทบทวนบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า การสร้าง ชุดแบบทดสอบมาตรฐานอ้างอิงที่มีเอกสารที่ทราบว่าเกี่ยวข้องเป็นสิ่งจำเป็นก่อนวัดคุณภาพการค้นคืน, NDCG, MRR และอัตราการพบเป็นเมตริกหลักสามรายการของการค้นคืน ซึ่งร่วมกันวัดคุณภาพการจัดอันดับได้อย่างครอบคลุม และ คุณภาพคำตอบตั้งแต่ต้นจนจบโดยใช้ผู้ตัดสินที่เป็น LLM เป็นตัวชี้วัดสูงสุดของการปรับปรุงไปป์ไลน์ ควรเรียกใช้การทดสอบประสิทธิภาพการค้นคืนเป็นการทดสอบการถดถอยในการผสานรวมอย่างต่อเนื่องเสมอ บทถัดไป เราจะสำรวจการสตรีม LLM เพื่อแสดงโทเค็นขณะที่ระบบสร้างโทเค็นเหล่านั้น
คำถามที่พบบ่อย
บทเรียน “การวัดผลกระทบของการจัดอันดับใหม่” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การวัดผลกระทบของการจัดอันดับใหม่” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การวัดผลกระทบของการจัดอันดับใหม่”
ทำการทดสอบเปรียบเทียบก่อนและหลัง โดยเทียบการดึงข้อมูลขั้นเดียวกับการดึงข้อมูลสองขั้นตอนที่มีการจัดอันดับใหม่ พร้อมวัด NDCG, MRR และคุณภาพคำตอบตั้งแต่ต้นจนจบ คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การวัดผลกระทบของการจัดอันดับใหม่” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดการดึงข้อมูลสองขั้นตอนจึงได้ผล
- การจัดอันดับใหม่ด้วยตัวเข้ารหัสไขว้กับ Cohere และ BGE
- การบีบอัดตามบริบทและการกรองความเกี่ยวข้อง
- การวัดผลกระทบของการจัดอันดับใหม่