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

การตัดสินเชิงเปรียบเทียบ: 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. ใช้ LLM ประเมินข้อมูลส่งออกของ LLM
  2. พรอมต์ให้คะแนนตามเกณฑ์ประเมิน
  3. การตัดสินเชิงเปรียบเทียบ: A กับ B
  4. การปรับเทียบและอคติในผู้ตัดสินที่เป็น LLM
← กลับไปที่ AI Prompt Engineering