İçeriğe geç

Kılavuzlar

Eğitim: rubrik hakemiyle metin üretimi

Serbest metin yazan bir fonksiyonu, burada bir talep özetleyiciyi, biçim denetimleri ve bir rubrik hakemiyle değerlendirin; o hakem herhangi bir şeye karar vermeden önce onu bir kişinin etiketlerine karşı ölçün; sonra gerçek bir değişikliği karşılaştırın. Hakem bu makinede model ve ağ olmadan çalışır; isteğe bağlı bir adım ise yerine gerçek bir model koyar.

Ne oluşturacaksınız

Bir destek talebini bir ya da iki cümleye dönüştüren bir özetleyici. "İyi" bir dize eşleşmesi değil bir yargıdır, bu yüzden görev başarısına rubrikli bir LLM hakemi karar verir: özet, bir destek temsilcisinin ihtiyaç duyduğu olguları belirtiyor mu? İki deterministik değerlendirici biçimi denetler; bu bir referans gerektirmez. Vaka, çalıştırma, metrik, hakem ve kapı gibi terimler Kavramlar sayfasında tanımlanmıştır.

Aynı yapı çıkarım ya da başka herhangi bir üretim için de uyar: bir fonksiyon bir sözlük içinde metin döndürür, referans iyi bir yanıtın neyi içermesi gerektiğini söyler ve bir rubrik nasıl karar verileceğini söyler.

Ön koşullar

  • Python 3.11 veya üstü ve bir sanal ortamda Oloproof:
python3 -m venv .venv
. .venv/bin/activate
pip install oloproof
  • Paketle birlikte gelen örnek proje. Onu yeni bir dizine kopyalayın ve orada çalışın:
oloproof init --example generation ticket-summaries
cd ticket-summaries
  • Yedek hakem için boş bir 8799 portu (değilse iki yerde de değiştirin).

"İsteğe bağlı: hakem olarak gerçek bir model" bölümüne kadarki her adım çevrimdışı ve deterministiktir: API anahtarı yok, sağlayıcı hesabı yok, maliyet yok.

Dosyalar

ticket-summaries/
  app.py                        the summariser under test (baseline)
  app_v2.py                     the candidate change
  judge_server.py               a stand-in judge speaking the OpenAI API on 127.0.0.1
  rubrics/covers_facts.md       the judge's rubric
  oloproof.yaml                 the suite
  release.yaml                  rules for a run
  compare.yaml                  a rule for a comparison
  data/tickets.jsonl            20 cases
  labels/reviewer_verdicts.csv  one person's verdicts on the baseline's summaries
  fill_labels.py                copies those verdicts into a labelling sheet

Her komutu ticket-summaries/ içinden çalıştırın.

Yedek hakem ve ne olmadığı

Bir rubrik hakemi, bir istemi (rubrik, vakanın girdisi, expected değeri ve çıktı) bir modele gönderen ve {"pass": true|false, "rationale": "..."} geri okuyan bir değerlendiricidir. Oloproof, OpenAI sohbet API'sini konuşan her sunucuyla konuşur ve localhost üzerindeki bir sunucu anahtar gerektirmez.

judge_server.py böyle bir sunucudur, ama bir model değildir. Bir özeti yalnızca vakanın expected alanındaki must_mention altındaki her ifadeyi, büyük küçük harf gözetmeden, içerdiğinde geçirir. Bu sabit bir kuraldır, bu yüzden eğitim her makinede aynı sayıları verir. Gerçek bir model hakeminden istenen, uydurulmuş bir olguyu fark etmeyi yapamaz. Onu ikinci bir terminalde başlatın ve çalışır halde bırakın:

python judge_server.py --port 8799
stand-in judge on http://127.0.0.1:8799/v1

Uygulama ve bağdaştırıcısı

# app.py
@system(name="ticket-summariser", version="first-sentence")
def summarise(case: dict[str, Any]) -> dict[str, str]:
    return {"summary": sentences(str(case["ticket"]))[0]}

Bir Python uygulamasının bağdaştırıcısı fonksiyonun kendisidir: vakanın input değerini alır ve bir sözlük döndürür. Kendi üreticiniz için içinde modelinizi ya da zincirinizi çağırın ve metni bir anahtar altında döndürün. Oloproof onu her vaka için bir kez çağırır ve çıktıyı fonksiyonun kaynağına ve bildirilen version değerine göre önbelleğe alır; model istemcinizi, istemlerinizi ya da durumunuzu yönetmez. Fonksiyonun okuduğu dosyaları, örneğin bir istem şablonunu, system.code_paths altında listeleyin.

Veri kümesi

{"id":"t01","input":{"ticket":"Hello. Order 1042 arrived with a cracked screen. I would like a replacement, not a refund."},"expected":{"must_mention":["1042","cracked","replacement"]}}
{"id":"t06","input":{"ticket":"Please cancel my subscription at the end of this month. I am moving abroad."},"expected":{"must_mention":["cancel","end of this month"]}}

input fonksiyonun aldığı şeydir. expected hakemin okuduğu referanstır: burada tam bir referans özet değil, özetin taşıması gereken olguların bir listesidir, çünkü birçok farklı özet doğrudur. t01 için çıktı {"summary": "Hello."} olur.

Değerlendiricileri seçme

version: 1
project: ticket-summaries
dataset: data/tickets.jsonl
system:
  name: ticket-summariser
  version: first-sentence
  callable: app:summarise
  timeout_s: 30
evaluators:
  - type: json_schema
    criterion: format_valid
    field: null
    schema:
      type: object
      required: [summary]
      properties:
        summary: {type: string, minLength: 1}
      additionalProperties: false
  - type: regex
    criterion: short_enough
    field: summary
    pattern: '^.{1,160}$'
    pass_if: match
  - type: rubric_judge
    criterion: covers_facts
    provider: openai_compatible
    model: stand-in-judge
    base_url: http://127.0.0.1:8799/v1
    rubric_file: rubrics/covers_facts.md
KriterDeğerlendiriciexpected gerekir miÖlçtüğü
format_validjson_schemahayırbiçim: boş olmayan tek bir metin alanı
short_enoughregexhayırbiçim: en fazla 160 karakter
covers_factsrubric_judgeevetrubriğin tanımladığı biçimde görev başarısı

Hello. iki biçim denetimini de geçer. Yalnızca hakem onun işe yaramaz bir özet olduğunu söyler. Bir hakem referans olmadan da çalışabilir: "PASS if the summary contains no greeting" gibi bir rubrik yalnızca girdiyi ve çıktıyı okur ve expected olmayan bir vaka yine de değerlendirilir. O durumda yapamayacağı şey, olguları güvendiğiniz bir yanıta karşı denetlemektir.

Rubrik:

PASS when the summary states every fact listed under must_mention in the expected answer, in
words a support agent would recognise, and adds nothing the ticket does not say.
FAIL when any listed fact is missing, changed or contradicted.

Politika

version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
require_validated_evaluators: true
rules:
  - id: valid-format
    metric: format_valid
    kind: observed_count
    max_failures: 0
  - id: short-enough
    metric: short_enough
    kind: observed_count
    max_failures: 0
  - id: covers-facts-floor
    metric: covers_facts
    min: 0.60

require_validated_evaluators: true motorun varsayılanıdır; burada açıkça yazılmıştır, çünkü bu eğitimin amacı odur: kimsenin insanlarla karşılaştırmadığı bir hakem bir kurala karar veremez.

Çalıştırın

oloproof run
Run run_01M4... [DECIDED/COMPLETE]
Gate: BLOCK (exit 3)
│ valid-format       │ format_valid │ PASS                  │ observed_failures_within_limit │
│ short-enough       │ short_enough │ PASS                  │ observed_failures_within_limit │
│ covers-facts-floor │ covers_facts │ INSUFFICIENT_EVIDENCE │ evaluator_not_validated        │
covers-facts-floor: the judge (or model or custom evaluator) behind this rule has not been measured against
people yet, so it may not decide.
  Label a sample:  oloproof review run_01M4... --criterion covers_facts --by YOU --sample 20
  Then measure it: oloproof evaluators validate EVALUATOR_ID --by YOU (ids: oloproof evaluators list)
│ format_valid │ 100.0%   │ [83.1%, 100.0%] │ 20 / 20 observed · 0 missing · 0 excluded │
│ short_enough │ 100.0%   │ [83.1%, 100.0%] │ 20 / 20 observed · 0 missing · 0 excluded │
│ covers_facts │ 45.0%    │ [23.0%, 68.5%]  │ 9 / 20 observed · 0 missing · 0 excluded  │
Cache: execution 0 hit/20 miss; judgment 0 hit/60 miss

Biçim kuralları geçer. Hakem 20 özetten 9'unu geçirdi, ama kural evaluator_not_validated gerekçesiyle INSUFFICIENT_EVIDENCE olur ve kapı 3 ile engeller. Kural %45'e göre karar vermedi: bir hakemin hata oranı ölçülene kadar bilinmez, bu yüzden onun hükümleri üzerine kurulan bir aralık belirtilmemiş bir hata taşırdı. Motor bunu MANUAL_REVIEW ya da FAIL olarak değil, INSUFFICIENT_EVIDENCE olarak bildirir: karar vermek için gereken kanıt eksiktir ve çıktı onu sağlayan iki komutu yazdırır.

Başarısızlıkları inceleyin

oloproof inspect RUN_ID --failures
11 of 20 cases failed, errored or did not finish

t01
  output: {"summary": "Hello."}
  covers_facts: failed
    judge text, not verified: missing: 1042, cracked, replacement

t02
  output: {"summary": "I was charged twice for order 2210."}
  covers_facts: failed
    judge text, not verified: missing: 49
...

Hakemin gerekçesi "judge text, not verified" olarak gösterilir: modelin açıklamasıdır, kanıt değildir. Örüntü yine de açıktır: ilk cümle çoğu zaman bir selamlamadır.

Hakemi bir kişiye karşı ölçün

Doğrulama, hakemin hükümlerini aynı yanıtlar üzerinde bir kişinin hükümleriyle karşılaştırır. Çalıştırmanın vakalarından rastgele bir örneklemi bir sayfaya çekin. Hakemin hükümleri bu sayfaya konmaz, böylece etiketleyen kişi onlara demir atmaz:

oloproof labels export RUN_ID --criterion covers_facts --sample 20 --local --out sample.csv
Wrote 20 cases to sample.csv, drawn at random with seed 2701013296, without the judge's verdict.
  This is a local sample, good-faith only, because it was drawn on this machine.
Fill in `passed` (pass or fail) and `labelled_by` on each row you judge, then run `oloproof labels import sample.csv`.

--local, barındırılan bir çalışma alanına sormadan bu makinede çeker; tohumu motor seçer. 20 vakayla 20'lik bir örneklem hepsidir. Pratikte bir kişi her satırın talebini ve özetini okur ve passed alanını doldurur. Bu eğitim için labels/reviewer_verdicts.csv, bir gözden geçirenin temelin özetlerine verdiği hükümleri tutar ve fill_labels.py onları sayfaya kopyalar:

python fill_labels.py sample.csv
oloproof labels import sample.csv
filled 20 rows of sample.csv
Recorded 20 labels from sample.csv (20 measurement).

Gözden geçiren hakemle bir kez anlaşamadı: t02 ("I was charged twice for order 2210.") için eksik tutarı önemsiz buldu ve geçirdi. Etiketler değerlendirdikleri yanıtın tam kendisini adlandırır, bu yüzden bu hükümler yalnızca temel çalıştırmaya uygulanır.

Hakemin sürüm kimliğini bulun ve doğrulayın:

oloproof evaluators list
oloproof evaluators validate EVALUATOR_ID --by alice
covers_facts  LLM_JUDGE  UNVALIDATED  (declared)  sha256:a662...

covers_facts: sha256:a662... is now VALIDATED
  agreement 95.0% [75.1%, 99.9%] · 19 of 20 labelled cases agreed · 0 labelled but not judged · kappa 0.900
  bias -5.0 points [-32.4, +20.7] · the judge's pass rate minus the people's · 20 cases · 0 labelled but not judged
  passes what people pass 90.0% [55.4%, 99.8%] · the judge passed 9 of 10 cases people passed · 0 labelled but not judged
  fails what people fail 100.0% [69.1%, 100.0%] · the judge failed 10 of 10 cases people failed · 0 labelled but not judged

%95'i değil aralıkları okuyun: 20 etiket en az %75,1'lik bir uyum gösterir. Bir politika minimum_evaluator_agreement ile daha fazlasını isteyebilir; bu, o alt sınırı karşılaştırır ve validate altında kalan bir hakemi reddeder. Hakemler kılavuzu çıtayı, yanlılığı, yoklamaları ve terminalde etiketleme için oloproof review komutunu anlatır.

Şimdi saklanan çalıştırmayı özetleyiciyi ya da hakemi çağırmadan yeniden karara bağlayın:

oloproof gate RUN_ID --policy release.yaml
valid-format: PASS (observed_failures_within_limit)
short-enough: PASS (observed_failures_within_limit)
covers-facts-floor: INSUFFICIENT_EVIDENCE (interval_overlaps_threshold)
  no sample size would make this PASS: the observed rate (0.500) is itself below the threshold (0.600), so more cases would move it toward FAIL
Gate: BLOCK (exit 3)

Hakem artık karar verebilir ve karar özetleyici hakkındadır: verdiği oran, 0.500, hakemin %45'i değildir. Bu çalıştırmanın kör, rastgele bir ölçüm etiketi örneklemi olduğu için kapı, hakemi bu etiketlerle düzeltilmiş olarak okur (Hakemler kılavuzundaki "Judge-corrected gates"). Düzeltme PPI'dır, prediction-powered inference: etiketli örneklemi hakemin oranının insanlarınkinden ne kadar uzakta olduğunu ölçmek için kullanır ve tahmini o kadar kaydırıp aralığı o kadar genişletir. Dışa aktarmanın PPI hakkındaki notlarının kastettiği de budur. Her iki durumda da temel tabanı karşılamıyor ve daha fazla vaka bunu değiştirmez.

Gerçek bir değişiklik yapın

app_v2.py kısa nezaket ifadelerini atlar ve sonraki iki cümleyi tutar. Onu app.py üzerine kopyalayın, oloproof.yaml içinde system altında version: skip-pleasantries ayarlayın, hakemi çalışır halde tutun ve:

oloproof run
Gate: ALLOW (exit 0)
│ covers-facts-floor │ covers_facts │ PASS  │ lower_bound_meets_minimum      │
│ covers_facts │ 100.0%   │ [83.1%, 100.0%] │ 20 / 20 observed · 0 missing · 0 excluded │
Cache: execution 0 hit/20 miss; judgment 6 hit/54 miss

Hakem aynı doğrulanmış sürümdür, bu yüzden kuralı doğrudan karar verir. Altı yargı, iki sürümün aynı yazdığı özetler için önbellekten geldi. Bu yeni özetleri kimse etiketlemedi; hükümlerinin geçerli olmasını sağlayan hakemin doğrulamasıdır.

Adayı temelle karşılaştırın

version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
require_validated_evaluators: true
rules:
  - id: covers-more-facts
    kind: superiority
    metric: covers_facts
oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yaml
format_valid: +0.0 points [-23.6, +23.6] · 20 paired · 0 missing · 0 excluded
short_enough: +0.0 points [-23.6, +23.6] · 20 paired · 0 missing · 0 excluded
covers_facts: +55.0 points [+13.0, +84.4] · 20 paired · 0 missing · 0 excluded
Decisions
  covers-more-facts  covers_facts  superiority  PASS  difference_above_zero
Gate: ALLOW (exit 0)

Bir karşılaştırma PPI düzeltmesini uygulamaz: hakemin iki çalıştırmadaki kendi hükümlerini karşılaştırır; kazancın yukarıdaki düzeltilmiş 0.500'den değil hakemin %45'inden başlamasının nedeni budur. On bir özet iyileşti ve hiçbiri kötüleşmedi; kazancın aralığı tamamen sıfırın üzerindedir, bu yüzden üstünlük kuralı geçer ve komut 0 ile çıkar. Biçimi bir karşılaştırma değil, hiçbir başarısızlığa izin vermeyen çalıştırma kuralları korur: 20 vaka üzerinde iki kusursuz biçim puanının karşılaştırması ancak farkın 23,6 puan içinde olduğunu söyleyebilirdi.

İsteğe bağlı: hakem olarak gerçek bir model

Bu adım çevrimdışı yoldan ayrılır. Bir model sunucusu, bir bulut sağlayıcısıyla da bir anahtar ve para gerektirir.

  • Yerel, anahtarsız ve maliyetsiz: localhost üzerinde Ollama, LM Studio ya da llama.cpp. Bir sohbet modeli çekin (Ollama için ollama pull llama3.1).
  • Bulut: anahtarınızı tutan değişkeni adlandıran api_key_env ile provider: anthropic ya da openai, veya base_url ve api_key_env ile openai_compatible. Her vaka bir hakem çağrısıdır (ilk yanıt geçerli JSON değilse iki), sağlayıcınızın ücretleriyle faturalanır ve Oloproof daha önce değerlendirdiği bir yanıt için bir hakemi asla yeniden çağırmaz.

Taslak hakemi, evaluators: altında göründüğü gibi kendi dosyasına yazın:

# live_judge.yaml
type: rubric_judge
criterion: covers_facts
provider: openai_compatible
model: llama3.1
base_url: http://localhost:11434/v1
rubric_file: rubrics/covers_facts.md

ve onu doğrulamadan ya da benimsemeden, gözden geçireninizin zaten etiketlediği yanıtlara karşı deneyin:

oloproof evaluators try live_judge.yaml

Yerel sunucular varsayılan olarak bir seferde bir isteğe yanıt verir; kuyruktaki çağrılar zaman aşımına uğramasın diye oloproof.yaml dosyasına concurrency: {system: 2, judge: 2} ekleyin. Bu adımın bir dizüstü bilgisayarda küçük bir yerel modelle (qwen2.5vl) yapılan bir çalıştırması şunu yazdırdı:

covers_facts: draft sha256:b88a... on 20 labelled cases · 20 judged now, 0 from cache, 11 errored
  agreement 88.9% [19.1%, 99.9%] · 8 of 9 labelled cases agreed · 11 labelled but not judged · kappa 0.769

On bir çağrı zaman aşımına uğradı ve uyum aralığı her birini iki yönde de sayar, bu yüzden %19,1'e kadar iner: yanıt vermeyen bir hakem ölçülmüş olmaz. Çözüm daha büyük bir model, daha uzun bir zaman aşımı ya da daha az eşzamanlı çağrıdır. Modeli benimsemek için onu oloproof.yaml içinde yedeğin yerine koyun. Bu yeni bir değerlendirici sürümüdür: yapılandırması (model, uç nokta, rubrik) onun kimliğidir, bu yüzden yedeğin doğrulaması ona geçmez. Temeli onunla yeniden çalıştırın ve yukarıdaki gibi etiketlere karşı doğrulayın.

Sorun giderme

BelirtiNeden ve çözüm
covers_facts tamamen eksik, no_observationsHakem sunucusu çalışmıyor ya da base_url üzerinde değil. Her hakem çağrısı hata verdi; oloproof inspect RUN_ID --failures nedenini gösterir.
Doğruladıktan sonra evaluator_not_validatedHakemi (model, uç nokta, port, rubrik) değiştirdiniz ve yeni bir sürüm oluşturdunuz. Onu doğrulayın.
labels import dosyayı reddediyor ve bir satır adlandırıyorSatır, çalıştırmanın içermediği bir vakayı ya da yürütmeyi adlandırıyor; etiketlediğiniz çalıştırmadan yeniden dışa aktarın.
labels export bir çalışma alanına ulaşılamadığını söylüyorBirine giriş yapmışsınız, bu yüzden çekimi ondan istedi. --local bunun yerine burada çeker.
Bir bulut hakemi hiçbir çağrıdan önce başarısız oluyorAnahtarı, api_key_env değerinin adlandırdığı değişkende değil.

Sınırlamalar

  • Yedek hakem bir ifade eşleşmesidir. Değerlendirme kalitesini değil, iş akışını gösterir.
  • BLEU, ROUGE ya da gömme benzerliği değerlendiricileri yoktur. SDK'da @evaluator ile bir tane yazın; oloproof.yaml henüz özel bir değerlendirici adlandıramaz.
  • Bir hakem metin görür: girdinin, referansın ve çıktının JSON'u. Görüntü ya da ses görmez.
  • Yirmi etiket geniş bir uyum aralığı verir. Güvendiğiniz bir hakem için rastgele ve kör olarak daha fazla etiketleyin.
  • Yerel bir örneklem yalnızca iyi niyete dayanır. Başkalarının güvendiği bir hakem için çalıştırmayı push edin ve örneklemi barındırılan bir çalışma alanının çekmesine izin verin (Hakemler).