İçeriğe atla
openplate

Çıkarım çalışma zamanı

Kendi çalışma zamanını getir

Bunu zaten çalıştırdığın bir llama.cpp, Ollama veya vLLM örneğine yönlendir; dilbilgisi zorlama gereksinimi, çalışma zamanı başına kurulum tuzakları

Bu sayfa, İngilizce belgeden makine çevirisiyle çevrildi.

Zaten llama.cpp, Ollama veya OpenAI protokolünü destekleyen başka bir şey çalıştırıyorsan bu servisi oraya yönlendir. Bu modda hiçbir model indirmez ve donanımında modelin ikinci bir kopyasını başlatmaz.

Bir çalışma zamanı seçmeden önce destek matrisi tablosunu kontrol et: bu işlem hattı dilbilgisi kısıtlamalı kod çözmeye ihtiyaç duyar ve OpenAI uyumluluğu vadeden her araç bunu sağlayamaz. llama.cpp, Ollama ve bir GPU üzerinde vLLM araçlarının çalıştığı ölçülmüştür. vLLM'in CPU derlemesi ilk taramada çöküyor: aynı sürüm, hızlandırıcı yok, çalışmayan işçi süreci.

Bir taramanın izlediği yol kısadır ve dilbilgisi tam ortasında yer alır. Tarayıcı bu servise bir fotoğraf gönderir, servis anahtarı denetler, isteği kabul eder, görüntünün boyutunu küçültür ve bir JSON şeması altında tek bir görme çağrısı yapar. Bu şemayı zorunlu kılan tek şey senin çıkarım çalışma zamanındır, bu yüzden aşağıdaki matris hızdan ziyade kuralları zorunlu kılmayla ilgilidir. Geriye dönen şey adlar ve gramajlardır; makro değerler daha sonra, yapılandırılmış gıda kaynağından aranıp bulunur ve model asla bir makro değeri yazmaz.

Tarayıcı bu servise bir fotoğraf gönderir, servis bir JSON şeması altında çıkarım çalışma zamanını bir kez çağırır, ardından yanıt vermeden önce makroları arayıp bulur.
Diyagram kaynağı
flowchart LR
  browser["Browser"]
  subgraph svc["openplate-inference"]
    gate["Key, rate limit, admission"]
    prep["Downscale to 896 px"]
    vision["One vision call, json_schema"]
    macros["Look up macros, food source"]
  end
  runtime["Your model runtime"]

  browser -->|"photo, POST /v1/chat/completions"| gate
  gate --> prep --> vision
  vision -->|"grammar constrained decoding"| runtime
  runtime -->|"names and grams, no macros"| macros
  macros -->|"one plate, as JSON"| browser
bash
docker run -d --name openplate-inference \
  -p 8300:8300 \
  -e MODEL_PROFILE=external \
  -e MODEL_RUNTIME_URL=http://your-runtime.lan:8000 \
  -e MODEL_ID=your-served-model-name \
  -e API_KEYS=opk_your_key \
  ghcr.io/lowcarbcheck/openplate-inference:latest

MODEL_PROFILE=external anahtarın tamamıdır. Ağırlık indirmeyi atlar ve hiçbir llama-server başlatmaz, bu yüzden /models birimi yoktur.

Harici mod değişkenleri

  • MODEL_RUNTIME_URL: sonda /v1 olmaz, servis OpenAI yollarını kendisi ekler. konteynerin içinde içinden çözümlenmelidir, yani localhost ana makineni değil, konteyneri ifade eder. MODEL_PROFILE=external olmadan bunu bir farklı adresine ayarlamak, sessizce geçersiz kılmak yerine bir önyükleme hatasıdır: paketlenmiş bir konteyner her zaman kendi geridöngüsünden hizmet verir. (Bunu tam olarak paketlenmiş geridöngü adresine ayarlamaya izin verilir ve hiçbir şeyi değiştirmez: daha eski .env.example kopyaları bu satırı yorumsuz olarak gönderiyordu.)
  • MODEL_ID: çalışma zamanına gönderilir. llama.cpp bunu yok sayar, ancak vLLM ve Ollama'nın her ikisi de tam olarak sunulan model adına ihtiyaç duyar: vLLM uyuşmazlığı reddeder, Ollama ise modeli seçmek ve yüklemek için bunu kullanır. istemciler tarafından kullanılan kimlik, her durumda her zaman openplate-plate-1 değeridir.
  • MODEL_RUNTIME_API_KEY: isteğe bağlıdır, çalışma zamanına Authorization: Bearer … olarak gönderilir. Bunu vllm serve --api-key … veya bir yetkilendirme vekili için ayarla. Bu, çağıranlar tarafının bu servisine sunduğu API_KEYS değerinden ayrıdır.
  • RUNTIME_COMPLETION_TIMEOUT_MS: tek bir tamamlama çağrısındaki milisaniye cinsinden toplam sınır. Varsayılan 600000 (10 dakika); 0 bunu devre dışı bırakır. paketlenmiş modda da içinde de geçerlidir: kilitlenmiş bir llama-server, yanlış yönlendirilmiş bir vekil kadar sessizdir. Donanımın tabak başına haklı olarak on dakikadan uzun bir süreye ihtiyaç duyuyorsa, bu değeri artır veya 0 olarak ayarla; hata mesajı değişkenin adını belirtir.

    Bu LATENCY_CEILING_MS değildir. O kabul politikası niteliğindedir: zamanında bitiremeyeceğin işi başlamadan önce reddet. Bu ise canlılık niteliğindedir: yukarı akışın asla geri vermeyeceği bir çalışan yuvasını serbest bırak.

    Bu değişken var olmadan önce de zaten bir sınır yürürlükteydi: Node'un fetch değeri headersTimeout ayarını varsayılan olarak 300 saniyeye ayarlar ve akışsız bir tamamlama başlıklarını yalnızca üretim bittiğinde yazdığı için, bu durum bu projenin desteklediği donanımlarda erişilebilen 300 saniyelik bir toplam tavan işlevi görür. RUNTIME_COMPLETION_TIMEOUT_MS değerini açıkça ayarlamak bu varsayılanı gevşetir.

    "Sonsuza kadar bekle" değildir, çünkü CONCURRENCY=2 varken, kilitlenmiş iki etkin tarama /readyz yeşil kalırken her iki çalışan yuvasını da kalıcı olarak meşgul eder: hazırlık yoklamaları farklı bir uç noktaya gider ve bunu göremez.

Çıkarım çalışma zamanı dilbilgisi kısıtlamalı kod çözmeyi zorunlu kılmalıdır

Bu kesin bir gereksinimdir. İşlem hattı, response_format: {"type": "json_schema", "json_schema": {"name": …, "strict": true, "schema": …}} ile tek bir görme çağrısı yapar ve geri gelen biçime güvenir. Ayrıştır ve yeniden dene döngüsü yoktur.

Tehlikeli hata reddedilme değil, kabul edilip yok sayılmadır: response_format alanını alan, bunu atan ve sözleşmeyi karşılamayan makul bir JSON döndüren bir çıkarım çalışma zamanı. Bu bir hata olarak yüzeye çıkmaz. Biraz hatalı gram tahminleri olarak ortaya çıkar.

Güvenmeden önce Seninkini tek komutla kontrol et. Bir şema talep ederken düzyazı iste; yanıt yine de şema biçimindeyse, dilbilgisi gerçektir:

bash
curl -s http://your-runtime.lan:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"your-model","messages":[{"role":"user","content":"Write a haiku about rain."}],
       "response_format":{"type":"json_schema","json_schema":
         {"name":"t","strict":true,"schema":{"type":"object","properties":{"x":{"type":"string"}},
          "required":["x"],"additionalProperties":false}}}}'

x anahtarına sahip bir JSON nesnesi, zorlamanın çalıştığı anlamına gelir. Bir haiku ise çalışmadığı anlamına gelir ve bu servis, bunu belirten bir mesajla her taramada 502 döndürür.

Destek matrisi

2026-08-15 tarihinde bizzat ölçüldü. Kendi çalıştırmadığımız satırlarda bu durum belirtilmiştir.

Çalışma zamanıSürümGramerGörsel girdisiKarar
llama.cpp (llama-server)b10330zorunlu (GBNF)base64 data URL'si✅ çalışıyor, paketlenmiş kalıbın çalıştırdığı budur
Ollama0.32.13zorunlubase64 data URL'si✅ çalışıyor, aşağıdaki hazır olma notuna bak
vLLM (CPU derlemesi)0.27.1yokyok❌ bozuk: Bir json_schema isteği sunucuyu çökertiyor (pin_memory=True requires a CUDA or other accelerator backend). Düz tamamlama istekleri çalıştığı için ilk gerçek tarama işlemi süreci çökertene kadar sorunsuz görünür
vLLM (GPU derlemesi)0.27.1zorunlu (xgrammar)base64 data URL'si✅ çalışıyor, Qwen3-VL-2B-Instruct ile bir RTX 3090 üzerinde ölçüldü
diğer her şeyyokyokyok⚠️ test edilmedi, yukarıdaki curl komutunu çalıştır

Aynı sürüm, zıt sonuçlar: Sorun doğrudan CPU derlemesindedir. GPU testi, CPU'da çöken özdeş vLLM kalıbını (vllm/vllm-openai:latest ve v0.27.1 aynı özeti paylaşır), bu servisin gönderdiği şema ve base64 görselin aynısıyla çalıştırdı. GPU üzerinde 1.8 saniyede şemaya uygun JSON döndürdü ve ayakta kaldı. ❌ satırını "vLLM desteklenmiyor" olarak değil, "vLLM'yi GPU olmadan çalıştırma" olarak oku.

CPU derlemesinin çökme nedeni. Dilbilgisi kısıtlı kod çözme, bir belirteç bit maskesi oluşturur ve bunu GPU'ya hızlı kopyalama amacıyla kullanılan sayfa kilitli bir arabellek olan sabitlenmiş belleğinde ayırır. Ortamda hızlandırıcı yokken bu talep edilirse, PyTorch bunu yok saymak yerine hata yükseltir. Bu durum doğrulama sırasında değil de sunum sırasında gerçekleştiği için, bir hata döndürmek yerine işçiyi devre dışı bırakır. Bu durum bir yukarı akış hatasıdır: aynı yükü hem llama.cpp hem de Ollama doğru şekilde işler.

Bilinmesinde fayda olan bir vLLM garipliği. Modelin istenen biçimde yanıtlayamadığı bir istem verildiğinde, modelin { ve ardından belirteç sınırına ulaşana kadar boşluk karakterleri ürettiğini gördük: dilbilgisi kuralı korunur (açıkça bir haiku istendiğinde bile asla düz yazı üretmedi), ancak model içerik yerine kısıtlanmamış boşlukları doldurur. Bu durum burada, belirteç sınırını belirten finish_reason: length hatası olarak ortaya çıkar. Gerçek bir tabak fotoğrafı bunu tetiklemedi; kapsam dışı bir istem tetikledi.

Listelemediğimiz bir satırı çalıştırırsan, lütfen sonucu belirten bir sorun kaydı aç.

Üç yapılandırma tuzağı

1. Bağlam penceresi: belirti bir başlangıç hatası değil, bozuk çıktıdır. Fazla küçük bir pencere belirgin bir hata vermez. İstemin baş kısmını atar ve eline kendinden emin bir saçmalık geçer.

İstem boyutu modeline bağlıdır. 896 piksele küçültülmüş aynı tabaklarına ait iki ilk elden ölçüm:

Modelİstem belirteçleri (896 px tabak)
llama.cpp üzerinde Qwen3-VL-8B10 tabaklık derlem genelinde 1.287 ile 3.507 arası
Ollama üzerinde moondream746

Boyutlandırmayı bu sayılara göre yapma: kendi değerlerini oku. Çalışma zamanına karşı tek bir tarama çalıştır ve bildirdiği değere bak:

bash
curl -s .../v1/chat/completions -d '…' | jq .usage.prompt_tokens

Pencereyi, en kötü durumunun da üzerinde, fazladan pay bırakarak boyutlandır. vLLM üzerinde bu --max-model-len değeridir. Ollama üzerinde num_ctx değeridir: bunu bir Modelfile içinde ayarla, çünkü OLLAMA_CONTEXT_LENGTH=8192 ayarının bir modelin bildirilen bağlamını 2048'in üzerine çıkarmada başarısız olduğunu ölçtük (Ollama modelin kendi eğitilmiş bağlamına sabitliyor gibi görünüyor, bu nedenle küçük bir eğitilmiş pencereye sahip bir modele daha büyüğü verilemez).

2. CONCURRENCY, çalışma zamanının gerçek yuva sayısıyla eşleşmelidir. Çalışma zamanının sahip olduğu yuva sayısından daha fazla eşzamanlı istek bulunması işleme kapasitesini artırmaz: kuyruğu bu servisin göremediği veya ölçemediği bir yere taşır ve kabul denetleyicisi bu durumda gerçek dışı bir varsayımla karar verir.

Çalışma zamanıYuvaları ayarlayan bayrak
llama.cpp--parallel N
vLLM--max-num-seqs N
OllamaOLLAMA_NUM_PARALLEL=N

3. Konteynerin HEALTHCHECK değeri başlamak için 60 dakikaya izin verir. Bu süre, ev bağlantısında ilk açılıştaki ağırlık indirme işlemi için boyutlandırılmıştır. Harici modda herhangi bir indirme yapılmaz, bu nedenle yanlış bir MODEL_RUNTIME_URL saniyeler içinde hata vermek yerine bir saat boyunca gizli kalır. start_period derleme sırasında gömülür, bu yüzden onu geçersiz kıl: docker/compose.yml içindeki yorum satırına alınmış bloğa bak.

Hazır olma durumu ve sana söylemedikleri

/readyz, çalışma zamanına GET /health sorgusunu iletir ve /health bulunmayan çalışma zamanları için GET /v1/models seçeneğine geri döner (Ollama'da bu yoktur). İki sınır söz konusudur:

  • Ollama karşısında /v1/models, hazır olma durumunu değil, canlılık durumunu belirtir. Yerleşik sıfır model varken 200 yanıtını verir (Ollama ilk istekte gecikmeli olarak yüklenir), dolayısıyla hazır okuması "ulaşılabilir" anlamına gelir, "ısınmış" anlamına gelmez. İlk taraman yükleme süresini karşılar.
  • /readyz, /health açıkken MODEL_RUNTIME_API_KEY doğrulamasını yapamaz. vLLM üzerinde /health kimlik doğrulaması gerektirmezken /v1/chat/completions gerektirir. Bu nedenle yanlış bir anahtar hazır bildirir ve her taramayı 502 ile başarısızlığa uğratır. Taramalar hazır bir servise karşı 502 döndürüyorsa, önce anahtarı kontrol et.

llama.cpp tarafındaki /health ucundan gelen bir 503, yükleniyor anlamına gelir ve hazır değil olarak bildirilir: hiçbir zaman "bu çalışma zamanında /health yok" şeklinde ele alınmaz.

/readyz ayrıca isteğe bağlı metin gömme (embedding) çalışma zamanını da bildirir; bu durum kodu durumunu hiçbir zaman etkilemeyen üç durumlu bir alandır (varsayılan olan yalnızca sözcüksel erişimdir, bir kesinti değildir):

embeddingReadyAnlamı
nullEMBEDDING_RUNTIME_URL ayarlanmamış. Erişim yapılandırma gereği yalnızca sözcükseldir. Normal.
trueYapılandırılmış ve yanıt veriyor. Erişim hibrittir.
falseYapılandırılmış ve başarısız: embeddingReason nedenini belirtir (ör. http 401). Düzeltilene kadar sıralama daha kötüdür.

Bir sorun olmadığında embeddingReason her zaman null değerindedir, bu yüzden embeddingReason !== null için uyarı tanımlamak güvenlidir. Yanlış bir EMBEDDING_RUNTIME_API_KEY yalnızca burada görünür ve başka hiçbir yerde çıkmaz: taramaları başarısız yapmak yerine sıralamayı düşürür.

Çıkarım çalışma zamanın iyi yanıtlar veriyor mu?

Uyumluluk, doğruluk demek değildir. Bir çalışma zamanı şemayı kusursuz biçimde zorunlu kılabilir ama yine de tabakları kötü okuyan bir modelle eşleştirilmiş olabilir. eval/run-50img.sh, bu belgelerdeki her sayının elde edildiği 50 görsellik referans kümesinin aynısını kullanarak herhangi bir uç noktayı puanlar: çıktıya güvenmeden önce kendi uç noktana yönelt.

Model bazında sunum notları (çalıştırdığımız modeller için bayraklar, beklenmedik davranışlar ve ölçülen performans) için eval/SERVING.md bölümüne bak.

Bu sayfayı GitHub üzerinde düzenle