LibreVLM
Skieruj model wizyjno-językowy na obraz, przekaż mu listę słów i odbierz ramki. LibreVLM zmienia Qwen3-VL, Florence-2 i podobne modele w detektory obiektów z otwartym słownikiem, które korzystają z dokładnie tego samego API Results co każdy inny model LibreYOLO.
Wprowadzenie
Klasyczny detektor ma stałą listę klas zapisaną w głowicy. LibreVLM usuwa to ograniczenie. Opakowuje nowoczesne modele wizyjno-językowe dostrojone do wykonywania instrukcji, skłania je do zwracania ramek ograniczających, analizuje wygenerowany tekst i zwraca ten sam obiekt Results, który jest używany z YOLO9 i RF-DETR. Lista klas to po prostu lista słów przekazywana w czasie działania, więc dodanie nowej kategorii nic nie kosztuje i działa w trybie zero-shot.
- Otwarty słownik. Wykrywaj
"pink car","license plate"lub"the small island"bez trenowania dla nich głowicy. - Jedna fabryka, jeden kontrakt.
LibreVLM(...)zwraca standardowy obiektResultszboxes.xyxy,boxes.clsiboxes.conf, a także metodami.plot()oraz.save(). - Wymienne backendy. Sześć rodzin modeli za jednym ciągiem aliasu, od Florence-2 z 230 mln parametrów po Qwen3-VL z 8 mld parametrów.
- Bezpośredni dostęp.
chat()pozwala swobodnie zadawać pytania o obraz, gdy potrzeba więcej niż ramek.
Dlaczego osobny poziom (i osobna strona)
LibreVLM celowo pozostaje poza fabryką LibreYOLO(...) o zamkniętym słowniku i jej rejestrem .pt. Te modele są sterowane promptami, korzystają z otwartego słownika i podają syntetyczny wskaźnik pewności, dlatego obowiązuje je inny kontrakt. Wydzielenie ich na osobny poziom pozwala zachować przejrzystość głównej dokumentacji detekcji i jasno opisać, co jest mierzone.
W gałęzi dev
LibreVLM znajduje się obecnie w gałęzi dev i jest planowany na wydanie v1.3. Nie jest częścią v1.2.0. Jest to poziom inferencji dostępny tylko przez API Pythona: nie ma jeszcze ścieżki trenowania, walidacji, eksportu ani CLI, a wskaźniki pewności są wartościami zastępczymi. Przed rozpoczęciem pracy przeczytaj sekcję Ograniczenia.
Instalacja
LibreVLM jest dostępny przez opcjonalny dodatek vlm. Instaluje on aktualną wersję transformers oraz narzędzia pomocnicze wymagane przez niektóre procesory. Bez tego dodatku importowanie rodziny VLM zgłasza ImportError ze wskazaniem tej strony.
1 pip install 'libreyolo[vlm]'
Przy pierwszym użyciu wagi są pobierane z Hugging Face Hub do lokalnego folderu weights/. Niektóre rodziny są objęte licencjami spoza OSI i przed pobraniem jednorazowo wyświetlają powiadomienie. W przypadku większych backendów zalecane jest GPU, ale każdy model działa także na CPU z ustawieniem device="cpu".
Szybki start
Utwórz model, podaj interesujące słowa i uruchom predykcję. Domyślnym backendem jest Qwen3-VL-4B, najsilniejszy detektor na tym poziomie, objęty licencją Apache-2.0.
1 from libreyolo import LibreVLM 2 3 # Qwen3-VL-4B by default; weights autodownload on first use 4 model = LibreVLM() 5 6 # The vocabulary is just words. Any words. 7 model.set_classes(["pink car", "wheel"]) 8 9 result = model.predict("street.jpg") 10 11 print(result.boxes.xyxy) # pixel [x1, y1, x2, y2] 12 print(result.boxes.cls) # ids into ["pink car", "wheel"] 13 result.plot() # same drawing helpers as any LibreYOLO model 14 result.save("out.jpg")
To cały przebieg. Wszystko za predict() zachowuje się jak zwykły detektor, więc istniejący kod wizualizacji, wycinania i śledzenia nadal działa.
Obsługiwane modele
Wybierz backend za pomocą aliasu przekazywanego do LibreVLM(...). Sama nazwa rodziny wskazuje jej domyślny rozmiar. Ogólnym domyślnym backendem jest qwen3-vl-4b. W praktyce najsilniejszymi detektorami są Qwen3-VL, LFM2-VL i Florence-2.
| Rodzina | Nazwa aliasu | Rozmiary (parametry) | Licencja | Uwagi |
|---|---|---|---|---|
| Qwen3-VL | qwen3-vl-2b / -4b / -8b | 2B / 4B / 8B | Apache-2.0 | Domyślny i najsilniejszy. Zalecany punkt wyjścia. |
| LFM2-VL | lfm2-vl-450m / -1.6b | 450M / 1.6B | LFM Open License | Rozmiar odpowiedni dla urządzeń brzegowych, zaskakująco silny mały detektor. Wymaga zaakceptowania powiadomienia. |
| InternVL3 | internvl3-1b / -2b / -8b | 1B / 2B / 8B | Qwen License | Dobre ugruntowanie przy 8 mld parametrów, małe rozmiary są słabe. Wymaga zaakceptowania powiadomienia. |
| Florence-2 | florence-2-base / -large | 0.23B / 0.77B | MIT | Model stworzony specjalnie do ugruntowania. Precyzyjne ramki, bez chat(). |
| SmolVLM2 | smolvlm2-500m / -2.2b | 500M / 2.2B | Apache-2.0 | Bardzo mały i szybki, ale słabszy jako detektor. Dobry do szybkich prób. |
| Kosmos-2 | kosmos-2 | ~1.6B | MIT | Model ugruntowujący z 2023 roku. Mniej precyzyjne ramki, bez chat(). |
Wybór backendu
- Najlepsza jakość:
qwen3-vl-8blubqwen3-vl-4b(domyślny). - Precyzyjne ramki, mały rozmiar:
florence-2-large. - Urządzenia brzegowe / CPU:
lfm2-vl-450mlubsmolvlm2-500m. - W pełni permisywna licencja: dowolny rozmiar Qwen3-VL, SmolVLM2, Florence-2 lub Kosmos-2.
Licencjonowanie
Qwen3-VL i SmolVLM2 są objęte licencją Apache-2.0, a Florence-2 i Kosmos-2 licencją MIT. LFM2-VL i InternVL3 są objęte licencjami spoza OSI i przed pierwszym pobraniem jednorazowo wyświetlają powiadomienie, co pozwala podjąć świadomą decyzję dotyczącą użycia komercyjnego.
Ustawianie słownika
Słownik stanowi podstawę detekcji z otwartym słownikiem. Wywołaj set_classes() z listą ciągów etykiet. Ustawienie jest trwałe: obowiązuje przy każdym późniejszym wywołaniu predict() i track(), dopóki nie zostanie zmienione. Metoda zwraca self, więc można łączyć wywołania.
1 # Sticky and chainable 2 model = LibreVLM("qwen3-vl-2b").set_classes(["person", "dog", "cat"]) 3 4 # Set it once at construction instead 5 model = LibreVLM("lfm2-vl-450m", names=["boat"], device="cpu") 6 7 # Re-set any time to change what you are looking for 8 model.set_classes(["a red car", "a blue truck"])
Etykietą może być dowolna fraza. Etykiety muszą być unikatowe bez względu na wielkość liter i należy przekazać listę, a nie pojedynczy ciąg. Jeśli set_classes() nie zostanie wywołane, model użyje słownika COCO-80, dzięki czemu samo predict() nadal zwróci sensowny wynik.
Predykcja
predict() (or równoważne wywołanie model(...)) przyjmuje te same typy źródeł co każdy detektor LibreYOLO: ścieżkę, obraz PIL, tablicę numpy, adres URL, folder lub wideo. Działają także stream=True i track().
1 result = model.predict( 2 source="image.jpg", # path | PIL | ndarray | URL | folder | video 3 conf=0.25, # see note below: scoring is synthetic 4 classes=[0], # optional: keep only these vocabulary ids 5 max_det=300, 6 )
Struktura wyniku
Zwracany jest standardowy obiekt Results, identyczny jak w detektorze z zamkniętym słownikiem:
| Pole | Kształt / typ | Znaczenie |
|---|---|---|
result.boxes.xyxy | N x 4 | Ramki w pikselach [x1, y1, x2, y2], przeskalowane do oryginalnego obrazu. |
result.boxes.cls | N | Identyfikatory klas indeksujące słownik set_classes(). |
result.boxes.conf | N | Syntetyczny wskaźnik pewności: 1.0 dla każdej ramki (zobacz Ograniczenia). |
result.plot() / .save() | - | Standardowe narzędzia pomocnicze do rysowania i zapisywania. |
Wewnętrznie LibreVLM elastycznie analizuje wynik modelu (obsługuje bloki Markdown, zbędną prozę, zduplikowane ramki i ucięte tablice), mapuje etykiety w swobodnym tekście z powrotem na identyfikatory klas i odrzuca każdą etykietę spoza słownika. Ten ostatni krok sprawia, że generator swobodnego tekstu zachowuje się jak detektor z zamkniętym zbiorem klas.
Przykłady
Detekcja obiektu o określonym kolorze
1 from libreyolo import LibreVLM 2 3 model = LibreVLM("qwen3-vl-4b") 4 model.set_classes(["red car"]) 5 6 result = model.predict("parking_lot.jpg") 7 print(f"Found {len(result.boxes.cls)} red car(s)") 8 result.save("red_cars.jpg")
Precyzyjne ramki z Florence-2
1 # Florence-2 is a purpose-built grounder: very tight pixel boxes. 2 model = LibreVLM("florence-2-large") 3 model.set_classes(["a red car", "license plate"]) 4 5 result = model.predict("car.jpg") 6 result.plot()
Filtrowanie do jednej klasy w locie
1 model = LibreVLM("qwen3-vl-2b").set_classes(["person", "dog", "cat"]) 2 3 # classes= filters the configured vocabulary by id 4 people_only = model.predict("street.jpg", classes=[0])
Uruchamianie na CPU z wbudowanym obrazem przykładowym
1 from libreyolo import LibreVLM, SAMPLE_IMAGE 2 3 model = LibreVLM("lfm2-vl-450m", device="cpu") 4 # No set_classes() -> falls back to the COCO-80 vocabulary 5 result = model.predict(SAMPLE_IMAGE) 6 print(model.names[result.boxes.cls[0]]) # e.g. "person"
Batche, foldery i wideo
1 model = LibreVLM().set_classes(["forklift", "pallet"]) 2 3 # A whole folder 4 for result in model.predict("warehouse_frames/", stream=True): 5 result.save() 6 7 # A video file (frames are processed one at a time) 8 model.predict("warehouse.mp4", save=True)
Surowy czat
Czasami potrzebny jest model, a nie detektor. Rodziny korzystające z szablonu czatu udostępniają chat(), które przyjmuje obraz i swobodny prompt, a następnie zwraca zdekodowany tekst bez zmian. Można użyć tej metody do liczenia, tworzenia podpisów lub zadawania szybkich pytań wizualnych.
1 model = LibreVLM("qwen3-vl-4b") 2 3 answer = model.chat("harbor.jpg", "How many boats are docked? Answer with a number.") 4 print(answer)
chat() jest dostępne w rodzinach korzystających z szablonu czatu (Qwen3-VL, LFM2-VL, SmolVLM2, InternVL3). Florence-2 i Kosmos-2 to modele ugruntowujące z tokenami zadań i zgłaszają NotImplementedError. Z tymi modelami należy użyć predict().
Różnice między backendami
Każda rodzina zwraca ten sam obiekt Results, ale dochodzi do niego w inny sposób. Rzadko ma to znaczenie, jednak warto wiedzieć, dlaczego niektóre backendy zachowują się w określony sposób. Rodziny czatowe otrzymują prompt z żądaniem tablicy ramek JSON, a modele ugruntowujące używają dedykowanych tokenów zadań.
| Rodzina | Promptowanie | Przestrzeń współrzędnych | chat() |
|---|---|---|---|
| Qwen3-VL | Prompt ramek JSON | Od 0 do 1000, przeskalowane | Tak |
| LFM2-VL | Prompt ramek JSON | Znormalizowane od 0 do 1 | Tak |
| SmolVLM2 | Prompt ramek JSON | Znormalizowane od 0 do 1 | Tak |
| InternVL3 | Prompt ramek JSON | Od 0 do 1000, przeskalowane | Tak |
| Florence-2 | Token zadania | Natywne piksele | Nie |
| Kosmos-2 | Prompt ugruntowania | Znormalizowane, przeskalowane | Nie |
W rodzinach czatowych można zastąpić prompt detekcji argumentem konstruktora prompt= i ograniczyć długość generowania za pomocą max_new_tokens=. Urządzenie i dtype są dobierane automatycznie: bf16 lub fp16 na CUDA, fp32 na CPU.
Ograniczenia
LibreVLM ma duże możliwości, ale jest młodym projektem. Znajomość ograniczeń od początku pozwala uniknąć późniejszych niespodzianek.
- Syntetyczny wskaźnik pewności. Każda ramka otrzymuje wynik 1.0. Filtr
conf=działa więc na zasadzie wszystko albo nic, a nie jak rzeczywisty próg. - Brak mAP i walidacji.
val()zgłasza wyjątek, ponieważ syntetyczne wyniki sprawiłyby, że mAP na COCO byłoby mylące. - Brak trenowania i eksportu.
train()iexport()zgłaszają wyjątek. Zamiast tego dostrój VLM w projekcie źródłowym i wczytaj uzyskane wagi. - Ograniczone śledzenie.
track()działa, ale jednakowe wyniki powodują, że etap odzyskiwania detekcji o niskiej pewności w trackerze jest nieaktywny. - Jeden obraz naraz. W wersji v1 generowanie jest sekwencyjne, więc większe wartości
batch=nie przyspieszają działania. - Tylko API Pythona. CLI
libreyolonie rozpoznaje jeszcze aliasów VLM.
Najlepsze zastosowania
Użyj LibreVLM, gdy zbiór klas jest otwarty, często się zmienia lub trudno go z góry opisać etykietami: do szybkiego prototypowania, kategorii z długiego ogona lub rzadkich oraz przepływów typu „znajdź obiekt opisany słowami”. Gdy potrzebny jest skalibrowany wskaźnik pewności, przepustowość lub artefakt gotowy do wdrożenia, wytrenuj model YOLO9 albo RF-DETR z zamkniętym słownikiem zgodnie z główną dokumentacją.