İçeriğe geç

Kılavuzlar

Eğitim: denetimler ve onları gören bir hakemle görüntüler

Görüntü üreten bir fonksiyonu, burada bir başlık da yazan bir ürün küçük resim oluşturucusunu, değerlendirin. Küçük resimleri model gerektirmeyen ölçümlerle denetleyin, başlıkları her küçük resmi gören bir modelle değerlendirin, o hakemi bir kişiye karşı ölçün, sonra gerçek bir değişikliği yayına alın. Her adım bu makinede model ve ağ olmadan çalışır; isteğe bağlı bir adım ise yerine gerçek bir görsel model koyar.

Ne oluşturacaksınız

Bir katalog hizmeti bir ürün fotoğrafı alır, bir küçük resim kaydeder ve ürünün rengini adlandıran tek satırlık bir başlık yazar. Bir sürümün yayına alınıp alınamayacağına üç soru karar verir:

  • Her küçük resim kataloğa uyuyor mu: bir web biçimi, en fazla 256'ya 256 piksel, en fazla 50 kB? Bu bir ölçümdür ve media_check tarafından küçük resmin baytlarından yapılır.
  • Her küçük resim hâlâ ürünün fotoğrafı mı, boş bir görüntü, bir kırpıntı ya da başka bir ürün değil mi? image_matches_reference onu algısal hash ile fotoğrafla karşılaştırır.
  • Her başlık, bir alışverişçinin gördüğü rengi adlandırıyor mu? Bu göz gerektirir, bu yüzden bir rubrik hakemine küçük resim gösterilir.

Fotoğraflar ve küçük resimler proje klasöründe kalır. Sistem onları başvuruyla kaydeder (media/v1): her dosyanın nerede olduğu, türü, boyutu ve sha256 değeri. Vaka, çalıştırma, hakem ve kapı gibi terimler Kavramlar sayfasında tanımlanmıştır; medya hakkındaki her şey Görüntü, ses ve video sayfasındadır.

Ön koşullar

  • Python 3.11 veya üstü ve görüntüleri karşılaştırmak için Pillow ekleyen medya ekiyle Oloproof:
python3 -m venv .venv
. .venv/bin/activate
pip install 'oloproof[media]'
  • Paketle birlikte gelen örnek proje. Onu yeni bir dizine kopyalayın ve orada çalışın:
oloproof init --example media product-thumbnails
cd product-thumbnails
  • Yedek hakem için boş bir 8798 portu (değilse iki yerde de değiştirin).

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

Dosyalar

product-thumbnails/
  app.py                              the thumbnailer under test (baseline)
  app_v2.py                           the candidate change
  judge_server.py                     a stand-in vision judge speaking the OpenAI API on 127.0.0.1
  rubrics/caption_names_colour.md     the judge's rubric
  oloproof.yaml                       the suite
  release.yaml                        rules for a run
  compare.yaml                        a rule for a comparison
  data/products.jsonl                 20 cases
  photos/                             the 20 product photos the cases name
  make_photos.py                      how the photos were drawn
  labels/reviewer_verdicts.csv        one person's verdicts on the baseline's captions
  fill_labels.py                      copies those verdicts into a labelling sheet

Her komutu product-thumbnails/ içinden çalıştırın.

Uygulama görüntülerini kaydeder

# app.py (excerpt)
@system(name="thumbnailer", version=VERSION, records=("media/v1",))
def describe(case: dict[str, Any]) -> dict[str, str]:
    photo_path = HERE / case["photo"]
    photo = Image.open(photo_path).convert("RGB")
    thumb = photo.copy()
    thumb.thumbnail((320, 320))
    out = HERE / "thumbs" / VERSION / photo_path.name
    out.parent.mkdir(parents=True, exist_ok=True)
    thumb.save(out)
    given = media_file(photo_path, role="input")
    made = media_file(out, width=thumb.width, height=thumb.height)
    current_case().media([given, made])
    centre = photo.getpixel((photo.width // 2, photo.height // 2))
    return {"caption": f"A {colour_name(centre)} product."}

media_file(path) bir dosyayı tanımlar: file:// konumu, MIME türü, boyutu ve sha256 değeri, dosyanın adıyla adlandırılmış olarak. role="input" sistemin aldığı fotoğrafı işaretler; küçük resim bir çıktıdır, varsayılan da budur. current_case().media(...) ikisini tek bir media/v1 yapıtı olarak kaydeder ve oloproof.yaml içindeki records: [media/v1] sistemin onu kaydettiğini bildirir. Hiçbir şey kopyalanmaz: bir denetim ya da bir hakem her dosyayı sonradan yeniden okur ve baytları artık kayıtla eşleşmeyen bir dosyayı reddeder.

Bu temelin iki kusuru var. Küçük resimleri 320 piksel genişliğindedir ve başlığı fotoğrafın ortadaki pikselinin rengini adlandırır; ürün bir kenarda durduğunda bu piksel arka plandır. Her sürüm küçük resimlerini thumbs/<version>/ altına yazar, bu yüzden sonraki bir çalıştırma daha önceki bir çalıştırmanın kaydettiği dosyaların üzerine asla yazmaz.

Veri kümesi

{"id": "p03", "input": {"photo": "photos/p03.png"}, "expected": {"photo": "photos/p03.png", "colour": "yellow", "shape": "triangle"}}

input sistemin aldığı şeydir. expected.photo küçük resmin karşılaştırıldığı referanstır; colour ve shape vakayı okuyan bir kişi için oradadır ve hiçbir değerlendirici onları okumaz.

Değerlendiricileri seçme

evaluators:
  # The catalogue's limits, measured from the thumbnail's bytes: a web format, at most 256 by
  # 256 pixels, at most 50 kB.
  - type: media_check
    criterion: thumbnail_fits
    kind: image
    formats: [png, jpeg, webp]
    max_width: 256
    max_height: 256
    max_bytes: 50000
  # The thumbnail is still the product's photo: a perceptual hash within 10 of 64 bits.
  - type: image_matches_reference
    criterion: same_photo
    reference_field: photo
    max_distance: 10
  # The caption, judged by a model that sees the thumbnail.
  - type: rubric_judge
    criterion: caption_names_colour
    provider: openai_compatible
    model: stand-in-vision
    base_url: http://127.0.0.1:8798/v1
    rubric_file: rubrics/caption_names_colour.md
    media: output

media_check her çıktı görüntüsünü ölçer: biçimi ilk baytlarından, boyutu başlığından, asla sistemin bildirdiğinden değil. image_matches_reference küçük resmin ve expected.photo değerinin adlandırdığı fotoğrafın hash'ini alır ve hash'ler 64 bitlerinin en fazla 10'unda farklı olduğunda geçer; yeniden boyutlandırma ya da yeniden sıkıştırma bir hash'i birkaç bit oynatır, başka bir resim çok bit oynatır. İkisi de model çağırmaz, bu yüzden ikisi de ilk çalıştırmadan itibaren karar verir.

media: output vakanın çıktı görüntülerini hakemin isteğine ekler, her biri isteminde adlandırılmış olarak. Bir hakem, insanların etiketleri onlarla uyuştuğunu gösterene kadar hiçbir şeye karar vermez, bu yüzden üçüncü kural bunu bekler.

Yedek hakem

Bir rubrik hakemi istemini ve eklenen görüntüleri bir modele gönderir ve {"pass": true|false, "rationale": "..."} geri okur. Burada model, aynı API'yi 127.0.0.1 üzerinde konuşan ve bir model olmayan judge_server.py dosyasıdır: eklenen küçük resmin kodunu çözer, arka planın beyazı ve grisi dışındaki en yaygın rengini bulur ve onu adlandıran bir başlığı geçirir. Onu ikinci bir terminalde başlatın ve çalışır halde bırakın:

python judge_server.py --port 8798

Politika

version: 1
confidence_level: 0.95
block_on: [FAIL, INSUFFICIENT_EVIDENCE, MANUAL_REVIEW]
require_validated_evaluators: true
rules:
  - id: thumbnails-fit
    metric: thumbnail_fits
    kind: observed_count
    max_failures: 0
  - id: same-photo
    metric: same_photo
    kind: observed_count
    max_failures: 0
  - id: caption-floor
    metric: caption_names_colour
    min: 0.80

Her küçük resim uymalı ve kendi fotoğrafı olmalıdır. Başlıkların en az %80'i doğru rengi adlandırmalıdır; bu, yalnızca aralığın alt sınırı %80'i aştığında karara bağlanır.

Çalıştırın

oloproof run
Gate: BLOCK (exit 1)
│ thumbnails-fit │ thumbnail_fits       │ FAIL                  │ observed_failures_exceed_limit   │
│ same-photo     │ same_photo           │ PASS                  │ observed_failures_within_limit   │
│ caption-floor  │ caption_names_colour │ INSUFFICIENT_EVIDENCE │ evaluator_not_validated          │
│ thumbnail_fits       │ 0.0%     │ [0.0%, 16.9%]   │ 0 / 20 observed · 0 missing · 0 excluded  │
│ same_photo           │ 100.0%   │ [83.1%, 100.0%] │ 20 / 20 observed · 0 missing · 0 excluded │
│ caption_names_colour │ 60.0%    │ [36.0%, 80.9%]  │ 12 / 20 observed · 0 missing · 0 excluded │

Hiçbir küçük resim uymuyor, her küçük resim kendi fotoğrafı ve 20 başlıktan 12'si doğru rengi adlandırıyor. Hakemin kuralı karara bağlanmamıştır, çünkü hakemi henüz kimse ölçmedi.

Başarısızlıkları inceleyin

oloproof inspect RUN_ID --failures
p03
  output: {"caption": "A white product."}
  thumbnail_fits: failed
    measured: p03.png: width 320 px is above 256 px
  caption_names_colour: failed
    judge text, not verified: the product is yellow; the caption says 'a white product.'

Bir denetimin gerekçesi measured olarak işaretlenmiş bir ölçümdür; bir hakeminki ise kimsenin denetlemediği kendi sözleridir. Fotoğraflar ve küçük resimler, oloproof export RUN_ID sonrasında, çalışma tezgâhında vakanın sayfasında her hükmün yanında da görünür ve bu klasörden okunur; barındırılan bir çalışma alanı onları tarayıcınızın oloproof collect üzerinden getirmesini sağlar ve onları asla tutmaz (Görüntü, ses ve video).

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

Çalıştırmanın vakalarından rastgele bir örneklemi, hakemin hükümleri olmadan bir sayfaya çekin, bir kişinin her küçük resme ve başlığa bakmasını sağlayın ve söylediklerini içe aktarın. Burada fill_labels.py o kişinin yerini tutar ve onun hükümlerini labels/reviewer_verdicts.csv dosyasından kopyalar:

oloproof labels export RUN_ID --criterion caption_names_colour --sample 20 --local --out sample.csv
python fill_labels.py sample.csv
oloproof labels import sample.csv

Sonra hakemi bu etiketlere karşı ölçün ve bunu kimin yaptığını kaydedin:

oloproof evaluators list
oloproof evaluators validate EVALUATOR_ID --by alice
caption_names_colour: sha256:53605dd6... is now VALIDATED
  agreement 100.0% [83.1%, 100.0%] · 20 of 20 labelled cases agreed · 0 labelled but not judged · kappa 1.000

Görüntüleri gören bir hakem, tıpkı metin okuyan bir hakem gibi ölçülür. Barındırılan bir çalışma alanında inceleme kuyruğu, her vakanın görüntülerini inceleyiciye gösterir; görüntüleri inceleyicinin tarayıcısı toplayıcınızdan getirir (Hakemler).

oloproof gate RUN_ID --policy release.yaml
thumbnails-fit: FAIL (observed_failures_exceed_limit)
same-photo: PASS (observed_failures_within_limit)
caption-floor: INSUFFICIENT_EVIDENCE (interval_overlaps_threshold)
Gate: BLOCK (exit 1)

Hakem artık karar verebilir ve %60 yeterli değildir.

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

app_v2.py 256 piksellik küçük resimler üretir ve ürün nerede olursa olsun fotoğrafın arka plan dışındaki en yaygın rengini adlandırır. Onu app.py üzerine kopyalayın, oloproof.yaml içinde system altında version: main-colour ayarlayın, hakemi çalışır halde tutun ve:

oloproof run
Gate: ALLOW (exit 0)
│ thumbnails-fit │ thumbnail_fits       │ PASS  │ observed_failures_within_limit │
│ same-photo     │ same_photo           │ PASS  │ observed_failures_within_limit │
│ caption-floor  │ caption_names_colour │ PASS  │ lower_bound_meets_minimum      │

Hakem, doğrulanmış olanla aynı değerlendirici sürümüdür, bu yüzden hükümleri sayılır.

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

oloproof compare CANDIDATE_RUN_ID BASELINE_RUN_ID --policy compare.yaml
thumbnail_fits: +100.0 points [+52.9, +100.0] · 20 paired · 0 missing · 0 excluded
caption_names_colour: +40.0 points [+1.8, +72.7] · 20 paired · 0 missing · 0 excluded
  captions-better  caption_names_colour  superiority  PASS  difference_above_zero

İsteğe bağlı: gerçek bir görsel model

Bu adım çevrimdışı yoldan ayrılır. Görüntüleri okuyan bir model gerektirir: yerelde, bir görsel modelle Ollama (ollama pull qwen2.5vl), anahtarsız ve maliyetsiz; bulutta, api_key_env ile provider: anthropic ya da openai, her kelime gibi her görüntü için de faturalanır.

# live_judge.yaml
type: rubric_judge
criterion: caption_names_colour
provider: openai_compatible
model: qwen2.5vl
base_url: http://localhost:11434/v1
rubric_file: rubrics/caption_names_colour.md
media: output
timeout_s: 300
oloproof evaluators try live_judge.yaml

Bu, inceleyicinizin etiketlediği vakaları gerçek modelle değerlendirir ve onu benimsemeden uyumunu bildirir. Onu benimsemek için oloproof.yaml içinde yedeğin yerine koyun: yeni bir model yeni bir değerlendirici sürümüdür, bu yüzden onu yukarıdaki gibi etiketlere karşı doğrulayın.

Sorun giderme

BelirtiNeden ve çözüm
caption_names_colour tamamen eksikHakem sunucusu çalışmıyor ya da base_url üzerinde değil; oloproof inspect RUN_ID --failures nedenini gösterir.
image_matches_reference Pillow'u adlandırarak çalıştırmayı durduruyorMedya ekini kurun: pip install 'oloproof[media]'.
Bir vaka media_unavailable ile eksikKaydedilen bir dosya çalıştırmadan sonra taşındı ya da silindi. Bir çalıştırmanın kaydettiği dosyaları, çalıştırmayı tuttuğunuz sürece tutun.
Bir çalıştırma is not the recorded content ile duruyorKaydedilen bir dosya çalıştırmadan sonra değiştirildi. Bir denetim ya da hakem farklı baytları asla kaydedilmiş olanlar gibi okumaz; her sürümün dosyalarını kendi yerine yazın.
Doğruladıktan sonra evaluator_not_validatedHakemi (model, uç nokta, port, rubrik, media) değiştirdiniz ve yeni bir sürüm oluşturdunuz. Onu doğrulayın.

Sınırlamalar

  • Yedek hakem pikselleri sayar. Değerlendirme kalitesini değil, iş akışını gösterir.
  • Algısal hash rengi değil, yerleşimi ve ışığı okur: fotoğrafın bir küçük resmini boş bir görüntüden ya da farklı bir sahneden ayırır, ama aynı stüdyodaki bir ürünü bir başkasından ayırmaz. Geniş boş alanları olan düz grafikler onu fotoğraflardan daha çok oynatır.
  • Yirmi etiket geniş bir uyum aralığı verir. Güvendiğiniz bir hakem için rastgele ve kör olarak daha fazla etiketleyin.
  • Ses ve video başka ayarlarla aynı şekilde çalışır: bkz. Görüntü, ses ve video.