การตัดสินเชิงเปรียบเทียบ: A กับ B
พรอมต์เปรียบเทียบเป็นคู่เพื่อจัดอันดับข้อมูลส่งออกโดยไม่ให้คะแนนแบบสัมบูรณ์
การตัดสินเชิงเปรียบเทียบ: A กับ B เป็นบทเรียน AI Prompt Engineering ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Prompt Engineering และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Prompt Engineering มีบทเรียนทั้งหมด 4 บทเรียน
การประเมินแบบจับคู่ (A กับ B) คืออะไร
การประเมินแบบจับคู่ (เรียกอีกอย่างว่าการตัดสินเชิงเปรียบเทียบ) จะแสดงคำตอบสองคำตอบสำหรับคำถามเดียวกันให้ผู้ตัดสินดู แล้วถามว่าคำตอบใดดีกว่า แทนที่จะให้คะแนนคำตอบเดียวตั้งแต่ 1–5 ผู้ตัดสินจะตัดสินเชิงสัมพัทธ์ว่า A ดีกว่า B, B ดีกว่า A หรือเสมอกัน
วิธีนี้หลีกเลี่ยงอคติบางส่วนจากการให้คะแนนแบบค่าสัมบูรณ์ และมักสร้างการจัดอันดับที่น่าเชื่อถือกว่าคะแนนค่าสัมบูรณ์ของคำตอบแต่ละรายการ
คำสั่งผู้ตัดสินแบบจับคู่พื้นฐาน
ผู้ตัดสินแบบจับคู่ที่ง่ายที่สุดจะถามว่าคำตอบใดดีกว่าและเพราะเหตุใด จุดสำคัญคือการบังคับให้เลือก อย่าปล่อยให้ผู้ตัดสินหลีกเลี่ยงการเปรียบเทียบด้วยคำตอบกว้าง ๆ ว่า ‘ทั้งคู่ก็ดี’
import anthropic
import json
client = anthropic.Anthropic(api_key='sk-ant-...')
PAIRWISE_PROMPT = (
'Given the same question, compare these two responses and decide which is better.\n\n'
'Question: {question}\n\n'
'Response A:\n{response_a}\n\n'
'Response B:\n{response_b}\n\n'
'Which response is better? You must pick A, B, or TIE (use TIE only if '
'they are truly equal in all meaningful ways).\n\n'
'Return JSON: {{"winner": "A" or "B" or "TIE", '
'"reason": "<one sentence explaining why the winner is better>"}}'
)
def pairwise_judge(question, response_a, response_b):
prompt = PAIRWISE_PROMPT.format(
question=question,
response_a=response_a,
response_b=response_b
)
r = client.messages.create(
model='claude-opus-4-5',
max_tokens=150,
messages=[{'role': 'user', 'content': prompt}]
)
return json.loads(r.content[0].text)
result = pairwise_judge(
'What is machine learning?',
'Machine learning is a subset of AI.',
'Machine learning is a method of data analysis that automates model building.'
)
print(result)การสุ่มลำดับเพื่อลดอคติด้านตำแหน่ง
อคติด้านตำแหน่งทำให้ผู้ตัดสินชอบตัวเลือกแรก เพื่อกำจัดอคตินี้ ให้ดำเนินการเปรียบเทียบทุกคู่สองครั้ง: ครั้งแรกให้ A อยู่ก่อน และครั้งที่สองให้ B อยู่ก่อน ให้นับผู้ชนะก็ต่อเมื่อลำดับทั้งสองแบบให้ผลตรงกัน หากผลไม่ตรงกัน ให้ประกาศว่าเสมอกันหรือส่งต่อให้มนุษย์ตรวจสอบ
import anthropic
import json
import random
client = anthropic.Anthropic(api_key='sk-ant-...')
def debiased_pairwise_judge(question, response_a, response_b):
def single_comparison(first, second, first_label, second_label):
prompt = (
f'Question: {question}\n\n'
f'Response {first_label}:\n{first}\n\n'
f'Response {second_label}:\n{second}\n\n'
f'Which is better? Reply with {first_label}, {second_label}, or TIE.'
)
r = client.messages.create(
model='claude-opus-4-5',
max_tokens=10,
messages=[{'role': 'user', 'content': prompt}]
)
return r.content[0].text.strip()
# Run A-first
result_ab = single_comparison(response_a, response_b, 'A', 'B')
# Run B-first
result_ba = single_comparison(response_b, response_a, 'B', 'A')
if result_ab == 'A' and result_ba == 'A':
return 'A', 'Consistent: A wins in both orderings'
elif result_ab == 'B' and result_ba == 'B':
return 'B', 'Consistent: B wins in both orderings'
else:
return 'TIE', f'Inconsistent: {result_ab} then {result_ba} — position bias detected'
winner, reason = debiased_pairwise_judge(
'Explain a hash table.',
'A hash table maps keys to values.',
'A hash table is a data structure using a hash function to store key-value pairs for O(1) lookup.'
)
print(f'Winner: {winner} — {reason}')การประเมินแบบจับคู่โดยใช้หลายเกณฑ์
ขอให้ผู้ตัดสินเปรียบเทียบตามมิติเฉพาะ แทนที่จะถามเพียงว่า ‘โดยรวมแล้วคำตอบใดดีกว่า’ การเปรียบเทียบแบบจับคู่แยกตามมิติช่วยให้คุณได้ข้อมูลที่นำไปใช้ได้จริงว่า เหตุใดจึงชอบคำตอบหนึ่งมากกว่าอีกคำตอบหนึ่ง
import anthropic
import json
client = anthropic.Anthropic(api_key='sk-ant-...')
DIMENSIONAL_PAIRWISE = (
'Compare Response A and Response B on each dimension.\n\n'
'Question: {question}\n\n'
'Response A: {response_a}\n\n'
'Response B: {response_b}\n\n'
'For each dimension, say A, B, or TIE:\n'
'1. ACCURACY: Which is more factually correct?\n'
'2. COMPLETENESS: Which answers the question more fully?\n'
'3. CLARITY: Which is easier to understand?\n'
'4. CONCISENESS: Which avoids unnecessary length?\n\n'
'Return JSON: {{"accuracy":"A/B/TIE", "completeness":"A/B/TIE", '
'"clarity":"A/B/TIE", "conciseness":"A/B/TIE", "overall":"A/B/TIE"}}'
)
def dimensional_compare(question, a, b):
r = client.messages.create(
model='claude-opus-4-5',
max_tokens=200,
messages=[{'role': 'user', 'content': DIMENSIONAL_PAIRWISE.format(
question=question, response_a=a, response_b=b
)}]
)
return json.loads(r.content[0].text)
result = dimensional_compare(
'How does HTTPS work?',
'HTTPS encrypts web traffic using SSL/TLS.',
'HTTPS secures HTTP using TLS. The browser and server perform a handshake, exchange certificates, and establish an encrypted channel for all data transfer.'
)
print(result)การสร้างการแข่งขัน: แบบพบกันหมด
เมื่อเปรียบเทียบคำตอบมากกว่าสองคำตอบ ให้ใช้การแข่งขันแบบพบกันหมด: เปรียบเทียบคำตอบทุกคำตอบกับคำตอบอื่นทุกคำตอบ คำตอบที่ชนะมากที่สุดจะได้อันดับหนึ่ง
from itertools import combinations
from collections import defaultdict
def round_robin_tournament(question, responses):
"""
responses: list of (label, text) tuples
Returns ranking by win count.
"""
wins = defaultdict(int)
ties = defaultdict(int)
# Every pair compared once
for (label_a, text_a), (label_b, text_b) in combinations(responses, 2):
winner, reason = debiased_pairwise_judge(question, text_a, text_b)
if winner == 'A':
wins[label_a] += 1
elif winner == 'B':
wins[label_b] += 1
else: # TIE
ties[label_a] += 1
ties[label_b] += 1
print(f'{label_a} vs {label_b}: {winner}')
# Rank by wins, then ties
ranking = sorted(
responses,
key=lambda x: (wins[x[0]], ties[x[0]]),
reverse=True
)
print('\nFinal ranking:')
for i, (label, _) in enumerate(ranking, 1):
print(f'{i}. {label}: {wins[label]} wins, {ties[label]} ties')
return rankingการจัดอันดับด้วยคะแนนเอโลอย่างต่อเนื่อง
สำหรับการประเมินขนาดใหญ่ ให้ใช้คะแนนเอโลแทนการแข่งขันแบบพบกันหมด คำตอบแต่ละคำตอบเริ่มต้นที่ 1,000 คะแนน หลังการเปรียบเทียบแต่ละครั้ง ผู้ชนะจะได้คะแนนเพิ่มและผู้แพ้จะเสียคะแนน โดยแปรผันตามความน่าประหลาดใจของผลลัพธ์นั้น เมื่อผ่านการเปรียบเทียบจำนวนมาก คะแนนเอโลจะสร้างการจัดอันดับโดยรวมที่น่าเชื่อถือ
import math
def elo_update(rating_a, rating_b, winner, k=32):
"""
Update Elo ratings after a match.
winner: 'A' (A won), 'B' (B won), 'TIE' (draw)
Returns (new_rating_a, new_rating_b)
"""
expected_a = 1 / (1 + 10 ** ((rating_b - rating_a) / 400))
expected_b = 1 - expected_a
if winner == 'A':
score_a, score_b = 1, 0
elif winner == 'B':
score_a, score_b = 0, 1
else: # TIE
score_a, score_b = 0.5, 0.5
new_a = rating_a + k * (score_a - expected_a)
new_b = rating_b + k * (score_b - expected_b)
return new_a, new_b
# Simulate ratings for 4 model variants
ratings = {'ModelA': 1000, 'ModelB': 1000, 'ModelC': 1000, 'ModelD': 1000}
# After running many pairwise comparisons:
ratings['ModelA'], ratings['ModelB'] = elo_update(ratings['ModelA'], ratings['ModelB'], 'A')
ratings['ModelC'], ratings['ModelD'] = elo_update(ratings['ModelC'], ratings['ModelD'], 'TIE')
ranking = sorted(ratings.items(), key=lambda x: x[1], reverse=True)
for model, score in ranking:
print(f'{model}: {score:.0f}')ควรใช้การประเมินแบบจับคู่หรือการให้คะแนนแบบค่าสัมบูรณ์เมื่อใด
ใช้การประเมินแบบจับคู่เมื่อ:
- คุณต้องการจัดอันดับโมเดลหรือรูปแบบคำสั่งหลายแบบ
- กำหนดเกณฑ์คะแนนค่าสัมบูรณ์ได้ยาก
- คุณกำลังเปรียบเทียบผลลัพธ์ที่ล้วน ‘ดี’ แต่ดีคนละแบบ
ใช้การให้คะแนนแบบค่าสัมบูรณ์ (ตามเกณฑ์) เมื่อ:
- คุณต้องการเกณฑ์ผ่าน/ไม่ผ่าน (‘คำตอบนี้ดีพอหรือไม่’)
- คุณมีคำตอบเพียงคำตอบเดียวให้ประเมินต่อคำขอหนึ่งรายการ
- คุณต้องการคะแนนแยกตามแต่ละเกณฑ์เพื่อใช้แก้ไขข้อบกพร่อง
การประเมินแบบจับคู่ด้วยการสุ่มตัวอย่างในวงกว้าง
การเปรียบเทียบคำตอบ N รายการทุกคู่ต้องใช้การเปรียบเทียบ N*(N-1)/2 ครั้ง หรือ O(N^2) สำหรับค่า N ขนาดใหญ่ ให้ใช้การสุ่มตัวอย่างแบบสุ่ม โดยเปรียบเทียบคำตอบแต่ละรายการกับคู่แข่งที่สุ่มมา K ราย แทนการเปรียบเทียบกับคำตอบอื่นทั้งหมด วิธีนี้ประมาณการจัดอันดับที่แท้จริงได้ด้วยต้นทุนที่ต่ำกว่ามาก
import random
from collections import defaultdict
def sampled_tournament(question, responses, k_opponents=5):
"""
Compare each response against k random opponents.
More efficient than full round-robin for large N.
"""
wins = defaultdict(int)
n = len(responses)
for i, (label, text) in enumerate(responses):
# Sample k random opponents (not self)
opponent_indices = random.sample(
[j for j in range(n) if j != i],
min(k_opponents, n - 1)
)
for j in opponent_indices:
opp_label, opp_text = responses[j]
winner, _ = debiased_pairwise_judge(question, text, opp_text)
if winner == 'A':
wins[label] += 1
elif winner == 'B':
wins[opp_label] += 1
ranking = sorted(responses, key=lambda x: wins[x[0]], reverse=True)
for i, (label, _) in enumerate(ranking, 1):
print(f'{i}. {label}: {wins[label]} wins')
return rankingการตีความผลที่ไม่ตรงกัน
เมื่อลำดับการจัดวางสองแบบให้ผลไม่ตรงกัน (A ชนะเมื่อจัดลำดับ A-B และ B ชนะเมื่อจัดลำดับ B-A) นั่นเป็นสัญญาณว่าการเปรียบเทียบก้ำกึ่งอย่างแท้จริง ไม่ใช่เพียงผลจากอคติด้านตำแหน่ง กรณีก้ำกึ่งเหล่านี้ควรได้รับการวิเคราะห์เชิงลึกยิ่งขึ้น
import anthropic
import json
client = anthropic.Anthropic(api_key='sk-ant-...')
def deep_analyze_tie(question, response_a, response_b):
"""When A vs B is a genuine tie, ask the judge to explain strengths of each."""
analysis_prompt = (
f'These two responses to the same question are closely matched in quality.\n\n'
f'Question: {question}\n\n'
f'Response A: {response_a}\n\n'
f'Response B: {response_b}\n\n'
f'Analyze both:\n'
f'1. What does A do better than B?\n'
f'2. What does B do better than A?\n'
f'3. For what audience or context would you prefer A?\n'
f'4. For what audience or context would you prefer B?'
)
r = client.messages.create(
model='claude-opus-4-5',
max_tokens=400,
messages=[{'role': 'user', 'content': analysis_prompt}]
)
return r.content[0].text
analysis = deep_analyze_tie(
'Explain async/await in Python.',
'Async/await allows non-blocking code execution.',
'Async/await lets you write asynchronous code that looks synchronous, '
'using the asyncio event loop to handle I/O without blocking.'
)
print(analysis[:300])การบันทึกผลการเปรียบเทียบแบบจับคู่
บันทึกผลการเปรียบเทียบแบบจับคู่ทั้งหมดเพื่อสร้างบันทึกที่ค้นหาได้ว่าคำตอบใดชนะคำตอบใด และเกิดขึ้นภายใต้เงื่อนไขใด ข้อมูลนี้มีประโยชน์ต่อการทดสอบการถดถอยและการทำความเข้าใจการปรับปรุงโมเดลเมื่อเวลาผ่านไป
import json
import datetime
def logged_pairwise(question, response_a, response_b,
label_a='A', label_b='B', log_file='pairwise_log.jsonl'):
winner, reason = debiased_pairwise_judge(question, response_a, response_b)
entry = {
'timestamp': datetime.datetime.utcnow().isoformat(),
'question': question[:100], # Truncate for storage
'label_a': label_a,
'label_b': label_b,
'winner': winner,
'reason': reason,
'response_a_length': len(response_a.split()),
'response_b_length': len(response_b.split()),
}
with open(log_file, 'a') as f:
f.write(json.dumps(entry) + '\n')
print(f'{label_a} vs {label_b}: {winner} — {reason}')
return winner
logged_pairwise(
'What is SQL?',
'SQL is a database query language.',
'SQL (Structured Query Language) is used to query and manage relational databases.',
label_a='ModelV1',
label_b='ModelV2'
)การประเมินแบบจับคู่เทียบกับการให้คะแนนแบบค่าสัมบูรณ์: ข้อแลกเปลี่ยน
การประเมินแบบจับคู่และการให้คะแนนแบบค่าสัมบูรณ์ตามเกณฑ์เป็นแนวทางที่ส่งเสริมกัน ไม่ใช่แนวทางที่แข่งขันกัน ใช้ทั้งสองแบบร่วมกัน: ใช้การให้คะแนนแบบค่าสัมบูรณ์เพื่อกำหนดเกณฑ์คุณภาพขั้นต่ำ และใช้การเปรียบเทียบแบบจับคู่เพื่อจัดอันดับตัวเลือกที่ผ่านเกณฑ์นั้น
ข้อแลกเปลี่ยนสำคัญคือ การประเมินแบบจับคู่ต้องใช้การเปรียบเทียบ O(N^2) ครั้งสำหรับคำตอบ N รายการ ขณะที่การให้คะแนนแบบค่าสัมบูรณ์ต้องใช้ O(N) ครั้ง เมื่อมีข้อมูลขนาดใหญ่ จำเป็นต้องใช้การประเมินแบบจับคู่ด้วยการสุ่มตัวอย่างหรือการจัดอันดับด้วยคะแนนเอโล
แบบทดสอบความรู้: การลดอคติในการประเมินแบบจับคู่
วิธีใดมีประสิทธิภาพสูงสุดในการลดอคติด้านตำแหน่งในการประเมิน LLM แบบจับคู่
สรุปทบทวน: การตัดสินเชิงเปรียบเทียบ A กับ B
การประเมินแบบจับคู่จะถามว่าคำตอบสองคำตอบใดดีกว่า แทนที่จะให้คะแนนแต่ละคำตอบบนมาตราสัมบูรณ์ เพื่อควบคุมอคติด้านตำแหน่ง ให้ดำเนินการเปรียบเทียบทุกคู่สองครั้งโดยสลับลำดับ และยอมรับเฉพาะผลที่ตรงกัน สำหรับคำตอบ N รายการ ให้ใช้การแข่งขันแบบพบกันหมด (ทุกคู่) เมื่อ N มีขนาดเล็ก หรือใช้การแข่งขันด้วยการสุ่มตัวอย่างเมื่อ N มีขนาดใหญ่ การจัดอันดับด้วยคะแนนเอโลสร้างการจัดอันดับต่อเนื่องจากการเปรียบเทียบแบบจับคู่จำนวนมาก ใช้การตัดสินแบบจับคู่แยกตามมิติ (ความถูกต้อง ความครบถ้วน และความชัดเจนแยกกัน) เพื่อให้ได้ข้อมูลวินิจฉัยที่นำไปใช้ได้จริง บันทึกผลทั้งหมดเพื่อใช้ในการทดสอบการถดถอยและวิเคราะห์แนวโน้มในโมเดลแต่ละรุ่น
คำถามที่พบบ่อย
บทเรียน “การตัดสินเชิงเปรียบเทียบ: A กับ B” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การตัดสินเชิงเปรียบเทียบ: A กับ B” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Prompt Engineering ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Prompt Engineering มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การตัดสินเชิงเปรียบเทียบ: A กับ B”
พรอมต์เปรียบเทียบเป็นคู่เพื่อจัดอันดับข้อมูลส่งออกโดยไม่ให้คะแนนแบบสัมบูรณ์ คุณปฏิบัติ AI Prompt Engineering ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Prompt Engineering หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Prompt Engineering บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การตัดสินเชิงเปรียบเทียบ: A กับ B” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Prompt Engineering นี้ได้ไหม
ได้ บทเรียน AI Prompt Engineering ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ใช้ LLM ประเมินข้อมูลส่งออกของ LLM
- พรอมต์ให้คะแนนตามเกณฑ์ประเมิน
- การตัดสินเชิงเปรียบเทียบ: A กับ B
- การปรับเทียบและอคติในผู้ตัดสินที่เป็น LLM