اختبار الانحدار عبر تحديثات النماذج
تشغيل مجموعات الاختبارات عند الترقية من GPT-4 إلى GPT-4o أو من Claude 3 إلى 3.5
اختبار الانحدار عبر تحديثات النماذج درس مجاني في AI Prompt Engineering على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في AI Prompt Engineering، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.
لماذا تؤدي تحديثات النماذج إلى تعطيل Prompts
يحدّث مزودو LLM نماذجهم بانتظام: GPT-4 → GPT-4o → GPT-4o-2024-11-20، وClaude 3 → Claude 3.5 → Claude 3.7. يغيّر كل تحديث سلوك النموذج — وغالبًا ما يحسّن معظم المهام، لكنه قد يؤدي أحيانًا إلى تراجع في بعض prompts المحددة.
من دون مجموعة اختبارات، تظل حالات التراجع غير مرئية حتى يبلغ المستخدمون عنها. أما مع وجود مجموعة اختبارات، فتكتشف حالات التراجع خلال دقائق من تحديث النموذج.
مشكلة تحديثات النماذج
قد تتسبب تحديثات النماذج في ثلاثة أنواع من التغييرات:
- التحسينات: تنجح الآن حالات الاختبار التي كانت تفشل سابقًا — وهذا أمر جيد
- المحايدة: لا يتغير السلوك — وهذا ينطبق على معظم الاختبارات
- حالات التراجع: تفشل الآن حالات الاختبار التي كانت تنجح سابقًا — ويجب التحقيق فيها
حتى معدل تراجع قدره 1% يُعد مهمًا: فإذا كان لديك 200 حالة اختبار وبدأت حالتان بالفشل بعد تحديث النموذج، فقد تكون هاتان الحالتان من أكثر حالات الاستخدام أهمية.
MODEL_HISTORY = [
{'model': 'gpt-4', 'deployed': '2023-03-14', 'pass_rate': 0.87},
{'model': 'gpt-4-turbo', 'deployed': '2023-11-06', 'pass_rate': 0.91},
{'model': 'gpt-4o', 'deployed': '2024-05-13', 'pass_rate': 0.93},
{'model': 'gpt-4o-2024-11-20', 'deployed': '2024-11-20', 'pass_rate': None}, # to be measured
]
# Goal: measure pass_rate for the new model before deploying to productionتشغيل مجموعة الاختبارات على نموذج جديد
عند الإعلان عن إصدار جديد من النموذج، شغّل مجموعة اختباراتك الكاملة على النموذج القديم والجديد معًا. قارن معدلات النجاح، وحدد حالات الاختبار المحددة التي تغيّر سلوكها.
import openai
client = openai.OpenAI(api_key='sk-...')
def run_suite_on_model(test_cases, system_prompt, model):
results = []
for test in test_cases:
resp = client.chat.completions.create(
model=model,
messages=[
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': test['input']}
],
temperature=0
)
output = resp.choices[0].message.content
passed = test['evaluator'](output)
results.append({'id': test['id'], 'passed': passed, 'output': output})
pass_rate = sum(r['passed'] for r in results) / len(results)
return results, pass_rate
old_results, old_rate = run_suite_on_model(TEST_CASES, PROMPT, 'gpt-4o')
new_results, new_rate = run_suite_on_model(TEST_CASES, PROMPT, 'gpt-4o-2024-11-20')
print(f'Old: {old_rate:.1%} | New: {new_rate:.1%} | Delta: {(new_rate-old_rate):+.1%}')مقارنة الفروقات بين إصدارات النماذج
بعد تشغيل المجموعتين، حدد الحالات التي تغيّرت حالتها: من نجاح → فشل (حالات التراجع)، ومن فشل → نجاح (التحسينات).
def diff_results(old_results, new_results):
old_by_id = {r['id']: r for r in old_results}
new_by_id = {r['id']: r for r in new_results}
regressions = []
improvements = []
for test_id, new_r in new_by_id.items():
old_r = old_by_id.get(test_id)
if old_r is None:
continue
if old_r['passed'] and not new_r['passed']:
regressions.append({'id': test_id, 'old_output': old_r['output'], 'new_output': new_r['output']})
elif not old_r['passed'] and new_r['passed']:
improvements.append({'id': test_id})
print(f'Regressions: {len(regressions)}')
print(f'Improvements: {len(improvements)}')
for reg in regressions:
print(f' REGRESSED: {reg["id"]}')
print(f' Old: {reg["old_output"][:60]}')
print(f' New: {reg["new_output"][:60]}')
return regressions, improvements
regressions, improvements = diff_results(old_results, new_results)تتبّع إصدار النموذج في سجلات الاختبارات
يجب أن يتضمن سجل كل تشغيل للاختبارات المعرّف الدقيق للنموذج — وليس 'gpt-4o' فقط، بل السلسلة الكاملة التي تتضمن الإصدار 'gpt-4o-2024-11-20'. تحدّث OpenAI وAnthropic النموذج الموجود خلف اسم مستعار (مثل 'gpt-4o') باستمرار من دون تغيير اسم الاسم المستعار، ولذلك يكون السجل ضروريًا لتصحيح سلوك سابق.
import openai, json
from datetime import datetime, timezone
client = openai.OpenAI(api_key='sk-...')
def run_test_with_version_tracking(test, system_prompt, model_alias):
resp = client.chat.completions.create(
model=model_alias,
messages=[
{'role': 'system', 'content': system_prompt},
{'role': 'user', 'content': test['input']}
],
temperature=0
)
output = resp.choices[0].message.content
return {
'test_id': test['id'],
'model_alias': model_alias,
'model_actual': resp.model, # The exact versioned model ID returned by the API
'timestamp': datetime.now(timezone.utc).isoformat(),
'output': output,
'passed': test['evaluator'](output)
}التحقيق في حالات التراجع
عند العثور على حالة تراجع، أجرِ تحقيقًا قبل تحديث prompt. اسأل: هل أصبح prompt أسوأ، أم أن النموذج أصبح أفضل بطريقة غيّرت السلوك؟
مثال: قد يتبع خليفة GPT-4o تعليمات التنسيق بصرامة أكبر، مما يؤدي إلى فشل اختبار لأن الاختبار القديم كان يتوقع مخرجات لا تلتزم بالمواصفات تمامًا. في هذه الحالة، تحسّن النموذج ويحتاج الاختبار إلى تحديث — وليس prompt.
def investigate_regression(test_id, old_output, new_output, prompt, user_input):
# Step 1: check if old behavior was actually wrong
judge_prompt = (
f'Given this task prompt: {prompt}\n'
f'And this user input: {user_input}\n\n'
f'Which output is better?\n'
f'A) {old_output}\n'
f'B) {new_output}\n\n'
'Reply with A or B and one sentence explanation.'
)
resp = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': judge_prompt}],
temperature=0
)
verdict = resp.choices[0].message.content
print(f'Judge verdict for {test_id}: {verdict}')
# If judge says B (new output) is better: update the test, not the promptمتى تحدّث Prompt ومتى تحدّث الاختبار
بعد التحقيق في حالة التراجع، اختر أحد الإجراءات الثلاثة:
- تحديث prompt: يتطلب النموذج الجديد صياغة تعليمات مختلفة لتحقيق السلوك نفسه
- تحديث الاختبار: كانت المخرجات المتوقعة القديمة خاطئة أو أقل جودة؛ أما المخرجات الجديدة فهي أفضل فعلًا
- قبول حالة التراجع: لا يستطيع النموذج الجديد تنفيذ هذه المهمة بشكل موثوق؛ فاستخدم اسم النموذج القديم المستعار لحالة الاستخدام هذه
REGRESSION_ACTIONS = {
'prompt_updated': {
'when': 'New model ignores instruction the old model followed. Same behavior needed.',
'action': 'Add stronger/rephrased instruction. Re-run tests on new model.'
},
'test_updated': {
'when': 'New model output is objectively better but fails old test criteria.',
'action': 'Update expected output in test. Document the improvement.'
},
'model_pinned': {
'when': 'New model cannot perform this task reliably despite prompt changes.',
'action': 'Pin the model alias to the old versioned ID for this endpoint.'
}
}تثبيت إصدارات النماذج
عندما يتسبب تحديث النموذج في حالات تراجع غير مقبولة، ثبّت النموذج على المعرّف السابق الذي يتضمن الإصدار أثناء التحقيق. لا تستخدم اسمًا مستعارًا (مثل 'gpt-4o') في بيئة الإنتاج — استخدم دائمًا إصدارًا محددًا.
# Bad practice: alias can point to different model versions over time
client.chat.completions.create(
model='gpt-4o', # could be any version at any time
messages=[...]
)
# Good practice: pin to a specific version for production
client.chat.completions.create(
model='gpt-4o-2024-11-20', # guaranteed behavior
messages=[...]
)
# Track in config
MODEL_CONFIG = {
'sentiment_classifier': 'gpt-4o-2024-11-20',
'code_generator': 'gpt-4o-2024-11-20',
'summarizer': 'gpt-4o-mini-2024-07-18',
}اختبار الانحدار الآلي في CI
شغّل مجموعة اختبارات الانحدار تلقائيًا عند تغيّر إصدار النموذج في إعداداتك. استخدم GitHub Actions أو نظام CI مشابهًا لاكتشاف حالات التراجع قبل النشر.
# .github/workflows/prompt_regression.yml (YAML, shown as comment)
# name: Prompt Regression Tests
# on:
# push:
# paths:
# - 'config/models.json' # triggers when model version changes
# - 'prompts/*.txt' # triggers when prompts change
# jobs:
# test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Install dependencies
# run: pip install pytest openai jsonschema
# - name: Run prompt test suite
# run: pytest tests/prompts/ -v --junitxml=results.xml
# env:
# OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
# In Python: read model version from config
import json
with open('config/models.json') as f:
MODEL_CONFIG = json.load(f)
MODEL = MODEL_CONFIG['sentiment_classifier']التعامل مع حالات التراجع بين المزودين
ينطبق اختبار الانحدار أيضًا عند التبديل بين المزودين: GPT-4o → Claude، وClaude → Gemini. تكشف مجموعة الاختبارات نفسها أي prompts تتطلب تغييرات لتوافق اختلافات سلوك المزود الجديد.
def cross_provider_test(test_cases, system_prompt, providers):
all_results = {}
for provider, config in providers.items():
results, rate = run_suite_on_model(
test_cases, system_prompt, model=config['model']
)
all_results[provider] = {'rate': rate, 'results': results}
print(f'{provider}: {rate:.1%}')
# Find cases that fail on one provider but not another
for test in test_cases:
outcomes = {
p: next(r for r in all_results[p]['results'] if r['id'] == test['id'])['passed']
for p in providers
}
if not all(outcomes.values()):
failing = [p for p, passed in outcomes.items() if not passed]
print(f' {test["id"]}: FAILS on {failing}')
return all_resultsمراقبة اتجاهات معدل النجاح
ارسم معدل النجاح بمرور الوقت من خلال قراءة سجل محفوظات الاختبارات. يشير الاتجاه المتناقص إلى تدهور prompt أو انجراف النموذج. أما الانخفاض المفاجئ فيشير إلى حدث تراجع، مثل تحديث النموذج أو تغيير prompt.
import json
def plot_pass_rate_trend(history_file='test_history.jsonl'):
runs = []
with open(history_file) as f:
for line in f:
runs.append(json.loads(line))
runs.sort(key=lambda r: r['run_id'])
print('Pass rate trend:')
for run in runs[-10:]: # last 10 runs
bar = '#' * int(run['pass_rate'] * 40)
print(f"{run['run_id'][:10]} {run['model']:30} {run['pass_rate']:.0%} |{bar}|")
# Detect regression
if len(runs) >= 2:
delta = runs[-1]['pass_rate'] - runs[-2]['pass_rate']
if delta < -0.05:
print(f'ALERT: pass rate dropped {delta:.0%} since last run!')
plot_pass_rate_trend()اختبار المعرفة
عندما يتسبب إصدار جديد من النموذج في فشل اختبار، ويكشف التحقيق أن مخرجات النموذج الجديد أفضل فعلًا من المخرجات القديمة، فما الإجراء الصحيح؟
مراجعة: اختبار الانحدار عبر تحديثات النماذج
الممارسات الأساسية لاختبار الانحدار عند تحديث النماذج:
- شغّل مجموعة الاختبارات الكاملة على النموذجين القديم والجديد — قارن معدلات النجاح وحدد الفروقات بين حالات الفشل
- تتبّع إصدار النموذج الدقيق في كل سجل اختبار — وليس الاسم المستعار فقط
- حقّق في كل حالة تراجع: هل المشكلة في prompt، أم في الاختبار، أم في قدرة النموذج؟
- ثبّت النماذج في بيئة الإنتاج باستخدام معرّفات محددة تتضمن الإصدار، لا الأسماء المستعارة
- أتمت العملية في CI — وشغّلها عند تغيير إعدادات النموذج أو ملفات prompt
الدرس التالي: بناء مجموعة اختبارات prompt كاملة باستخدام أدوات داعمة.
الأسئلة الشائعة
هل درس «اختبار الانحدار عبر تحديثات النماذج» مجاني؟
نعم — نص درس «اختبار الانحدار عبر تحديثات النماذج» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة AI Prompt Engineering، انتقل إلى CoddyKit PRO. تتضمن دورة AI Prompt Engineering 4 دروس في المجموع.
ماذا ستتعلم في «اختبار الانحدار عبر تحديثات النماذج»؟
تشغيل مجموعات الاختبارات عند الترقية من GPT-4 إلى GPT-4o أو من Claude 3 إلى 3.5 تتمرن على AI Prompt Engineering مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ AI Prompt Engineering؟
لا تُشترط خبرة سابقة. AI Prompt Engineering على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «اختبار الانحدار عبر تحديثات النماذج»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس AI Prompt Engineering هذا؟
نعم. كل درس في AI Prompt Engineering يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- كتابة حالات اختبار المطالبات
- اختبار المطالبات القائم على التأكيدات
- اختبار الانحدار عبر تحديثات النماذج
- بناء مجموعة اختبارات للمطالبات