AI Prompt Engineering · درس

التحكيم المقارن: A مقابل B

مطالبات المقارنة الثنائية لترتيب المخرجات دون تقييم مطلق

الدرس 3 من 413 خطوة

التحكيم المقارن: A مقابل B درس مجاني في AI Prompt Engineering على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Prompt Engineering، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.

ما المقصود بالتقييم الثنائي (A مقابل B)؟

التقييم الثنائي (ويُسمى أيضًا التحكيم المقارن) يعرض على المُحكِّم استجابتين للسؤال نفسه، ويسأله أيهما أفضل. فبدلًا من تقييم استجابة واحدة بدرجة من 1 إلى 5، يُصدر المُحكِّم حكمًا نسبيًا: A أفضل، أو B أفضل، أو أن النتيجة تعادل.

يتجاوز هذا الأسلوب بعض تحيزات التقييم المطلق، وغالبًا ما ينتج ترتيبات أكثر موثوقية من الدرجات المطلقة لكل استجابة.

موجه المُحكِّم للتقييم الثنائي الأساسي

يسأل أبسط مُحكِّم للتقييم الثنائي أي الاستجابتين أفضل ولماذا. والمهم هو فرض الاختيار — فلا تسمحوا للمُحكِّم بتجنب المقارنة بعبارة مبهمة مثل «كلتاهما جيدتان».

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

تقييم Elo للترتيب المستمر

للتقييم على نطاق واسع، استخدموا تقييمات Elo بدلًا من نظام الدوري الكامل. تبدأ كل استجابة برصيد 1000 نقطة. وبعد كل مقارنة، يكتسب الفائز نقاطًا ويخسرها الخاسر (بما يتناسب مع مدى مفاجأة النتيجة). وبعد إجراء مقارنات كثيرة، تنتج درجات Elo ترتيبًا عالميًا موثوقًا.

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). وعند التوسع إلى نطاق كبير، يصبح التقييم الثنائي القائم على أخذ العينات أو تقييمات Elo ضروريًا.

اختبار المعرفة: الحد من تحيز التقييم الثنائي

ما الطريقة الأكثر فاعلية للحد من تحيز الموضع في تقييم LLM الثنائي؟

مراجعة: التحكيم المقارن A مقابل B

يسأل التقييم الثنائي أي الاستجابتين أفضل بدلًا من تقييم كل استجابة على مقياس مطلق. وللحد من تحيز الموضع، أجروا كل مقارنة مرتين مع تبديل الترتيب، ولا تقبلوا النتيجة إلا إذا اتفق الترتيبان. بالنسبة إلى N من الاستجابات، استخدموا نظام الدوري الكامل (جميع الأزواج) عندما تكون N صغيرة، أو بطولات قائمة على أخذ العينات عندما تكون كبيرة. تنتج تقييمات Elo ترتيبات مستمرة من خلال العديد من المقارنات الثنائية. استخدموا التحكيم الثنائي حسب الأبعاد (الدقة، والاكتمال، والوضوح كلٌّ على حدة) للحصول على إشارة تشخيصية عملية. وسجلوا جميع النتائج لاختبار التراجعات وتحليل الاتجاهات عبر إصدارات النموذج.

البدء مجانًا

تعلم AI Prompt Engineering مع معلم ذكاء اصطناعي — مجانًا

اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.

الدورات
53
الدروس
199

الأسئلة الشائعة

هل درس «التحكيم المقارن: A مقابل B» مجاني؟

نعم — نص درس «التحكيم المقارن: A مقابل B» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Prompt Engineering، انتقل إلى CoddyKit PRO. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.

ماذا ستتعلم في «التحكيم المقارن: A مقابل B»؟

مطالبات المقارنة الثنائية لترتيب المخرجات دون تقييم مطلق تتمرن على AI Prompt Engineering مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ AI Prompt Engineering؟

لا تُشترط خبرة سابقة. AI Prompt Engineering على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «التحكيم المقارن: A مقابل B»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس AI Prompt Engineering هذا؟

نعم. كل درس في AI Prompt Engineering يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. استخدام LLM لتقييم مخرجات LLM
  2. مطالبات التقييم القائمة على معايير
  3. التحكيم المقارن: A مقابل B
  4. المعايرة والتحيز في محكّمي LLM
← العودة إلى AI Prompt Engineering