Cette section n'est disponible qu'en anglais pour le moment.
Documentation principale
Niveau expérimental

LibreVLM

Pointez un modèle de vision-langage vers une image, fournissez-lui une liste de mots et récupérez des boîtes. LibreVLM transforme Qwen3-VL, Florence-2 et les modèles similaires en détecteurs d'objets à vocabulaire ouvert qui utilisent exactement la même API Results que tous les autres modèles LibreYOLO.

Introduction

Un détecteur classique est fourni avec une liste fixe de classes intégrée à sa tête. LibreVLM supprime cette contrainte. Il encapsule des modèles de vision-langage modernes affinés par instructions, leur demande d'émettre des bounding boxes, analyse le texte généré et renvoie le même objet Results que celui que vous utilisez déjà avec YOLO9 et RF-DETR. La liste de classes n'est qu'une liste de mots que vous fournissez au runtime : ajouter une catégorie ne coûte donc rien et fonctionne en zero-shot.

  • Vocabulaire ouvert. Détectez "pink car", "license plate" ou "the small island" sans jamais entraîner de tête pour ces classes.
  • Une factory, un contrat. LibreVLM(...) renvoie l'objet Results standard avec boxes.xyxy, boxes.cls et boxes.conf, ainsi que .plot() et .save().
  • Backends interchangeables. Six familles de modèles derrière une seule chaîne d'alias, de Florence-2 230M à Qwen3-VL 8B.
  • Un accès brut. chat() vous permet de poser des questions libres sur une image lorsque les boîtes ne suffisent pas.

Pourquoi un niveau distinct (et une page distincte)

LibreVLM est délibérément tenu à l'écart de la factory LibreYOLO(...) à vocabulaire fermé et de son registre .pt. Ces modèles sont pilotés par prompt, à vocabulaire ouvert et indiquent une confiance synthétique : ils respectent donc un contrat différent. Les traiter comme un niveau distinct permet de conserver une documentation de détection principale claire et fidèle aux mesures effectuées.

Sur la branche dev

LibreVLM se trouve actuellement sur la branche dev et vise la version v1.3 ; il ne fait pas partie de v1.2.0. C'est un niveau d'inférence réservé à Python : l'entraînement, la validation, l'export et le chemin CLI ne sont pas encore disponibles, et les scores de confiance sont des valeurs temporaires. Lisez la section Limitations avant de vous appuyer dessus.

Installation

LibreVLM est disponible via l'extra facultatif vlm. Celui-ci installe une version récente de transformers et les utilitaires requis par certains processeurs. Sans cet extra, l'import d'une famille VLM déclenche une ImportError qui vous renvoie ici.

bash
1pip install 'libreyolo[vlm]'

Les poids sont téléchargés depuis le Hub Hugging Face lors de la première utilisation, dans un dossier local weights/. Quelques familles sont fournies sous des licences non OSI et affichent un avertissement unique avant le téléchargement. Un GPU est recommandé pour les backends les plus volumineux, mais chaque modèle fonctionne aussi sur CPU avec device="cpu".

Démarrage rapide

Construisez un modèle, définissez les mots qui vous intéressent et lancez une prédiction. Le backend par défaut est Qwen3-VL-4B, le détecteur le plus performant du niveau, sous licence Apache-2.0.

python
1from libreyolo import LibreVLM
2
3# Qwen3-VL-4B by default; weights autodownload on first use
4model = LibreVLM()
5
6# The vocabulary is just words. Any words.
7model.set_classes(["pink car", "wheel"])
8
9result = model.predict("street.jpg")
10
11print(result.boxes.xyxy) # pixel [x1, y1, x2, y2]
12print(result.boxes.cls) # ids into ["pink car", "wheel"]
13result.plot() # same drawing helpers as any LibreYOLO model
14result.save("out.jpg")

La boucle complète se résume à cela. Tout ce qui suit predict() se comporte comme avec un détecteur normal : le code existant de visualisation, de recadrage et de suivi continue donc de fonctionner.

Modèles pris en charge

Choisissez un backend avec l'alias que vous transmettez à LibreVLM(...). Un nom de famille seul correspond à sa taille par défaut. Le backend global par défaut est qwen3-vl-4b. En pratique, les détecteurs les plus performants sont Qwen3-VL, LFM2-VL et Florence-2.

FamilleAliasTailles (paramètres)LicenceNotes
Qwen3-VLqwen3-vl-2b / -4b / -8b2B / 4B / 8BApache-2.0Modèle par défaut et le plus performant. Point de départ recommandé.
LFM2-VLlfm2-vl-450m / -1.6b450M / 1.6BLFM Open LicenseConçu pour l'edge, petit détecteur étonnamment performant. Soumis à un avertissement.
InternVL3internvl3-1b / -2b / -8b1B / 2B / 8BQwen LicenseBon grounding à 8B ; les petites tailles sont peu performantes. Soumis à un avertissement.
Florence-2florence-2-base / -large0.23B / 0.77BMITModèle de grounding dédié. Boîtes ajustées, pas de chat().
SmolVLM2smolvlm2-500m / -2.2b500M / 2.2BApache-2.0Minuscule et rapide ; détecteur moins performant. Adapté aux essais rapides.
Kosmos-2kosmos-2~1.6BMITModèle de grounding de 2023. Boîtes plus approximatives, pas de chat().

Choisir un backend

  • Meilleure qualité : qwen3-vl-8b ou qwen3-vl-4b (modèle par défaut).
  • Boîtes ajustées, faible encombrement : florence-2-large.
  • Edge / CPU : lfm2-vl-450m ou smolvlm2-500m.
  • Licence entièrement permissive : toutes les tailles de Qwen3-VL, SmolVLM2, Florence-2 ou Kosmos-2.

Licences

Qwen3-VL et SmolVLM2 sont sous licence Apache-2.0 ; Florence-2 et Kosmos-2 sont sous licence MIT. LFM2-VL et InternVL3 utilisent des licences non OSI et affichent un avertissement unique avant leur premier téléchargement, afin que vous puissiez faire un choix éclairé pour un usage commercial.

Définir le vocabulaire

Le vocabulaire est au cœur de la détection à vocabulaire ouvert. Appelez set_classes() avec une liste de chaînes d'étiquettes. Ce réglage est persistant : il s'applique à tous les appels ultérieurs à predict() et track() jusqu'à ce que vous le redéfinissiez. La méthode renvoie self, ce qui permet de chaîner les appels.

python
1# Sticky and chainable
2model = LibreVLM("qwen3-vl-2b").set_classes(["person", "dog", "cat"])
3
4# Set it once at construction instead
5model = LibreVLM("lfm2-vl-450m", names=["boat"], device="cpu")
6
7# Re-set any time to change what you are looking for
8model.set_classes(["a red car", "a blue truck"])

Les étiquettes peuvent être n'importe quelle expression. Elles doivent être uniques sans tenir compte de la casse, et vous devez transmettre une liste, pas une simple chaîne. Si vous n'appelez jamais set_classes(), le modèle utilise le vocabulaire COCO-80 par défaut afin qu'un simple predict() produise tout de même un résultat pertinent.

Prédiction

predict() (et l'appel équivalent à model(...)) accepte les mêmes types de sources que tous les détecteurs LibreYOLO : un chemin, une image PIL, un tableau numpy, une URL, un dossier ou une vidéo. stream=True et track() fonctionnent aussi.

python
1result = 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)

Structure du retour

Vous récupérez l'objet Results standard, identique à celui d'un détecteur à vocabulaire fermé :

ChampForme / typeSignification
result.boxes.xyxyN x 4Boîtes en pixels [x1, y1, x2, y2], redimensionnées aux dimensions de l'image d'origine.
result.boxes.clsNIdentifiants de classe indexant votre vocabulaire set_classes().
result.boxes.confNConfiance synthétique : 1.0 pour chaque boîte (voir Limitations).
result.plot() / .save()-Utilitaires habituels de dessin et d'enregistrement.

En interne, LibreVLM analyse avec tolérance la sortie du modèle (blocs délimités en Markdown, texte parasite, boîtes dupliquées et tableaux tronqués), remappe les étiquettes de texte libre vers vos identifiants de classe et ignore toute étiquette absente de votre vocabulaire. Cette dernière étape permet à un générateur libre de se comporter comme un détecteur à ensemble fermé.

Exemples

Détecter un objet d'une couleur précise

python
1from libreyolo import LibreVLM
2
3model = LibreVLM("qwen3-vl-4b")
4model.set_classes(["red car"])
5
6result = model.predict("parking_lot.jpg")
7print(f"Found {len(result.boxes.cls)} red car(s)")
8result.save("red_cars.jpg")

Boîtes ajustées avec Florence-2

python
1# Florence-2 is a purpose-built grounder: very tight pixel boxes.
2model = LibreVLM("florence-2-large")
3model.set_classes(["a red car", "license plate"])
4
5result = model.predict("car.jpg")
6result.plot()

Filtrer à la volée sur une seule classe

python
1model = LibreVLM("qwen3-vl-2b").set_classes(["person", "dog", "cat"])
2
3# classes= filters the configured vocabulary by id
4people_only = model.predict("street.jpg", classes=[0])

Exécuter sur CPU avec une image d'exemple intégrée

python
1from libreyolo import LibreVLM, SAMPLE_IMAGE
2
3model = LibreVLM("lfm2-vl-450m", device="cpu")
4# No set_classes() -> falls back to the COCO-80 vocabulary
5result = model.predict(SAMPLE_IMAGE)
6print(model.names[result.boxes.cls[0]]) # e.g. "person"

Batchs, dossiers et vidéo

python
1model = LibreVLM().set_classes(["forklift", "pallet"])
2
3# A whole folder
4for result in model.predict("warehouse_frames/", stream=True):
5 result.save()
6
7# A video file (frames are processed one at a time)
8model.predict("warehouse.mp4", save=True)

Chat brut

Vous avez parfois besoin du modèle, pas du détecteur. Les familles à template de chat exposent chat(), qui reçoit une image et un prompt libre, puis renvoie le texte décodé tel quel. Utilisez-la pour compter, générer des légendes ou répondre à des questions visuelles rapides.

python
1model = LibreVLM("qwen3-vl-4b")
2
3answer = model.chat("harbor.jpg", "How many boats are docked? Answer with a number.")
4print(answer)

chat() est disponible pour les familles à template de chat (Qwen3-VL, LFM2-VL, SmolVLM2, InternVL3). Florence-2 et Kosmos-2 sont des modèles de grounding à token de tâche et déclenchent une NotImplementedError ; utilisez predict() avec eux.

Différences entre les backends

Chaque famille renvoie le même Results, mais y parvient différemment. Vous avez rarement besoin de vous en préoccuper, mais ces détails expliquent le comportement de certains backends. Les familles de chat reçoivent un prompt demandant un tableau JSON de boîtes ; les modèles de grounding utilisent des tokens de tâche dédiés.

FamilleMéthode de promptingEspace de coordonnéeschat()
Qwen3-VLPrompt JSON de boîtes0 à 1000, remis à l'échelleOui
LFM2-VLPrompt JSON de boîtesNormalisé de 0 à 1Oui
SmolVLM2Prompt JSON de boîtesNormalisé de 0 à 1Oui
InternVL3Prompt JSON de boîtes0 à 1000, remis à l'échelleOui
Florence-2Token de tâchePixels natifsNon
Kosmos-2Prompt de groundingNormalisé, remis à l'échelleNon

Pour les familles de chat, vous pouvez remplacer le prompt de détection avec l'argument de constructeur prompt= et limiter la longueur de génération avec max_new_tokens=. Le device et le dtype sont déterminés automatiquement : bf16 ou fp16 sur CUDA, fp32 sur CPU.

Limitations

LibreVLM est puissant mais encore jeune. Connaître ses limites dès le départ évite les surprises.

  • Confiance synthétique. Chaque boîte reçoit un score de 1.0. Le filtre conf= fonctionne donc en tout ou rien, plutôt que comme un véritable seuil.
  • Pas de mAP ni de validation. val() déclenche une erreur, car des scores synthétiques rendraient la mAP COCO trompeuse.
  • Pas d'entraînement ni d'export. train() et export() déclenchent une erreur. Faites le fine-tuning du VLM en amont et chargez plutôt les poids obtenus.
  • Suivi dégradé. track() s'exécute, mais les scores uniformes rendent inopérante l'étape de récupération à faible confiance du tracker.
  • Une seule image à la fois. La génération est séquentielle dans la v1, donc augmenter la valeur de batch= n'accélère pas le traitement.
  • API Python uniquement. La CLI libreyolo ne résout pas encore les alias VLM.

Cas d'usage idéaux

Utilisez LibreVLM lorsque l'ensemble de classes est ouvert, change souvent ou est difficile à étiqueter en amont : prototypage rapide, catégories rares ou de longue traîne, et workflows « trouver l'objet que je décris avec des mots ». Quand vous avez besoin d'une confiance calibrée, de débit ou d'un artefact déployable, entraînez un YOLO9 ou RF-DETR à vocabulaire fermé à partir de la documentation principale.

Inférence uniquementbranche dev / version v1.3 viséeSource sur GitHub