Ürününüz için birisi bir fotoğraf yüklüyor ve bunu bir kameranın çektiğini iddia ediyor. Arka ucunuz bunu kanıtlayabilir veya çürütebilir mi? Görüntü oluşturucular artık insan gözüne gerçek görünen sonuçlar üretiyor, bu yüzden "gözlere güvenmek" bir süre önce işe yaramaz hale geldi. İyi haber şu ki, işe yarar bir yanıt sunmak için kendi modelinizi eğitmenize gerek yok. İki bağımsız sinyali, yani kriptografik bir köken manifestini ve bir makine öğrenimi sınıflandırıcısını, tek başına herhangi bir sinyalden daha dürüst olan tek bir kararda birleştirebilirsiniz. Bu eğitim, POST /verify uç noktasına sahip tek bir servis olarak bu arka ucu inşa etme sürecini adım adım anlatıyor. Ona bir görüntü verirsiniz, o da bir güven puanı ve bulduğu köken detaylarıyla birlikte bir JSON kararı döndürür. Sunucu için Python ve FastAPI, köken sinyali için açık kaynak C2PA araçları ve sınıflandırıcı sinyali için barındırılan bir algılama API'si kullanacağız. Bu bir API projesi olduğundan, uç nokta sözleşmesini de önce tasarlayacak ve bunu alay etmek ve test etmek için Apidog'u kullanacağız, böylece arka uç kodu bitmeden ön uç ekibiniz entegrasyona başlayabilir.
TL;DR
POST /verify'yi gösteren bir FastAPI servisi inşa edeceksiniz. Bu servis bir görüntü yüklemesini kabul edecek, c2pa-python kütüphanesiyle C2PA İçerik Kimlik Bilgileri manifestini çıkaracak ve doğrulayacak, ikinci bağımsız bir sinyal olarak barındırılan bir AI algılama sınıflandırıcısını çağıracak ve tek bir JSON kararı (likely_authentic, likely_ai veya uncertain) ile bir güven puanı ve ham köken detaylarını döndürecek. Ayrıca uç nokta için OpenAPI şemasını tasarlayacak ve Apidog'u kullanarak bir mock sunucu oluşturacak ve ona karşı uç nokta testleri çalıştıracaksınız.
Neden bir yerine iki sinyal
Herhangi bir kod yazmadan önce, neyi tespit ettiğiniz hakkında net olmak yardımcı olur. Bir dosyanın "bunu bir insan yaptı" veya "bunu bir yapay zeka yaptı" diyen tek bir özelliği yoktur. Bunun yerine ipuçları vardır ve her ipucu farklı türde bir görüntüyü yakalarken diğerlerini kaçırır. İlk ipucu kökendir. İçerik Köketi ve Özgünlük Koalisyonu (C2PA), bir medya dosyasına kurcalamaya dayanıklı, kriptografik olarak imzalanmış meta verileri ekleyen açık bir standarttır. Bu meta veri paketi manifeste denir ve kullanıcıya yönelik adı İçerik Kimlik Bilgileri'dir. Katılımcı bir araç, bir kamera, bir düzenleyici veya bir görüntü oluşturucu bir görüntü oluşturduğunda veya değiştirdiğinde, ne olduğunu kaydeden ve bunu bir sertifika ile imzalayan bir manifest yazabilir. Bu manifesti okuyabilir ve doğrulayabilirseniz, görüntünün geçmişi hakkında güçlü, doğrulanabilir bir beyan elde edersiniz. Ancak: C2PA isteğe bağlıdır ve manifest kırılgandır. Bir ekran görüntüsü onu kaldırır. Bir mesajlaşma uygulaması aracılığıyla yeniden kodlama onu kaldırır. Birçok platform yükleme sırasında meta verileri kaldırır. Bu nedenle eksik bir manifest size neredeyse hiçbir şey söylemez; görüntünün sahte olduğu anlamına gelmez ve gerçek olduğu anlamına da gelmez. İkinci ipucu istatistiksel bir sınıflandırıcıdır. Bir algılama modeli, milyonlarca gerçek ve üretilmiş görüntü üzerinde eğitilir ve oluşturucuların geride bırakma eğiliminde olduğu görsel eserleri öğrenir. Meta verilerle veya meta veriler olmadan herhangi bir görüntü üzerinde çalışır, ancak olasılıksaldır. Bir gerçek değil, bir olasılık döndürür ve özellikle eğitim dağılımının dışındaki görüntülerde veya yoğun şekilde sıkıştırılmış görüntülerde yanlış olabilir. Hiçbir sinyal tek başına yeterli değildir. Köken hassastır ama nadiren mevcuttur. Sınıflandırıcı her zaman mevcuttur ancak asla kesin değildir. Onları birleştirin ve esasen "işte kriptografinin kanıtladığı, işte modelin tahmin ettiği ve bu kombinasyonun bizi ne kadar güvende hissettirdiği" diyen bir karar elde edersiniz. Bu tasarım hedefidir. Tek sinyalli yaklaşımların neden yetersiz kaldığına daha derinlemesine bakmak isterseniz, yapay zeka görüntü algılamasının neden başarısız olduğu hakkındaki yazımız hata modlarını ayrıntılı olarak ele alır.
Mimariye genel bakış
Servis bilerek küçüktür. Bir uç nokta, iki aşağı akış çağrısı, birleşik bir yanıt.
┌─────────────────────────────┐
görüntü ──▶ │ FastAPI POST /verify │
│ │
│ 1. yüklemeyi doğrula │
│ 2. ┌──────────────────┐ │
│ │ C2PA manifesti │ │ köken sinyali
│ │ (c2pa-python) │ │
│ └──────────────────┘ │
│ 3. ┌──────────────────┐ │
│ │ sınıflandırıcı API │ │ istatistiksel sinyal
│ │ (barındırılan algılayıcı) │ │
│ └──────────────────┘ │
│ 4. karara birleştir │
└─────────────────────────────┘
│
▼
JSON kararı + güven
Adım 1, yüklemenin desteklenen bir türde gerçek bir görüntü olup olmadığını ve bir boyut sınırının içinde olup olmadığını kontrol eder. Adım 2, C2PA manifestini yerel olarak okur; ağ çağrısı yok, sadece ayrıştırma ve sertifika doğrulama. Adım 3, görüntü baytlarını HTTPS üzerinden barındırılan bir sınıflandırıcıya gönderir. Adım 4, iki sonucu küçük bir kural işleviyle birleştirir ve kararı döndürür. İki sinyal adımı bağımsızdır. Bu, hata yönetimi için önemlidir: sınıflandırıcı zaman aşımına uğrarsa, köken sinyalinden kısmi bir karar döndürebilirsiniz ve tam tersi. Buna sertleştirme bölümünde geri döneceğiz. Yığın için, C2PA kütüphanesi buna ihtiyaç duyduğu için Python 3.10 veya daha yenisi gereklidir. Web katmanı için FastAPI, çalıştırmak için Uvicorn, dosya yüklemeleri için python-multipart, giden sınıflandırıcı çağrısı için httpx ve köken için c2pa-python kullanacaksınız.
pip install fastapi "uvicorn[standard]" python-multipart httpx c2pa-python
C2PA sinyali
Content Authenticity Initiative, contentauth GitHub organizasyonu altında açık kaynak C2PA araçlarını yayınlamaktadır. Duyacağınız iki parça var:
c2patool, manifestleri görüntülemek ve eklemek için bir komut satırı aracı. Terminalden hızlı inceleme için kullanışlıdır. Bağımsız deposunun artık arşivlendiğini ve CLI'ninc2pa-rsRust projesinin içinde olduğunu unutmayın.c2pa-python, aynı temel Rust kütüphanesinin (c2pa-rs) Python bağlamasıdır. Servisiniz bunu kullanacaktır. PyPI'dac2pa-pythonolarak yayınlanmıştır vepip install c2pa-pythonile kurulur.
Kütüphanenin okuma yolu bir Reader nesnesi etrafında odaklanmıştır. Onu bir görüntüye işaret edersiniz, sonra manifest deposunu JSON olarak istersiniz. İşte köken modülünün çekirdeği.
# provenance.py
import json
import c2pa
def read_provenance(image_path: str) -> dict:
"""
Bir görüntüden C2PA manifestini oku ve doğrula.
Bulunanları açıklayan normalleştirilmiş bir sözlük döndürür.
"""
try:
with c2pa.Reader(image_path) as reader:
manifest_store = json.loads(reader.json())
except c2pa.C2paError as err:
# ManifestNotFound çoğu görüntü için beklenen durumdur.
if str(err).startswith("ManifestNotFound"):
return {
"has_manifest": False,
"validation": "none",
"detail": "Bu görüntüde C2PA manifesti bulunmuyor.",
}
# Diğer herhangi bir C2paError, dosyanın ayrıştıramadığımız C2PA verileri olduğu anlamına gelir.
return {
"has_manifest": True,
"validation": "error",
"detail": f"Manifest ayrıştırılamadı: {err}",
}
active_label = manifest_store.get("active_manifest")
manifests = manifest_store.get("manifests", {})
active = manifests.get(active_label, {})
# validation_status sadece doğrulama sorunları olduğunda görünür.
validation = "valid" if not manifest_store.get("validation_status") else "invalid"
claim_generator = active.get("claim_generator", "unknown")
signature_issuer = active.get("signature_info", {}).get("issuer", "unknown")
return {
"has_manifest": True,
"validation": validation,
"claim_generator": claim_generator,
"signature_issuer": signature_issuer,
"validation_status": manifest_store.get("validation_status", []),
"detail": "Manifest başarıyla okundu.",
}
Kodun ne yaptığına dair birkaç not. Reader, temel kaynakların serbest bırakılması için bir bağlam yöneticisi olarak kullanılır. reader.json(), tam manifest deposunu bir JSON dizesi olarak döndürür; her iddia ve bileşenle uzun biçimli raporu istiyorsanız kütüphane ayrıca reader.detailed_json()'u da sunar. Çoğu yükleme için beklenen sonuç, mesajı ManifestNotFound ile başlayan bir C2paError'dır, çünkü çoğu görüntüde basitçe İçerik Kimlik Bilgileri yoktur. Bunu bir hata değil, veri olarak ele alın. Bir manifest mevcut olduğunda, bir karar için en önemli iki alan vardır. claim_generator dizesi, manifesti hangi aracın yazdığını söyler, örneğin bir kamera yazılımı dizesi veya bir yapay zeka görüntü aracının adı. validation_status dizisi, imza ve hash'ler kontrol edildiğinde boştur ve uyuşmadığında hata kodlarıyla doldurulur. Geçersiz bir manifest, yüksek sesle yüzeye çıkarılması gereken bir kırmızı bayraktır; bu, dosyanın kriptografinin desteklemediği bir geçmişi iddia ettiği anlamına gelir. Bu sinyalin yapamayacağı şey: manifest olmadığında size bir karar veremez, ki bu çoğu zaman böyledir. İşte bu yüzden ikinci sinyale ihtiyacınız var.
Sınıflandırıcı sinyali
Sınıflandırıcı, bir görüntünün yapay zeka tarafından üretilme olasılığını puanlayan barındırılan bir API'dir. Birkaç satıcı bunu sunar. Bu eğitimde Sightengine kullanılıyor çünkü AI algılama modeli belgelenmiş bir HTTP API'sine ve net bir yanıt biçimine sahip, ancak kalıp herhangi bir sağlayıcı için aynıdır; URL'yi, parametreleri ve okuduğunuz alanı değiştirirsiniz. Seçenekleri değerlendiriyorsanız, en iyi AI görüntü algılama API'leri derlememiz satıcılar arası doğruluğu, fiyatlandırmayı ve kapsayıcılığı karşılaştırır. Sightengine'in kontrol uç noktası https://api.sightengine.com/1.0/check.json'dur. Görüntüyü media olarak POST edersiniz, models'i genai olarak ayarlarsınız ve api_user ve api_secret'ınızı iletirsiniz. Yanıt, 0 ile 1 arasında bir puan olan type.ai_generated içerir, yüksek olan daha olası AI tarafından üretildiği anlamına gelir.
# classifier.py
import httpx
SIGHTENGINE_URL = "https://api.sightengine.com/1.0/check.json"
async def classify_image(
image_bytes: bytes,
filename: str,
api_user: str,
api_secret: str,
timeout_seconds: float = 8.0,
) -> dict:
"""
Görüntüyü barındırılan algılayıcıya gönder.
AI tarafından üretilen puanı içeren normalleştirilmiş bir sözlük döndürür.
"""
data = {
"models": "genai",
"api_user": api_user,
"api_secret": api_secret,
}
files = {"media": (filename, image_bytes)}
try:
async with httpx.AsyncClient(timeout=timeout_seconds) as client:
response = await client.post(SIGHTENGINE_URL, data=data, files=files)
response.raise_for_status()
payload = response.json()
except httpx.TimeoutException:
return {"available": False, "reason": "classifier_timeout"}
except httpx.HTTPStatusError as err:
return {
"available": False,
"reason": f"classifier_http_{err.response.status_code}",
}
except httpx.HTTPError as err:
return {"available": False, "reason": f"classifier_error: {err}"}
if payload.get("status") != "success":
return {
"available": False,
"reason": payload.get("error", {}).get("message", "unknown_error"),
}
ai_score = payload.get("type", {}).get("ai_generated")
if ai_score is None:
return {"available": False, "reason": "missing_score_in_response"}
return {"available": True, "ai_score": float(ai_score)}
Fonksiyon asenkrondur, böylece yavaş bir sınıflandırıcı olay döngüsünü engellemez. Zaman aşımı açık ve kısadır; sekiz saniye etkileşimli bir uç nokta için mantıklı bir varsayılan değerdir ve sağlayıcınızın gerçek gecikmesine göre ayarlamanız gerekir. Her hata yolu, bir istisna fırlatmak yerine makine tarafından okunabilir bir nedenle available: False döndürür. Bu kasıtlıdır: bir sınıflandırıcı kesintisi, isteği çökertmek yerine kararı düşürmelidir. Bir sonraki bölümde yer alan karar mantığı available'ı okur ve ne yapacağına karar verir. Skoru bir tahmin olarak ele alın. 0.92 "model oldukça emin" anlamına gelir, "bu kanıtlanmış AI'dır" anlamına gelmez. Satıcılar modellerini günceller ve doğruluk oluşturucuya ve görüntünün size ulaşmadan ne kadar sıkıştırıldığına göre değişir. Bu araçların pratikte nasıl davrandığına dair daha geniş bir görünüm için, bir görüntünün AI tarafından oluşturulup oluşturulmadığını nasıl kontrol edeceğimize dair rehberimize bakın.
/verify sözleşmesini tasarlama
İşte Apidog'un yerini aldığı kısım. Rota işleyicisini yazmadan önce, isteği ve yanıtı bir OpenAPI şeması olarak tasarlayın. Bunu ilk yapmak size üç şey sağlar: her iki ekibin de üzerinde anlaşabileceği tek bir gerçek kaynağı, ön ucun hemen çağırabileceği bir mock sunucu ve arka uç var olduğu anda çalıştırabileceğiniz bir test paketi.
İstek
POST /verify, kontrol edilecek dosya olan image adlı tek bir alanla multipart/form-data gövdesini alır. Bu kadar basit tutun. İsteğe bağlı sorgu parametreleri daha sonra gelebilir.
Yanıt
Yanıt, tasarım çalışmasının karşılığını verdiği yerdir. Son kararı, güveni ve her iki ham sinyali göstermelidir, böylece arayan kişi kararı denetleyebilir. İşte şekil.
{
"verdict": "likely_ai",
"confidence": 0.86,
"signals": {
"provenance": {
"has_manifest": true,
"validation": "valid",
"claim_generator": "SomeImageTool/2.1",
"signature_issuer": "Some Issuing CA"
},
"classifier": {
"available": true,
"ai_score": 0.91
}
},
"explanation": "Geçerli bir C2PA manifesti bir AI görüntü aracını adlandırıyor ve sınıflandırıcı görüntüyü muhtemelen AI tarafından üretilmiş olarak puanladı.",
"checked_at": "2026-05-21T09:30:00Z"
}
verdict üç dize değerinden biridir: likely_authentic, likely_ai veya uncertain. Üç değer, iki değil, çünkü dürüstlük önemlidir; sinyaller çeliştiğinde veya her ikisi de zayıf olduğunda, "belirsiz" doğru cevaptır. confidence, sinyallerin bu kararı ne kadar güçlü desteklediğini açıklayan 0'dan 1'e kadar bir kayan noktadır. signals, arayanın kendi kullanıcı arayüzünü göstermesi veya kendi politikasını uygulaması için her iki ham girişi de taşır. explanation, destek personeli ve loglar için insan tarafından okunabilir bir cümledir. Bunu bir OpenAPI şeması olarak ifade etmek basittir. İşte spesifikasyonunuza koyacağınız yanıt bileşeni.
components:
schemas:
VerifyResponse:
type: object
required: [verdict, confidence, signals, checked_at]
properties:
verdict:
type: string
enum: [likely_authentic, likely_ai, uncertain]
confidence:
type: number
format: float
minimum: 0
maximum: 1
signals:
type: object
properties:
provenance:
type: object
properties:
has_manifest: { type: boolean }
validation:
type: string
enum: [valid, invalid, error, none]
claim_generator: { type: string }
signature_issuer: { type: string }
classifier:
type: object
properties:
available: { type: boolean }
ai_score:
type: number
format: float
explanation: { type: string }
checked_at: { type: string, format: date-time }
Bu şemayı doğrudan Apidog'un görsel tasarımcısında yazabilir veya mevcut bir OpenAPI dosyasını içe aktarabilirsiniz. Uygulamadan önce API'yi tasarlamak genel olarak benimsenecek değerli bir iş akışıdır; spesifikasyon öncelikli mod eğitimimiz Apidog'da baştan sona nasıl yapılacağını gösterir.
Kod incelemesi
Şimdi parçalar bir araya geliyor. Aşağıda FastAPI uygulaması yer alıyor: giriş doğrulama, her iki sinyal çağrısı, birleştirme işlevi ve rota.
İki sinyali birleştirme
Karar işlevi, servisin kalbidir. Politikanızı kodlar. Provenans, geçerli ve mevcut olduğunda, kriptografik olduğu için daha güçlü bir sinyaldir; sınıflandırıcı bir beraberlik bozucu ve yedektir. İşte net, muhafazakar bir sürüm.
# verdict.py
def combine_signals(provenance: dict, classifier: dict) -> dict:
"""Provenans ve sınıflandırıcı sinyallerini tek bir kararda birleştirir."""
has_manifest = provenance.get("has_manifest", False)
validation = provenance.get("validation", "none")
generator = (provenance.get("claim_generator") or "").lower()
classifier_ok = classifier.get("available", False)
ai_score = classifier.get("ai_score")
# Sezgisel: bilinen AI araçları manifestoda kendilerini belirtme eğilimindedir.
ai_keywords = ("firefly", "dall-e", "dalle", "midjourney", "stable",
"gpt", "gemini", "imagen", "generat")
generator_looks_ai = any(k in generator for k in ai_keywords)
# Durum 1: bir AI üreticisini adlandıran geçerli bir manifest. Güçlü AI sinyali.
if has_manifest and validation == "valid" and generator_looks_ai:
return _verdict("likely_ai", 0.95,
"Geçerli bir C2PA manifesti bir AI görüntü aracını adlandırıyor.")
# Durum 2: bir kameradan veya AI olmayan bir düzenleyiciden geçerli bir manifest. Güçlü otantik sinyal.
if has_manifest and validation == "valid" and not generator_looks_ai:
if classifier_ok and ai_score is not None and ai_score > 0.85:
return _verdict("uncertain", 0.55,
"Manifest otantik görünüyor ancak sınıflandırıcı "
"katılmıyor; sinyaller çelişiyor.")
return _verdict("likely_authentic", 0.9,
"AI olmayan bir araçtan geçerli bir C2PA manifesti mevcut.")
# Durum 3: doğrulaması başarısız olan bir manifest. Şüpheli olarak ele alınır.
if has_verdict and validation in ("invalid", "error"):
return _verdict("uncertain", 0.6,
"Görüntü, doğrulaması başarısız olan bir C2PA manifesti taşıyor; "
"iddia edilen geçmişi doğrulanmadı.")
# Durum 4: manifest yok. Tamamen sınıflandırıcıya güvenilir.
if classifier_ok and ai_score is not None:
if ai_score >= 0.7:
return _verdict("likely_ai", round(ai_score, 2),
"Provenans verisi yok; sınıflandırıcı görüntüyü "
"muhtemelen AI tarafından üretilmiş olarak puanladı.")
if ai_score <= 0.3:
return _verdict("likely_authentic", round(1 - ai_score, 2),
"Provenans verisi yok; sınıflandırıcı görüntüyü "
"muhtemelen otantik olarak puanladı.")
return _verdict("uncertain", 0.5,
"Provenans verisi yok ve sınıflandırıcı puanı "
"kesin değil.")
# Durum 5: manifest yok ve sınıflandırıcı yok. Gerçekten bir şey söyleyemeyiz.
return _verdict("uncertain", 0.0,
"Provenans verisi yok ve sınıflandırıcı kullanılamıyordu.")
def _verdict(verdict: str, confidence: float, explanation: str) -> dict:
return {"verdict": verdict, "confidence": confidence,
"explanation": explanation}
Beş durumu okuduğunuzda politikayı görebilirsiniz. Geçerli bir manifest baskındır. Başarısız bir manifest bir uyarıdır, sahtekarlığın kanıtı değil, bu yüzden "belirsiz"e iner. Temiz bir manifest ile yüksek bir sınıflandırıcı puanı arasındaki çatışma da taraf seçmek yerine "belirsiz"e iner. Ve her iki sinyal de eksik olduğunda, servis sıfır güvenle dürüstçe söyler, tahmin etmek yerine. Bu eşikleri kendi risk toleransınıza göre ayarlarsınız; bir içerik platformu ve bir haber odası çizgileri farklı çekerdi.
FastAPI uygulaması
# main.py
import os
import tempfile
from datetime import datetime, timezone
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import JSONResponse
from provenance import read_provenance
from classifier import classify_image
from verdict import combine_signals
app = FastAPI(title="AI Görüntü Algılayıcı API", version="1.0.0")
ALLOWED_TYPES = {"image/jpeg", "image/png", "image/webp"}
MAX_BYTES = 12 * 1024 * 1024 # 12 MB
SIGHTENGINE_USER = os.environ.get("SIGHTENGINE_API_USER", "")
SIGHTENGINE_SECRET = os.environ.get("SIGHTENGINE_API_SECRET", "")
@app.post("/verify")
async def verify(image: UploadFile = File(...)):
# 1. Yüklemeyi doğrula.
if image.content_type not in ALLOWED_TYPES:
raise HTTPException(
status_code=415,
detail=f"Desteklenmeyen tür {image.content_type}. "
f"JPEG, PNG veya WebP gönderin.",
)
image_bytes = await image.read()
if len(image_bytes) == 0:
raise HTTPException(status_code=400, detail="Boş dosya.")
if len(image_bytes) > MAX_BYTES:
raise HTTPException(status_code=413, detail="Dosya 12 MB sınırını aşıyor.")
# 2. Provenans sinyali. C2PA okuyucusu bir dosya yoluna ihtiyaç duyar,
# bu yüzden geçici bir dosyaya yazın ve sonra temizleyin.
suffix = os.path.splitext(image.filename or "")[1] or ".img"
with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
tmp.write(image_bytes)
tmp_path = tmp.name
try:
provenance = read_provenance(tmp_path)
finally:
os.unlink(tmp_path)
# 3. Sınıflandırıcı sinyali. Hatalar istisna değil, available: False döndürür.
if SIGHTENGINE_USER and SIGHTENGINE_SECRET:
classifier = await classify_image(
image_bytes, image.filename or "upload",
SIGHTENGINE_USER, SIGHTENGINE_SECRET,
)
else:
classifier = {"available": False, "reason": "classifier_not_configured"}
# 4. Birleştir ve yanıtla.
result = combine_signals(provenance, classifier)
return JSONResponse({
"verdict": result["verdict"],
"confidence": result["confidence"],
"signals": {
"provenance": {
k: provenance.get(k) for k in
("has_manifest", "validation", "claim_generator",
"signature_issuer")
},
"classifier": {
"available": classifier.get("available", False),
"ai_score": classifier.get("ai_score"),
},
},
"explanation": result["explanation"],
"checked_at": datetime.now(timezone.utc).isoformat(),
})
uvicorn main:app --reload ile yerel olarak çalıştırın ve uç nokta http://127.0.0.1:8000/verify adresinde canlı olacaktır. C2PA okuyucusu bir dosya yolu bekler, bu yüzden işleyici yüklemeyi geçici bir dosyaya yazar ve finally bloğunda siler; sınıflandırıcı doğrudan baytlardan çalışır. İsteğin asla eksik bir manifest veya mevcut olmayan bir sınıflandırıcı nedeniyle çökmediğini unutmayın; her ikisi de karar işlevinin ele aldığı normal durumlardır. Bu şekilde tasarlanmış bir arka uç, temiz bir sözleşmeye sahip odaklanmış bir hizmet, ürünlerin temel yeteneklerini bir API aracılığıyla gösterme genel eğilimine uyar. Bu fikir ilginizi çekiyorsa, yazılımın "headless" hale gelmesi hakkındaki yazımızı okumaya değer.
Apidog ile test ve moklama
İşte iş akışı problemi: ön uç ekibiniz yükleme kullanıcı arayüzünü ve sonuç panelini şimdi oluşturmak istiyor, ancak yukarıdaki arka ucun bitirilmesi, anahtarlarının alınması ve dağıtılması birkaç gün sürer. Onların engellenmesini istemezsiniz. Mok sunucular bunun içindir ve şemayı ilk tasarlamanın karşılığını verdiği yer burasıdır.
Şemadan bir mock sunucu oluşturun
OpenAPI şemasını Apidog'a aktarın veya görsel tasarımcıda /verify uç noktasını oluşturun. Apidog, yanıt şemasını okur ve otomatik olarak bir mock sunucu oluşturur. Şema alan türlerini ve enumarasyonları tanımladığından, mock tam olarak gerçek uç nokta gibi veriler döndürür: üç enum değerinden biri olan bir verdict, 0 ile 1 arasında bir confidence kayan nokta, doldurulmuş bir signals nesnesi. Ön uç, fetch çağrısını Apidog mock URL'sine yönlendirir ve ilk günden itibaren gerçekçi yanıtlar alır. Gerçek arka uç gönderildiğinde, tek bir temel URL'yi değiştirirler. Mock ayrıca, gerçek kod mevcut olmadan önce zor durumları uyguladığınız yerdir. Önemli kararlar için örnek yanıtlar tanımlayın:
- geçerli bir kamera manifesti ile
likely_authenticyanıtı, - manifestte bir AI aracı adı geçen
likely_aiyanıtı, - sınıflandırıcının kullanılamadığı
uncertainyanıtı, 415ve413hata yanıtları.
Ön uç, hata durumları da dahil olmak üzere her durumu mock'a karşı oluşturabilir ve stilize edebilir. Bir kullanıcı arayüzünü ve bir API'yi sırayla değil, paralel olarak bu şekilde gönderirsiniz.
Apidog'da uç nokta testleri çalıştırın
Arka uç çalışmaya başladığında, Apidog'da POST /verify için bir istek oluşturun. Metodu ayarlayın, yerel URL'nize yönlendirin ve Body sekmesinde form-data'yı seçin, image alanını ekleyin, türünü Dosya olarak ayarlayın ve diskten bir test görüntüsü seçin. Gönderin ve Apidog JSON yanıtını gösterir. Şimdi, bunun tek seferlik bir tıklama yerine tekrarlanabilir bir kontrol haline gelmesi için iddialar ekleyin:
- yanıt durumunun
200olduğunu iddia edin, verdict'in var olduğunu ve izin verilen üç dizeden biri olduğunu iddia edin,confidence'in 0 ile 1 arasında bir sayı olduğunu iddia edin,signals.provenance.has_manifest'in bir boole olduğunu iddia edin.
Birkaç yüklemeyi sırayla çalıştıran küçük bir test senaryosu oluşturun: İçerik Kimlik Bilgileri olan bir görüntü, manifesti olmayan düz bir JPEG, çok büyük bir dosya ve .jpg uzantısıyla yeniden adlandırılmış bir görüntü olmayan dosya. Her biri karar mantığınızın ve giriş doğrulamanızın farklı bir dalını kontrol eder. Senaryoyu kaydedin ve her değişiklikten sonra tüm paketi yeniden çalıştırabilir veya CI'ye bağlayarak karar işlevindeki bir regresyonun yapıyı başarısız etmesini sağlayabilirsiniz. curl ile elle bir yükleme uç noktasını test etmek hızla sıkıcı hale gelir; kaydedilmiş bir senaryo bunu yapmaz.
Sertleştirme ve uç durumlar
Mutlu yol, kolay %80'dir. Bir doğrulama hizmeti, diğer %20'lik kısımdan geçer veya ölür, çünkü girişler doğası gereği düşmancadır; birisi bir görüntüyü olduğu gibi göstermeye çalışır.
Bozuk veya kesik dosyalar. Bir dosyanın bir görüntü MIME türü olabilir ve yine de çöp olabilir. C2PA okuyucusu, ayrıştıramadığı verilerde bir C2paError yükseltir ve read_provenance işlevi bunu zaten 500 yerine temiz bir sonuca dönüştürür. Ek önlem olarak, Pillow gibi bir kütüphane ile görüntüyü işlemeden önce çözebilir ve çözme başarısız olursa 400 ile reddedebilirsiniz. Bu, yeniden adlandırılmış metin dosyası numarasını da engeller.
Eksik manifest. Kapsandı, ancak en yaygın durum olduğu ve yanlış yapılması en kolay olduğu için tekrar belirtmeye değer. Manifest olmaması bir hata değildir ve bir karar değildir. Kütüphane bunu ManifestNotFound ile başlayan bir mesajla bir C2paError ile sinyaller; hizmet bunu özellikle yakalar ve sınıflandırıcıya geçer. Asla eksik bir manifestin 500 veya "sahte" bir karar üretmesine izin vermeyin.
Sınıflandırıcı zaman aşımı veya kesintisi. Sınıflandırıcı üçüncü taraf bir ağ bağımlılığıdır, bu yüzden bazen başarısız olacağını varsayın. classify_image işlevi, açık bir httpx zaman aşımı kullanır ve herhangi bir zaman aşımı veya HTTP hatasında available: False döndürür. Karar işlevi daha sonra yalnızca provenansa geri döner veya manifest de yoksa sıfır güvenle uncertain döndürür. Uç nokta hala 200 ve dürüst bir kararla yanıt verir; yavaş bir satıcı hizmetinizi çökertemez.
Sahte manifestler. Bir manifest mevcut olabilir ancak geçersiz olabilir, kötü bir sertifika ile imzalanmış veya piksellerle eşleşmeyen hash'lere sahip olabilir. Bu, insanların unuttuğu durumdur. Her zaman validation_status'ı kontrol edin; boş bir dizi manifestin doğrulandığı anlamına gelir, doldurulmuş bir dizi ise doğrulanmadığı anlamına gelir. Karar işlevi, başarısız bir manifesti bir uyarı olarak ele alır ve asla kanıt olarak değil, uncertain'e iner. Doğrulanmamış bir manifest'e güvenmek, hiç manifest olmamasından daha kötüdür.
Büyük dosyalar ve kötüye kullanım. Yükleme boyutunu sınırlayın, örnek 12 MB kullanır ve her şeyi belleğe almadan önce 413 ile daha büyük olanları reddedin. Uç noktanın önüne bir hız sınırı koyun; kriptografik doğrulama ve her istek için giden bir API çağrısı ücretsiz değildir ve açık bir doğrulama uç noktası cazip bir hedeftir.
Gizlilik. Kullanıcı görüntüleri alıyorsunuz. Örnekte olduğu gibi, bunları bellekte veya hemen sildiğiniz geçici bir dosyada işleyin ve görüntü baytlarını kaydetmeyin. Görüntüleri üçüncü taraf bir sınıflandırıcıya gönderiyorsanız, gizlilik politikanızda bunu belirtin ve bunun kullanım durumunuz için izin verildiğinden emin olun.
Her sinyalin yakaladığı ve kaçırdığı şeyler
Bu tablo, akılda tutulması gereken zihinsel modeldir. Servisin her ikisini de kullanmasının nedeni budur.
| Senaryo | C2PA provenans sinyali | Sınıflandırıcı sinyali |
|---|---|---|
| İçerik Kimlik Bilgileri yazan bir araçtan AI görüntüsü | Yakalıyor: manifest üreticiyi adlandırıyor | Genellikle yakalıyor: eserler mevcut |
| Meta verileri kaldırılmış AI görüntüsü (ekran görüntüsü, yeniden yükleme) | Kaçırıyor: okunacak manifest yok | Yakalıyor: pikseller üzerinde çalışır, meta veriye gerek yok |
| İçerik Kimlik Bilgileri imzalayan bir kameradan gerçek fotoğraf | Doğruluyor: geçerli manifest, AI olmayan üretici | Yoğun sıkıştırma veya düzenlemelerde yanlış pozitif verebilir |
| Hiç meta verisi olmayan gerçek fotoğraf | Sinyal yok: doğrulanacak bir şey yok | Sadece en iyi tahmin: olasılıksal, yanlış olabilir |
| Sahte veya kurcalanmış manifestli görüntü | Yakalıyor: validation_status hatayı işaretliyor |
Yakalayabilir veya yakalamayabilir, piksellere bağlı |
| Sınıflandırıcının üzerinde eğitilmediği yeni bir üretici | Yalnızca araç bir manifest yazarsa yakalar | Genellikle kaçırıyor: eğitim dağılımının dışında |
| Yoğun şekilde düzenlenmiş gerçek fotoğraf (gerçek bir taban üzerinde AI rötuşu) | Manifest, mevcutsa, düzenleme geçmişini kaydeder | Belirsiz: kısmen sentetik, puan orta aralığa düşer |
Herhangi bir satırı okuduğunuzda aynı hikayeyi görüyorsunuz: bir sinyalin kör olduğu yerde, diğeri genellikle değildir. Provenans kesindir ama seyrektir; sınıflandırıcı evrenseldir ama bulanıktır. Birleşik karar, tek başına herhangi bir sütundan daha güvenilirdir ve her iki sinyalin de zayıf olduğu satırlar için dürüst uncertain değeri mevcuttur.
Gerçek dünya kullanım durumları
Bu kalıp akademik değil. Doğrudan uyduğu birkaç yer:
- Kullanıcı tarafından oluşturulan içerik platformları. Bir pazar yeri veya sosyal uygulama, yüklemeleri
/verifyaracılığıyla çalıştırabilir ve muhtemelen AI olarak puanlanan veya doğrulamayı geçemeyen bir manifest taşıyan her şeyi etiketleyebilir veya inceleme kuyruğuna alabilir. Üç değerli karar, "izin ver", "işaretle" ve "insana gönder" ile net bir şekilde eşleşir. - Haber odaları ve doğruluk kontrolü. Viral bir görüntüyü kontrol eden bir editör, varsa kriptografik kökeni ve bağımsız bir model tahminini tek bir çağrıda alır, notlarında alıntılayabileceği bir açıklama cümlesiyle birlikte.
- Sigorta ve talep alımı. Bir müşteri fotoğraf kanıtı sunduğunda, bir doğrulama adımı, insan bir ayarlayıcının zaman harcamasından önce, üretilmiş görünen veya kurcalanmış bir manifest taşıyan görüntülerde bir bayrak kaldırır.
- Dahili varlık boru hatları. Bir stok kütüphanesinden AI tarafından oluşturulan görüntüleri çıkarması veya açıkça etiketlemesi gereken bir ekip, alımı
/verifyüzerinde kilitleyebilir. - Provenans farkındalıklı yayıncılık. Daha fazla kamera ve editör İçerik Kimlik Bilgileri'ni benimsedikçe, bir CMS yükleme sırasında manifesti okuyabilir ve doğrulanmış bir rozet gösterebilir, manifest mevcut olmadığında sınıflandırıcıya geri dönebilir.
Ortak nokta: hızlı, otomatik bir ilk geçiş istersiniz ve kendi belirsizliği konusunda dürüsttür, böylece insan dikkati gerçekten ihtiyaç duyulan yere gider.
Sonuç
AI tarafından oluşturulan görüntüleri iyi tespit etmek, tek bir mükemmel test bulmakla ilgili değildir. Bağımsız sinyalleri birleştirmek ve güven konusunda dürüst olmakla ilgilidir.
- C2PA İçerik Kimlik Bilgileri, size güçlü, kriptografik olarak doğrulanabilir bir provenans sinyali verir, ancak manifest isteğe bağlıdır ve kolayca çıkarılabilir, bu yüzden genellikle mevcut değildir.
- Barındırılan bir sınıflandırıcı, size herhangi bir görüntü üzerinde, meta verilerle veya meta veriler olmadan çalışan evrensel ama olasılıksal bir sinyal verir.
- Bunları küçük bir FastAPI servisinde birleştirmek, bir güven puanı ve denetim için her iki ham sinyali de eklenmiş üç değerli bir karar,
likely_authentic,likely_aiveyauncertainüretir. - Önce OpenAPI sözleşmesini tasarlamak, uç noktayı Apidog'da moklamanıza olanak tanır, böylece ön uç paralel olarak oluşturulur, ardından gerçek arka uca karşı kaydedilmiş test senaryolarını çalıştırırsınız.
- Hiçbir algılayıcı mükemmel değildir. İki sinyal güveni artırır; belirsizliği ortadan kaldırmazlar, bu yüzden
uncertainkararı bir özellik, bir boşluk değil.
Bunu gerçekten inşa etmek için, /verify şemasını tasarlayın, bir mock sunucu oluşturun ve uç nokta testlerinizi tek bir yerde çalıştırın. Apidog'u tasarlamak, moklamak ve API'yi inşa ederken test etmek için indirin, ardından tek bir temel URL değişikliğiyle mok'tan canlı arka uca geçin.
