Python tuzakları

Pipelogic'in Python component API'si küçüktür, ama platformun process()'in nasıl davranabileceğine dair görüşleri vardır. Bu sayfadaki kalıplar, temiz bir şekilde derlenip yayımlanan, fakat sonra çalışma zamanında başarısız olanlardır — genellikle dönüş şekli, stateful kontrat ya da içe aktarma yerleşimi runtime'ın beklediğine uymadığı için.

Temiz inşa edilen ama hiç output üretmeyen bir component'i debug etmeden önce bunu bir kez okuyun.

Diğer yazarları önce ısıran şeyler, tuzağın bulunduğu yere göre düzenlenmiş.

Yapılandırma

runtime base'in zaten getirdiği paketleri sabitlemeyin

runtime base imajı numpy, pyyaml, protobuf, pika ve pipelogic getirir. Bunlardan herhangi birini requirements.txt içinde sabitlemek sessizce yanlış davranmaz — build system'in requirements.txt doğrulayıcısı yüklemeyi, size sabitlemeyi kaldırmanızı söyleyen bir alan hatasıyla reddeder. Gerçekten farklı bir sürüme ihtiyacınız varsa, yeniden sabitlemek yerine daha ağır bir build_system seçin.

# WRONG — rejected at validation time
numpy==2.0.0

# Right — the runtime base supplies numpy

Her bağımlılığı tam olarak sabitleyin

==1.2.3, asla >=, ~=, ==1.2.* gibi bir joker, bir URL/VCS referansı veya hiç belirteç olmadan — doğrulayıcı bunların her birini reddeder. Gevşek sabitlemeler build'leri tekrarlanamaz kılar ve yeniden inşada sessizce yeni CVE'leri içeri çeker.

Doğru build_system'i seçin

build_system varsayılanı olmayan zorunlu bir alandır. Değeri, component'inizin üzerine inşa edildiği runtime base imajını seçer; o base'in getirmediği bir kütüphaneyi içe aktarmak (örn. yalnızca CPU'lu bir base altında torch) çalışma zamanında başarısız olur. component registry genelinde görülen değerler:

build_systemTipik kullanım
2Yalın Python runtime
2-mlYaygın ML runtime
2-opencv4.11OpenCV ağırlıklı component'ler
2-cuda12.6 / 2-cuda12.8-onnxrtgpu1.22CUDA / ONNX Runtime GPU
2-cuda12.8-torch2.8-onnxrtgpu1.22PyTorch + ONNX Runtime
2-cuda12.8-torch2.8-ultralyticsUltralytics yığını
2-cuda12.8-torch2.8-onnxrtgpu1.22-roboflowRoboflow çıkarımı
customKendi base imajını getir

Değeri içe aktardığınız kütüphanelere göre eşleştirin. Tam matris için concepts/build-systems'e bakın.

Tipler

Bytes / List'ten numpy erişimi: hangi çağrının kopyaladığını bilin

import numpy as nparr = pipe_bytes.unsafe_numpy(dtype=np.uint8, shape=(h, w, 3))  # zero-copy, READ-ONLY viewarr = np.asarray(pipe_bytes)                                    # copy-on-writearr = pipe_bytes.safe_numpy()                                   # copy-on-writearr = np.array(pipe_bytes, copy=True)                           # always an independent copy

unsafe_numpy() yalnızca kaynak Bytes/List nesnesi kapsamdayken geçerli olan, salt-okunur, kopyasız bir görünüm döndürür — onu çağrının ötesinde saklamayın ve üzerinden yazmayın. np.asarray(...) ve .safe_numpy() copy-on-write'tır: kapsamdayken tutmak güvenlidir ve mutasyonlar ilk yazma özel bir kopyayı zorlayana kadar arabelleğe geri yansır. Girdiden tamamen bağımsız bir değere ihtiyacınız olduğunda np.array(..., copy=True) kullanın.

Varsayılan int Int64'tür, varsayılan float Double'dır

from pipelogic.types import ListL = List([1, 2, 3])              # element type: Int64L = List([1.0, 2.0])             # element type: DoubleL = List([1, 2, 3], '[Int32]')   # explicit Int32

Tipli değerler için dict inşa etmeyin

High-level wrapper'lar bir nedenle vardır — named-type registration'ı ve alan yerleşimini sizin için hallederler:

# WRONG — manual dict construction breaks when type fields driftreturn {"width": w, "height": h, "data": arr.tobytes(), "format": ...}# Right — let the wrapper do itreturn Image(arr, color_space=ColorSpace.BGR)

Aynı şey BoundingBox, Tensor, AudioFrame, Mask, Landmark vb. için de geçerlidir. pipelogic.cv ve pipelogic.types içindeki wrapper'ları tercih edin — alan yerleşimini ve named-type registration'ı sizin için hallederler. Yalnızca wrapper'ların kapsamadığı bir nedeniniz olduğunda ham dict'lere inin.

Components

Virtual input parametre adıyla opt-in'dir

virtual-input mesajları almak için component fonksiyonunuzda parametreyi virtual_input olarak adlandırın. runtime adı tespit eder ve component'i virtual-input moduna geçirir:

def from_vin(virtual_input):    return virtual_input[0]run(from_vin)

1-output'lu bir component'ten bir tuple döndürmek onu tek output olarak sarar

component.yml bir output_type deklare ediyorsa ve fonksiyonunuz (a, b) döndürüyorsa, runtime tuple'ı tek output'unuz olarak serileştirir — otomatik bölmez. Birden fazla output döndürmek için, bunları component.yml içinde deklare edin:

worker:  output_types:    - BoundingBox    - Image

ardından (boxes, image)'ı deklare edilen sırada döndürün.

Stateful component'ler bir dict döndürmelidir

run'a initial_state= ilettiğinizde bir component stateful olur. O andan itibaren fonksiyon bir state argümanı alır ve her iki anahtarı da döndürmelidir:

def stateful(x, state):    return {"output": x * 2, "state": state + 1}    # required keysrun(stateful, initial_state=0)

Döndürülen dict'ten state'i atlamak ValueError("state must be provided when stateful is True") fırlatır.

Virtual-output component'leri bir virtual_output listesi döndürmelidir

run'a use_virtual_output=True ileterek virtual output'u etkinleştirin. Fonksiyon ardından virtual_output anahtarı bir liste (muhtemelen boş) olan bir dict döndürür; her öğe normal output'lardan önce virtual-output stream'inde yayımlanır:

def with_virtual_out(x):    return {"output": x, "virtual_output": [item1, item2]}run(with_virtual_out, use_virtual_output=True)

virtual_output anahtarını atlamak hata fırlatır.

CV wrapper'ları

Stereo ses otomatik olarak mono'ya karıştırılmaz

AudioFrame.numpy() orijinal (samples, channels) float32 şeklini döndürür. Birçok ses modeli mono bekler — .mono()'yu açıkça çağırın:

audio_arr = audio.mono()              # 1-D float32, channels averaged

.mono() float32 kalır; bir model int16 PCM istiyorsa audio.to_int16(mono=True) kullanın.

Image color space'i zorunlu kılınmıştır — yalan söylemeyin

Image(arr, color_space=ColorSpace.RGB) hatta RGB'yi ilan eder. Belirli bir color space bekleyen aşağı akış consumer'ları (örn. bir Image.to_gray() zinciri) doğru dönüşümü deklare edilen color space'e göre hesaplar. RGB olarak etiketlenmiş BGR verisi iletirseniz, her aşağı akış dönüşümü yanlış olur.

image.numpy() geçerli color space'i döndürür

Girdi BGR idiyse, image.numpy() BGR'dir. Belirli bir uzay istiyorsanız to_bgr()/to_rgb()/to_gray() çağırın — bunlar her zaman doğru uzayı döndürür (ve dönüşüm gerektiğinde kopyalar).

Image.resize((h, w)) önce yükseklik, sonra genişlik alır

OpenCV tam tersidir — cv2.resize(img, (w, h)). Pipelogic'in wrapper'ı numpy shape konvansiyonlarına uymak için (height, width) alır.

Dosya ve model yolları

find_model_file tam olarak bir eşleşme gerektirir

find_model_file bir dizini .pt, .onnx, .safetensors veya .bin dosyaları için özyinelemeli olarak arar (extensions= ile geçersiz kılın). Sıfır eşleşme FileNotFoundError fırlatır; birden fazlası ValueError fırlatır. Bu kasıtlıdır — hangi ağırlık dosyasının "model" olduğu konusunda açık olmaya zorlar. Çok dosyalı checkpoint'ler için bir üst dizini gösterin ve kendi loader'ınızı yazın.

ensure_local_dir offline modu dikkate alır

ensure_local_dir bir yerel dizin yolunu olduğu gibi döndürür ve aksi halde repo'yu snapshot ile indirir. Container env'inizde HF_HUB_OFFLINE=1 (veya TRANSFORMERS_OFFLINE=1) ayarlayın; indirme local_files_only'e geçer — build zamanında önceden getirilen cache'i sunar ve asla ağa erişmez.

Init ve başlatma

pipelogic'i lazy içe aktarmayın

pipelogic içe aktarma zamanında çalışan backend'e bağlanır. İçe aktarmayı geciktirirseniz, component'iniz stream'lerine bağlanamaz. from pipelogic.worker import run'u main.py'nin en üstüne koyun.

Mutable yapılandırma

Mutable parametreler yalnızca config.sync()'i drain ettiğinizde güncellenir

component.yml içinde mutable olarak deklare edilen parametreler config özniteliklerini kendiliğinden değiştirmez. config.sync()'i tick başına bir kez çağırmanız gerekir — bekleyen güncelleme kuyruğunu drain eder, yeni değerleri config üzerine uygular ve değişen anahtarların kümesini döndürür. config.threshold'u okuyup config.sync()'i hiç çağırmayan bir component, başladığı değeri görmeye devam eder.

from pipelogic.worker import config, rundef process(x):    changed = config.sync()          # drain once per tick    if "threshold" in changed:        ...                          # react to the new value    return x

Değişen anahtar kümesini HotSwapModel.apply'a kendiniz iletin

HotSwapModel, izlenen bir config anahtarı değiştiğinde bir model backend'i yeniden yükler, ama kasıtlı olarak config.sync()'i asla kendi çağırmaz — böylece tek bir component'teki birkaç consumer aynı güncelleme batch'ine tepki verebilir. config.sync()'i siz drain edersiniz ve sonucunu iletirsiniz:

def process(x):    swapper.apply(config.sync())     # you drain, HotSwapModel reacts    return swapper.backend.run(x)

Rebuild (veya yeni bir model id için ön-doğrulama indirmesi) başarısız olursa, önceki backend canlı kalır ve bir uyarı loglanır — component, son bilinen iyi modelle hizmet vermeye devam eder.

İlgili

Bu sayfa yardımcı oldu mu?