الانتقال إلى المحتوى

الأدلة الإرشادية

درس تعليمي: تقييم تطبيق RAG

جولة قابلة للتشغيل لتطبيق معزَّز بالاسترجاع، في مسارين: تطبيق قائم يُعامَل صندوقًا أسود تسجّل استرجاعه وسياقه واستشهاداته من الخارج، وتطبيق مرحلي يشغّله Oloproof مرحلةً مرحلة كي يستطيع oloproof diagnose إعادة تنفيذ الحالات المُخفِقة تحت تغييرات مضبوطة. يعمل كلاهما محليًا دون بيانات اعتماد أي مزوِّد.

المفاهيم وراء كل خطوة (المراحل، ووسوم الصلة، والسياق الذهبي، ووسوم الإخفاق الأربعة) موجودة في صفحة تقييم RAG؛ والمصطلحات الحالة والمُقيِّم والمقياس والفترة والبوابة موجودة في المفاهيم الأساسية. وهذه الصفحة هي الطريق العملي عبرها.

أي مسار يناسبك

تطبيقكالمسارما تحصل عليهما لا تحصل عليه
استدعاء واحد يدخل وإجابة واحدة تخرج (خدمة، أو نقطة نهاية HTTP، أو سلسلة إطار عمل لا تريد تقسيمها)أ، صندوق أسودمقاييس الاسترجاع، وفحوص الاستشهاد، وحُكّام الاستناد، والبوابة، والمقارنةالتدخلات المضبوطة: لا يعيد diagnose تنفيذ أي شيء
استرجاع وتوليد يمكنك استدعاؤهما منفصلينب، مرحليكل ما في أ، والتخزين المؤقت لكل مرحلة، وdiagnose مع السياق الذهبي وtop-k ومُعيد ترتيب بجانب ضابطتدخلات غير هذه الثلاثة

ابدأ بـ أ إن لم تكن متأكدًا. فهو لا يحتاج إلى أي تغيير في التطبيق، والانتقال إلى ب لاحقًا يحتفظ بمجموعة البيانات والمُقيِّمات والسياسة.

المتطلبات المسبقة

  • Python 3.11 أو أحدث، وOloproof مثبَّتًا (pip install oloproof).
  • مشاريع الأمثلة، وهي تأتي مع الحزمة: blackbox_rag للمسار أ وsupport_rag للمسار ب. انسخ أحدها إلى مجلد جديد واعمل هناك:
oloproof init --example blackbox_rag my-rag
cd my-rag

كل أمر أدناه يُشغَّل من داخل المجلد المنسوخ. وتُخزَّن التشغيلات والأحكام والتشخيصات في .oloproof/ هناك.

المسار أ: تطبيق قائم بوصفه صندوقًا أسود

الملفات

الملفما هو
app.pysupport_api(question)، الذي ينوب عن تطبيقك، وrun(case)، المحوِّل
server.pyالتطبيق نفسه عبر HTTP، لمتغيّر HTTP أدناه
data/corpus.jsonlقاعدة المعرفة ذات المقاطع الأربعة عشر التي يبحث فيها التطبيق
data/support.jsonl15 حالة: 13 مع وسوم صلة ومقاطع ذهبية، و2 دون أي منهما
oloproof.yamlمجموعة الاختبار: مجموعة البيانات، والنظام، والمُقيِّمات، والشرائح
oloproof.http.yamlمجموعة الاختبار نفسها مقابل خادم HTTP
release.yamlسياسة الإصدار لتشغيل واحد
compare.yamlالسياسة لمقارنة تشغيل مرشَّح بخط أساس

ما يعيده التطبيق

يتصرف support_api كتطبيق لديك أصلًا: يبحث، ويبني موجّهًا من أفضل المصادر التي تتسع لها ميزانية الكلمات، ويجيب ويستشهد. واستجابته تحمل أصلًا ما فعله:

{
  "answer": "Team plans include five seats.",
  "cited": ["kb-03"],
  "sources": [{"id": "kb-03", "score": 3.0, "text": "Team plans include five seats. ..."}],
  "prompt_sources": [{"id": "kb-03", "score": 3.0, "text": "...", "rank": 1, "tokens": 17}],
  "skipped": [{"id": "kb-05", "rank": 3, "why": "top_k"}]
}

ستختلف أسماء حقول تطبيقك. المهم أن يستطيع إخبارك، لكل سؤال، بالمصادر المرتَّبة التي استرجعها، والتي بلغت النموذج، والتي استشهد بها. وإن لم يستطع، فأضف ذلك إلى استجابته أو سجلاته أولًا: يقيس Oloproof ما يُسجَّل ولا يستنتج الاسترجاع من إجابة أبدًا.

المحوِّل

يستدعي run التطبيق دون تغيير ويعيّن الاستجابة على ثلاثة مُخرَجات فنية ذات أنواع، وهي السجلات التي تقرؤها مُقيِّمات الاسترجاع والاستشهاد:

@system(
    name="support-rag-blackbox",
    version="tutorial",
    records=("retrieval/v1", "context/v1", "citations/v1"),
)
def run(case):
    response = support_api(str(case["question"]))
    recorder = current_case()
    recorder.retrieval(
        Retrieval(
            query=case["question"],
            depth=SEARCH_DEPTH,
            candidates=tuple(
                Passage(doc_id=s["id"], score=s["score"], text=s["text"])
                for s in response["sources"]
            ),
        )
    )
    recorder.context(
        Context(
            items=tuple(
                ContextItem(doc_id=i["id"], position=i["rank"], tokens=i["tokens"], text=i["text"])
                for i in response["prompt_sources"]
            ),
            dropped=tuple(
                DroppedItem(doc_id=i["id"], position=i["rank"], reason=i["why"])
                for i in response["skipped"]
            ),
            token_budget=PROMPT_WORD_BUDGET,
        )
    )
    recorder.citations(response["cited"])
    return {"answer": response["answer"], "citations": response["cited"]}
المُخرَج الفنيالشكليقرؤه
retrieval/v1query، وdepth، وcandidates بالترتيب الذي أعادها به مسترجِعك، كلٌّ منها Passage(doc_id, chunk_id, score, text)hit_rate، recall، mrr، ndcg
context/v1items التي بلغت النموذج (doc_id، position، tokens، text)، والعناصر dropped مع reason قيمته top_k أو token_budget، وtoken_budgetcitation_validity، groundedness_judge، citation_support_judge
citations/v1ids، كلٌّ منها doc_id أو doc_id#chunk_idcitation_validity، citation_support_judge

يسجّل Oloproof المواضع كما أُعطيت ولا يعيد ترتيبها أبدًا. والمُخرَج الفني المشوَّه يوقف التشغيل برمز الخروج 2 بدلًا من أن يُخزَّن. وcase هو كائن input الخاص بالحالة، فيكون case["question"] هو السؤال من مجموعة البيانات.

لاستخدام تطبيقك أنت، استبدل جسم support_api باستدعاء له (استدعاء SDK، أو طلب HTTP) واحتفظ بـ run. ووجّه system.callable في oloproof.yaml إليه بصيغة module:function.

متغيّر HTTP

لا يستطيع نظام HTTP استدعاء المُسجِّل، فتحمل استجابته الأدلة بدلًا من ذلك، بالأشكال الثلاثة أعلاه، وتسمّي التهيئة مواضعها:

system:
  name: support-rag-http
  version: tutorial
  http:
    url: http://127.0.0.1:8766/answer
    output_path: result
    artifacts:
      retrieval/v1: evidence.retrieval
      context/v1: evidence.context
      citations/v1: evidence.citations

يقدّم server.py ذلك بالضبط. شغّله، ثم شغّل مقابله:

python server.py 8766
oloproof run --config oloproof.http.yaml

يُرسَل مُدخَل الحالة جسمًا بصيغة JSON. ويلتقط output_path المُخرَج من الاستجابة، ويسجّل كل إدخال في artifacts مسارًا منقوطًا بوصفه ذلك النوع؛ والحقل الغائب أو المشوَّه يوقف التشغيل برمز الخروج 2. والنتائج مطابقة لمسار الكائن القابل للاستدعاء أدناه. وفي خدمتك أنت، يكون كائن الأدلة عادةً حقل تصحيح تفعّله لحركة التقييم.

ما تعلنه الحالة

{"id":"seat_count","input":{"question":"How many seats does a team plan include?"},"expected":{"answer":"5 seats","relevant":[{"doc_id":"kb-03"}],"gold_context":[{"doc_id":"kb-03","text":"Team plans include five seats. ..."}]},"metadata":{"topic":"billing"}}
{"id":"office_hours","input":{"question":"What are the support office hours?"},"expected":{"answer":"09:00"},"metadata":{"topic":"account"}}
  • يسرد expected.relevant المقاطع التي تجيب عن السؤال. وتقرؤه مقاييس الاسترجاع. والحالة التي ليس لها ذلك، مثل office_hours، تُستبعد منها مع no_relevance_labels: تخرج من المقام بدلًا من أن تُحتسب نجاحًا أو إخفاقًا.
  • expected.gold_context هو نص المقطع نفسه. لا يستخدمه المسار أ أبدًا؛ ويضعه المسار ب مكان السياق المسترجَع أثناء التشخيص.

الحالات غير الموسومة أمر عادي في الممارسة، لأن وسم الصلة يتطلب جهدًا. وهي تظل تُحتسب لفحوص الإجابة والاستشهاد.

اختيار المُقيِّمات

evaluators:
  - {type: contains, criterion: answer_correct, field: answer, expected_field: answer}
  - {type: hit_rate, k: 2}
  - {type: recall, k: 2}
  - {type: citation_validity, require_citations: true}
slices: [metadata.topic]
min_slice_support: 4
  • يفحص contains أن الإجابة تحتوي على النص المتوقع. وهو فحص المهمة: هل حصل المستخدم على الإجابة الصحيحة. استخدم مطابقة تامة أو حَكَم معيار بدلًا منه حين تتفاوت الصياغة.
  • يقيس hit_rate وrecall عند k: 2 الاسترجاع عند العمق الذي يضعه التطبيق فعلًا في الموجّه. ومقياس الاسترجاع عند عمق لا يراه النموذج أبدًا يصف الفهرس، لا التطبيق.
  • يفحص citation_validity أن كل معرّف مستشهَد به يسمّي مقطعًا بلغ النموذج؛ ويُخفق require_citations: true أيضًا الإجابة التي لا تستشهد بشيء.
  • يسأل groundedness_judge وcitation_support_judge (اختياريان) نموذجًا هل الإجابة مدعومة بالسياق. ويحتاجان إلى مزوِّد ونموذج وبيانات اعتماد في متغير بيئة، ويكلّفان مالًا لكل حالة؛ انظر الحُكّام لما يجب أن يجتازه الحَكَم قبل أن يُسمح له بالحجب بالبوابة.

شريحتا relevant_position وcontext_truncated غير متاحتين هنا: فهما تقارنان المواضع بـ top-k الخاص بالتطبيق، الذي لا يعلنه إلا نظام مرحلي. وطلبهما يوقف التشغيل مع slice 'relevant_position' compares relevant positions with top_k, so it needs a staged system.

سياسة الإصدار

version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
rules:
  - id: answer-floor
    metric: answer_correct
    min: 0.70
  - id: retrieval-floor
    metric: hit_rate_at_2
    min: 0.80
  - id: citations-valid
    metric: citations_valid
    kind: observed_count
    max_failures: 0

قاعدة min لا تنجح إلا حين تتجاوز الفترة كلها الحد الأدنى، وتُخفق حين تقع الفترة كلها دونه، وتكون INSUFFICIENT_EVIDENCE فيما عدا ذلك. وقاعدة observed_count تقرر على الحالات التي شُغّلت فعلًا، دون فترة: "لا استشهاد غير صالح في مجموعة الاختبار هذه". انظر البوابة.

شغّله

oloproof run
Run run_01M4FCBPE0G550CKCVGXCNEM2P [DECIDED/COMPLETE]
Gate: BLOCK (exit 1)
│ answer-floor    │ answer_correct  │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold    │
│ retrieval-floor │ hit_rate_at_2   │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold    │
│ citations-valid │ citations_valid │ FAIL                  │ observed_failures_exceed_limit │

│ answer_correct  │ 73.3%    │ [44.8%, 92.3%] │ 11 / 15 observed · 0 missing · 0 excluded │
│ hit_rate_at_2   │ 92.3%    │ [63.9%, 99.9%] │ 12 / 13 observed · 0 missing · 2 excluded │
│ recall_at_2     │ 92.3%    │ [63.9%, 99.9%] │ 12 / 13 observed · 0 missing · 2 excluded │
│ citations_valid │ 93.3%    │ [68.0%, 99.9%] │ 14 / 15 observed · 0 missing · 0 excluded │
Cache: execution 0 hit/15 miss; judgment 0 hit/56 miss

كيف تقرؤه:

  • Gate: BLOCK (exit 1): أخفقت قاعدة (FAIL). الخروج 1 يعني FAIL؛ والخروج 3 يعني أن البوابة حجبت دون FAIL (وهنا ستكون INSUFFICIENT_EVIDENCE)؛ والخروج 0 يعني أنه لا شيء مما تحجب عليه السياسة. و[DECIDED/COMPLETE] هي حالة التنفيذ: شُغّلت كل حالة.
  • تُخفق citations-valid: إجابة واحدة لم تستشهد بشيء، ويحتسب require_citations ذلك غير صالح.
  • answer-floor هي INSUFFICIENT_EVIDENCE، لا PASS، مع أن 73.3% أعلى من 70%: مع 15 حالة تنزل الفترة حتى 44.8%، فلا تستطيع الأدلة أن تُظهر أن الحد الأدنى قد بُلغ.
  • يقرأ hit_rate_at_2 القيمة 2 excluded: الحالتان غير الموسومتين. ومقامه 13، لا 15.
  • جدول Slices الذي يلي استكشافي ولا يُحجب عليه بالبوابة أبدًا؛ والشريحة دون min_slice_support لا تعرض فترة.

افحص الإخفاقات

معرّف التشغيل في السطر الأول من مُخرَج التشغيل.

oloproof inspect RUN_ID --failures
4 of 15 cases failed, errored or did not finish

refund_review
  output: {"answer": "Every refund request on an annual plan is logged in the audit trail, and the same request is listed again on the day it was reviewed and approved."…
  answer_correct: failed

money_back
  output: {"answer": "I could not find that in the knowledge base.", "citations": []}
  answer_correct: failed
  hit_rate_at_2: failed
  recall_at_2: failed
  citations_valid: failed

security_review
  output: {"answer": "Security reviews during Enterprise onboarding include an access review and a written summary for the customer, and every review is scheduled with t…
  answer_correct: failed

seat_count
  output: {"answer": "Team plans include five seats.", "citations": ["kb-03"]}
  answer_correct: failed

يطبع oloproof inspect RUN_ID --case refund_review مُدخَل حالة واحدة والقيم المتوقعة والمُخرَج وكل حكم. والمُخرَجات الفنية المسجَّلة موجودة في الحزمة المصدَّرة:

oloproof export RUN_ID

كل سطر من .oloproof/bundles/RUN_ID/cases.jsonl هو سجل حالة واحدة؛ ويحمل حقلها artifacts ما سُجّل. ولـ money_back، يقرأ ذلك الحقل:

{"retrieval/v1": [{"candidates": [], "depth": 6, "query": "Where do I claim money back on a yearly subscription?"}], "context/v1": [{"dropped": [], "items": [], "source": "retrieval", "token_budget": 40}], "citations/v1": [{"ids": []}]}

قراءة الإخفاقات الأربعة من الأدلة المسجَّلة وحدها:

الحالةما يُظهره السجلإجراء تالٍ ذو معنى
money_backلم يُعِد الاسترجاع شيئًا: لا يشترك السؤال في أي كلمة مع مقطع الاستردادإعادة صياغة الاستعلام أو المرادفات، مقيسة بـ hit_rate_at_2
refund_review، security_reviewنجح hit_rate_at_2، لكن الإجابة جاءت من مقطع آخرافحص context/v1: هل أُسقط المقطع ذو الصلة بسبب الميزانية؟
seat_countاستُرجع المقطع الصحيح وأُبقي واستُشهد به؛ تقول الإجابة "five"، وتتوقع الحالة "5"أصلح التوقع أو تنسيق الإجابة، لا الاسترجاع

ذلك الجدول هو قراءتك للسجل. إنه ارتباط بين إخفاق ومرحلة، لا سبب مثبت: لم يُعِد شيء تنفيذ الحالة مع تغيير المرحلة.

ما يفعله diagnose على صندوق أسود

oloproof diagnose RUN_ID --intervention gold-context --criterion answer_correct
Selected: 4 failed cases with gold context (observed; no population claim)
UNRESOLVED: 4 of 4, the system is not staged, so no case was re-executed
Diagnosis sha256:8809e100ab2ec1dad8ffeacc136cd510300081a0edf01ec11f881c543ed104bc
Cases: oloproof inspect sha256:8809e100ab2ec1dad8ffeacc136cd510300081a0edf01ec11f881c543ed104bc

كل حالة UNRESOLVED مع السبب intervention_unsupported. لا يستطيع Oloproof أن يعطي صندوقًا أسود المقطع الذهبي بدلًا من استرجاعه الخاص، فلا يتظاهر بذلك. والتدخلات المضبوطة تحتاج إلى المسار ب.

أجرِ تغييرًا مرشَّحًا وقارن

يقول السجل إن money_back أخفقت في الاسترجاع. والتغيير المرشَّح يوسّع السؤال بمرادفات قبل البحث. في app.py:

EXPAND_QUERY = True

تغيير الشيفرة يغيّر نسخة النظام المسجَّلة للتشغيل. شغّل مرة أخرى، ثم قارن المرشَّح بخط الأساس:

oloproof run
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yaml

تشغيل المرشَّح وحده: citations-valid الآن PASS، وhit_rate_at_2 تقرأ 100.0% [75.2%, 100.0%]، وما زالت البوابة تحجب برمز الخروج 3 لأن answer-floor وretrieval-floor تبقيان INSUFFICIENT_EVIDENCE. والمقارنة:

Comparison sha256:2feb024c… of run_01M4FCCJYCVVYA8NB4XZDV6YMB against run_01M4FCCHVBG9WHDP7G5HFX7RDT · 15 paired cases
answer_correct: +6.7 points [-26.5, +40.8] · 15 paired · 0 missing · 0 excluded
hit_rate_at_2: +7.7 points [-29.8, +45.5] · 13 paired · 0 missing · 2 excluded
  excluded 2: no_relevance_labels
recall_at_2: +7.7 points [-29.8, +45.5] · 13 paired · 0 missing · 2 excluded
  excluded 2: no_relevance_labels
citations_valid: +6.7 points [-26.5, +40.8] · 15 paired · 0 missing · 0 excluded
20 exploratory slice differences not shown; add --slices to list them
Decisions
  answers-not-worse  answer_correct  non-inferiority, margin 5.0 points  INSUFFICIENT_EVIDENCE  interval_overlaps_margin
    about 38 more paired cases would decide it, if the difference holds (53 in total at 7% discordance)
  citations-not-worse  citations_valid  non-inferiority, margin 2.0 points  INSUFFICIENT_EVIDENCE  interval_overlaps_margin
    about 68 more paired cases would decide it, if the difference holds (83 in total at 7% discordance)
Gate: BLOCK (exit 3)

أصلح التغيير الحالة التي استهدفها (إجابة إضافية واحدة، +6.7 نقطة على 15 حالة مزدوجة). وما زالت المقارنة لا تستطيع إثبات أن المرشَّح ليس أسوأ من خط الأساس بأكثر من الهامش: تترك 15 حالة مزدوجة فترة عرضها نحو 67 نقطة. ويقول سطر التخطيط كم حالة مزدوجة إضافية ستحسم المسألة لو ثبت الفرق. والإجراء التالي مجموعة اختبار أكبر، لا هامش مختلف. انظر مقارنة تشغيلين وقواعد المقارنة.

المسار ب: تطبيق مرحلي مع تشخيص

الملفات المرحلية

يشغّل المسار ب مثال support_rag، الموصوف في صفحة تقييم RAG. انسخه:

oloproof init --example support_rag my-staged-rag
cd my-staged-rag
الملفما هو
app.pySupportRag، صنف مزخرَف بـ @rag_system: retrieve(input, depth)، generate(input, context)، count_tokens(passage)
data/corpus.jsonl، data/support.jsonlقاعدة المعرفة، و13 حالة، لكل منها relevant وgold_context
oloproof.yamlيشير system.rag إلى الصنف ويضبط depth وtop_k وtoken_budget وindex_version
release.yaml، compare.yamlالسياسات نفسها كما في المسار أ

الفرق عن المسار أ هو من يجمّع السياق. هنا يستدعي Oloproof retrieve، ويحتفظ بأول top_k من المرشَّحات، ويُسقط المقاطع التي تتجاوز token_budget، ويمرّر الباقي إلى generate. ولأنه يُبقي المراحل منفصلة، يستطيع تخزينها مؤقتًا كلًّا على حدة وإعادة تنفيذ التوليد بسياق مختلف. ولتكييف تطبيقك أنت، استبدل جسمَي retrieve (استدعِ فهرسك، وأعِد Retrieval(candidates=[Passage(...)]) بترتيب مسترجِعك) وgenerate (استدعِ نموذجك بالمقاطع المعطاة). واضبط index_version على شيء يتغير حين يتغير فهرسك: فهو جزء من هوية الاسترجاع، والقيمة القديمة تعيد استخدام استرجاعات مخزّنة مؤقتًا مقابل فهرس لم يعد يعيدها.

وتتيح التهيئة نفسها أيضًا شريحتَي relevant_position وcontext_truncated، ومُقيِّم ndcg على عمق الاسترجاع الكامل.

شغّل مجموعة الاختبار المرحلية

oloproof run
Gate: BLOCK (exit 3)
│ answer-floor    │ answer_correct  │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold    │
│ retrieval-floor │ hit_rate_at_2   │ INSUFFICIENT_EVIDENCE │ interval_overlaps_threshold    │
│ citations-valid │ citations_valid │ PASS                  │ observed_failures_within_limit │
│ answer_correct  │ 69.2%    │ [38.5%, 91.0%]  │ 9 / 13 observed · 0 missing · 0 excluded     │
│ hit_rate_at_2   │ 92.3%    │ [63.9%, 99.9%]  │ 12 / 13 observed · 0 missing · 0 excluded    │
│ recall_at_2     │ 92.3%    │ [63.9%, 99.9%]  │ 12 / 13 observed · 0 missing · 0 excluded    │
│ ndcg_at_6       │ 0.866    │ [0.506, 0.990]  │ mean of 13 observed · 0 missing · 0 excluded │
│ citations_valid │ 100.0%   │ [75.2%, 100.0%] │ 13 / 13 observed · 0 missing · 0 excluded    │
Cache: execution 0 hit/13 miss; judgment 0 hit/65 miss
Stages: retrieve 0 hit/13 miss; generate 0 hit/13 miss

سطر Stages هو التخزين المؤقت الخاص بالنظام المرحلي. الخروج 3: لم يُخفق شيء، لكن قاعدتين تفتقران إلى الأدلة اللازمة لـ PASS.

شخّص بالسياق الذهبي، بجانب ضابط

oloproof diagnose RUN_ID --intervention gold-context --criterion answer_correct
Selected: 4 failed cases with gold context (observed; no population claim)
Control: 0 of 4 passed when re-executed without the intervention
Recovered under gold context: 3 of 4
RETRIEVAL_MISS: 1 of 4, recovered; no relevant evidence was retrieved
CONTEXT_ASSEMBLY_LOSS: 2 of 4, recovered; relevant evidence within top-k was left out of the context
GENERATION_FAILURE: 1 of 4, still failed with the gold context
Implicated: context budget, in 2 of the 3 recovered failures.
Candidate experiment: a larger token budget. This is a hypothesis to test, not an established cause.
Candidate experiment: smaller chunks. This is a hypothesis to test, not an established cause.
Diagnosis sha256:50a6124f…
Child runs: gold context run_…, control run_…
Cases: oloproof inspect sha256:50a6124f…

يُنشأ تشغيلان فرعيان من الحالات المُخفِقة: أحدهما مع gold_context الخاص بالحالة مكان السياق المسترجَع، وضابط يعيد تنفيذها دون تغيير. والضابط هو ما يجعل القراءة آمنة: الحالة التي تنجح في إعادة تشغيل عادية كانت غير مستقرة، لا مشخَّصة. ويخرج diagnose بالرمز 0 أيًا كان ما يجده؛ فهو لا يقرر شيئًا بشأن الإصدار.

oloproof inspect DIAGNOSIS_ID
money_back: RETRIEVAL_MISS, relevant_not_retrieved, strength intervention_recovery, best relevant position none
refund_review: CONTEXT_ASSEMBLY_LOSS, relevant_dropped_from_context, strength intervention_recovery, best relevant position 2
seat_count: GENERATION_FAILURE, fails_with_gold_context, strength intervention_non_recovery, best relevant position 1
security_review: CONTEXT_ASSEMBLY_LOSS, relevant_dropped_from_context, strength intervention_recovery, best relevant position 2

قراءة الوسوم

الوسمما رُصدما لا يثبته
RETRIEVAL_MISSلم يُسترجع أي مقطع ذي صلة، ونجحت الحالة مع المقطع الذهبيأن الاسترجاع هو الخلل الوحيد، أو أن تغييرًا معينًا في الاسترجاع سيصلحه
RANKED_OUTاستُرجع مقطع ذو صلة تحت top_k، ونجحت الحالة مع المقطع الذهبيأن توسيع top-k سيساعد حالات أخرى
CONTEXT_ASSEMBLY_LOSSأُسقط من السياق مقطع ذو صلة ضمن top-k، ونجحت الحالة مع المقطع الذهبيأي ميزانية ستكفي
GENERATION_FAILUREظلت الحالة تُخفق والمقطع الذهبي في متناولهاأن الخطأ في النموذج، لا في الموجّه أو التوقع
UNRESOLVEDلا يمكن استنتاج شيء: النظام غير مرحلي (intervention_unsupported)، أو تعافت الحالة تحت الضابط (unstable_under_control)، أو ليس لها وسوم صلة (no_relevance_labels)، أو الأدلة مفقودةأي شيء عن الحالة

كل وسم ارتباط بين إخفاق ومرحلة تحت تدخّل واحد على هذه الحالات. وليس سببًا مثبتًا: "Implicated" و"Candidate experiment" هما أقوى كلمتين يستخدمهما المُخرَج، والأعداد لا تصف إلا الحالات المختارة ("no population claim"). وseat_count تذكير جيد: تُخفق مع المقطع الصحيح لأن قاعدة المعرفة تقول "five" والحالة تتوقع "5"، وهو ما لا يصلحه أي تغيير في الاسترجاع.

حالات مع مقاطع ذهبية ومن دونها

لا يمكن إعادة تنفيذ إلا الحالات المُخفِقة التي تعلن expected.gold_context. احذف المقطع الذهبي من seat_count وmoney_back (ووسم الصلة من money_back) فيُبلغ الأمر نفسه عن:

Selected: 2 failed cases with gold context (observed; no population claim)
Excluded: 2 failed cases, no_gold_context - declare the passages that would have answered the case in its `expected.gold_context`, as a list of `{doc_id, text}` objects; an intervention needs them to tell a retrieval failure from a generation one
Control: 0 of 2 passed when re-executed without the intervention
Recovered under gold context: 2 of 2
CONTEXT_ASSEMBLY_LOSS: 2 of 2, recovered; relevant evidence within top-k was left out of the context

الحالات المستبعدة مسرودة، لا مُسقَطة بصمت. ولاحظ أيضًا ما يفعله حذف وسم صلة بالتشغيل نفسه: ارتفع hit_rate_at_2 إلى 100.0% (12 / 12 مرصودة، 1 مستبعدة)، لأن الحالة الوحيدة التي فاتها الاسترجاع لم تعد تُقاس. الحالات غير الموسومة تخرج من المقام؛ ولا تُحتسب نجاحات، ويمكن لمقياس على حالات أقل أن يبدو أفضل مما هو عليه التطبيق. ضع الوسوم على الحالات الصعبة أولًا.

اختبر إصلاحًا قبل إجرائه: top-k ومُعيد ترتيب

تدخّلان آخران يعيدان تشغيل الاسترجاع المسجَّل بإعداد مختلف، فلا يُستدعى المسترجِع مرة أخرى:

oloproof diagnose RUN_ID --intervention top-k --top-k 4 --criterion answer_correct
Recovered under top-k 4: 0 of 4
Confirmed under top-k 4: 0 of 0 RANKED_OUT cases also recovered
Labels from gold context (diagnosis sha256:50a6124f…): 3 of 4 recovered

مُعيد الترتيب دالة (input, candidates) -> candidates تكتبها أنت. احفظها باسم rerank.py بجانب app.py:

"""A candidate reranker: shorter passages first, so more of them fit the token budget."""

from oloproof import Passage


def shortest_first(input: dict, candidates: list[Passage]) -> list[Passage]:
    return sorted(candidates, key=lambda passage: len((passage.text or "").split()))
oloproof diagnose RUN_ID --intervention reranker --reranker rerank:shortest_first --criterion answer_correct
Recovered under reranker rerank:shortest_first: 0 of 4
Confirmed under reranker rerank:shortest_first: 0 of 0 RANKED_OUT cases also recovered

لم يُعِد أيٌّ منهما شيئًا، وهو ما تنبأت به وسوم السياق الذهبي: لم يكن أي إخفاق هنا مقطعًا مرتَّبًا تحت الحد بقليل. وكل إعادة تشغيل تحمل وسوم السياق الذهبي معها، فتُقرأ التشخيصات معًا.

شغّل التجربة التي سمّاها التشخيص، وقارن

ارفع token_budget إلى 120 في oloproof.yaml، ثم:

oloproof run
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yaml
Stages: retrieve 13 hit/0 miss; generate 7 hit/6 miss

أُعيد استخدام كل استرجاع، لأن top_k والميزانية خارج هوية الاسترجاع؛ ولم يُعَد توليد إلا الحالات الست التي تغيّر سياقها.

answer_correct: +0.0 points [-33.6, +33.6] · 13 paired · 0 missing · 0 excluded
Decisions
  answers-not-worse  answer_correct  non-inferiority, margin 5.0 points  INSUFFICIENT_EVIDENCE  interval_overlaps_margin
  citations-not-worse  citations_valid  non-inferiority, margin 2.0 points  INSUFFICIENT_EVIDENCE  interval_overlaps_margin
Gate: BLOCK (exit 3)

لم تساعد التجربة: لم تغيّر حالة واحدة حكمها، فالفرضية التي قدّمها التشخيص غير مدعومة لهذه الحالات. وتلك نتيجة مفيدة. والتجربة التالية مقاطع أصغر، أو موجّهات حالتَي تجميع السياق؛ وتحتاج seat_count إلى إصلاح توقعها.

استكشاف الأخطاء وإصلاحها

العَرَضالسببالإصلاح
Configuration error: slice 'relevant_position' ... needs a staged systemشريحة مواضع على نظام قابل للاستدعاء أو نظام HTTPاحذف الشريحة، أو انتقل إلى المسار ب
يتوقف التشغيل برمز الخروج 2 وmalformed retrieval/v1 artifactحقل لا يسمح به المخطط، أو مرشَّحات أكثر من depthلا تعيّن إلا الحقول الموثّقة؛ واضبط depth على عدد المُعاد على الأقل
يقرأ citations_valid القيمة 0 / 0 observed · 15 missing وقاعدته INSUFFICIENT_EVIDENCE مع no_observationsلم يسجّل المحوِّل citations/v1 (أو context/v1)؛ وكل حالة كهذه مفقودة، لا ناجحةسجّل كليهما في كل مسار عبر المحوِّل، بما في ذلك "لا إجابة"؛ ويُظهر oloproof inspect RUN_ID --failures الخطأ لكل حالة
يُظهر مقياس استرجاع كثيرًا من excludedحالات دون expected.relevantضع عليها وسومًا، أو اقبل المقام الأصغر عن وعي
يقول diagnose UNRESOLVED ... not stagedالمسار أمتوقع؛ استخدم المسار ب للتدخلات
يرفض diagnose مع an intervention must re-execute the same systemتغيّرت الشيفرة أو التهيئة منذ التشغيلشخّص تشغيلًا للنسخة الحالية، أو استعِد النسخة التي شُغّلت
يختار التشخيص حالات أقل مما أخفقحالات مُخفِقة دون expected.gold_contextأضف المقاطع الذهبية؛ والحالات المستبعدة مسمّاة في المُخرَج
يُعاد استخدام الاسترجاعات بعد تغيّر الفهرسindex_version لم يتغيرغيّر index_version حين يتغير الفهرس

القيود

  • يستدعي Oloproof تطبيقك؛ لكنه لا يستضيفه ولا يعزله ولا يعيد ضبطه. وفهرسه وذاكرات تخزينه المؤقت وأي حالة يحتفظ بها لك.
  • على الصندوق الأسود، لا تتاح التدخلات: يَسِم diagnose كل حالة UNRESOLVED ولا يعيد تنفيذ شيء.
  • التدخلات هي السياق الذهبي وtop-k ومُعيد الترتيب. ولا يوجد تدخّل للتقطيع أو التضمين أو الموجّه.
  • تصف وسوم التشخيص الحالات المُخفِقة المختارة تحت تدخّل واحد بجانب ضابط. وهي تربط إخفاقًا بمرحلة؛ ولا تثبت سببًا، ولا تدّعي شيئًا عن حالات لم تُختر.
  • تحتاج مقاييس الاسترجاع إلى وسوم صلة، ويحتاج التشخيص إلى مقاطع ذهبية؛ ولا ينشئ Oloproof أيًا منهما.
  • الأمثلة الحتمية تنوب عن مسترجِع ونموذج حقيقيين. والنموذج الحي في generate أو مُقيِّم الحَكَم يستدعي مزوِّدًا، ويحتاج إلى بيانات اعتماد، ويكلّف مالًا لكل حالة.
  • ما يعمل وأين، SDK مقابل YAML مقابل المتصفح، موجود في ما يعمل اليوم.