LibreVLM
Передайте визуально-языковой модели изображение и список слов, чтобы получить рамки. LibreVLM превращает Qwen3-VL, Florence-2 и похожие модели в детекторы объектов с открытым словарём, которые используют тот же API Results, что и остальные модели LibreYOLO.
Введение
Классический детектор поставляется с фиксированным списком классов, встроенным в его голову. LibreVLM снимает это ограничение. Он оборачивает современные визуально-языковые модели, настроенные на выполнение инструкций, запрашивает у них ограничивающие рамки, разбирает сгенерированный текст и возвращает тот же объект Results, который используется для YOLO9 и RF-DETR. Список классов — это просто список слов, передаваемый во время выполнения, поэтому новую категорию можно добавить без затрат и обучения.
- Открытый словарь. Детектируйте
"pink car","license plate"или"the small island", не обучая для них голову. - Одна фабрика, один контракт.
LibreVLM(...)возвращает стандартный объектResultsсboxes.xyxy,boxes.cls,boxes.conf, а также.plot()и.save(). - Взаимозаменяемые бэкенды. Шесть семейств моделей за одной строкой псевдонима, от Florence-2 с 230 млн параметров до Qwen3-VL с 8 млрд.
- Прямой доступ.
chat()позволяет задавать произвольные вопросы об изображении, когда одних рамок недостаточно.
Зачем нужен отдельный уровень и отдельная страница
LibreVLM намеренно не входит в фабрику LibreYOLO(...) с закрытым словарём и её реестр .pt. Эти модели управляются промптами, используют открытый словарь и сообщают синтетическую уверенность, поэтому работают по другому контракту. Отдельный уровень сохраняет основную документацию по детекции ясной и точно описывает, что именно измеряется.
В ветке dev
Сейчас LibreVLM находится в ветке dev и планируется для релиза v1.3, но не входит в v1.2.0. Этот уровень предназначен только для инференса через Python: обучение, валидация, экспорт и CLI пока недоступны, а оценки уверенности служат заглушками. Перед началом работы прочитайте раздел Ограничения.
Установка
LibreVLM доступен через необязательное дополнение vlm. Оно устанавливает свежую версию transformers и вспомогательные пакеты, необходимые нескольким процессорам. Без дополнения импорт семейства VLM вызывает ImportError со ссылкой на эту страницу.
1 pip install 'libreyolo[vlm]'
При первом использовании веса скачиваются из Hugging Face Hub в локальную папку weights/. Некоторые семейства распространяются по лицензиям, не одобренным OSI, и перед скачиванием один раз выводят уведомление. Для крупных бэкендов рекомендуется GPU, но все модели также работают на CPU с device="cpu".
Быстрый старт
Создайте модель, укажите нужные слова и запустите предсказание. По умолчанию используется Qwen3-VL-4B, самый сильный детектор уровня под лицензией 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")
Это весь цикл. Всё после predict() работает как с обычным детектором, поэтому существующий код визуализации, обрезки и трекинга продолжает работать.
Поддерживаемые модели
Выберите бэкенд с помощью псевдонима, передаваемого в LibreVLM(...). Имя семейства без размера разрешается в размер по умолчанию. Общий бэкенд по умолчанию — qwen3-vl-4b. На практике самые сильные детекторы — Qwen3-VL, LFM2-VL и Florence-2.
| Семейство | Псевдоним | Размеры (параметры) | Лицензия | Примечания |
|---|---|---|---|---|
| Qwen3-VL | qwen3-vl-2b / -4b / -8b | 2B / 4B / 8B | Apache-2.0 | Модель по умолчанию и самая сильная. Рекомендуемая отправная точка. |
| LFM2-VL | lfm2-vl-450m / -1.6b | 450M / 1.6B | LFM Open License | Компактный размер для edge-устройств и неожиданно сильная детекция. Требует подтверждения уведомления. |
| InternVL3 | internvl3-1b / -2b / -8b | 1B / 2B / 8B | Qwen License | Хорошая привязка у версии 8B, малые размеры слабее. Требует подтверждения уведомления. |
| Florence-2 | florence-2-base / -large | 0.23B / 0.77B | MIT | Специализированная модель привязки. Точные рамки, без chat(). |
| SmolVLM2 | smolvlm2-500m / -2.2b | 500M / 2.2B | Apache-2.0 | Очень компактная и быстрая, но слабее в детекции. Подходит для быстрых проб. |
| Kosmos-2 | kosmos-2 | ~1.6B | MIT | Модель привязки 2023 года. Менее точные рамки, без chat(). |
Выбор бэкенда
- Лучшее качество:
qwen3-vl-8bилиqwen3-vl-4b(по умолчанию). - Точные рамки и малый размер:
florence-2-large. - Edge-устройства и CPU:
lfm2-vl-450mилиsmolvlm2-500m. - Полностью разрешительная лицензия: любой размер Qwen3-VL, SmolVLM2, Florence-2 или Kosmos-2.
Лицензирование
Qwen3-VL и SmolVLM2 распространяются по Apache-2.0, а Florence-2 и Kosmos-2 — по MIT. У LFM2-VL и InternVL3 лицензии, не одобренные OSI, поэтому перед первым скачиванием они выводят однократное уведомление, чтобы решение о коммерческом использовании было осознанным.
Настройка словаря
Словарь — основа детекции с открытым словарём. Вызовите set_classes() со списком строковых меток. Он сохраняется для всех последующих вызовов predict() и track(), пока не будет задан снова. Метод возвращает self, поэтому вызовы можно объединять в цепочку.
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"])
Метки могут быть любыми фразами. Они должны быть уникальными без учёта регистра, и передавать нужно список, а не отдельную строку. Если set_classes() ни разу не вызывался, модель использует словарь COCO-80, поэтому вызов predict() без дополнительных настроек всё равно даёт осмысленный результат.
Предсказание
predict() и эквивалентный вызов model(...) принимают те же типы источников, что и любой детектор LibreYOLO: путь, изображение PIL, массив NumPy, URL, папку или видео. stream=True и 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 )
Форма результата
Возвращается стандартный объект Results, такой же, как у детектора с закрытым словарём:
| Поле | Форма / тип | Значение |
|---|---|---|
result.boxes.xyxy | N x 4 | Пиксельные рамки [x1, y1, x2, y2], масштабированные до исходного изображения. |
result.boxes.cls | N | Идентификаторы классов, ссылающиеся на словарь из set_classes(). |
result.boxes.conf | N | Синтетическая уверенность: 1.0 для каждой рамки (см. раздел «Ограничения»). |
result.plot() / .save() | - | Обычные вспомогательные методы для отрисовки и сохранения. |
Внутри LibreVLM устойчиво разбирает вывод модели, обрабатывая ограждения Markdown, посторонний текст, повторяющиеся рамки и обрезанные массивы, сопоставляет произвольные текстовые метки с идентификаторами классов и отбрасывает метки, которых нет в словаре. Именно последний шаг заставляет генератор произвольного текста работать как детектор с закрытым набором классов.
Примеры
Детекция объекта заданного цвета
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")
Точные рамки с 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()
Фильтрация до одного класса на лету
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])
Запуск на CPU со встроенным примером изображения
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"
Батчи, папки и видео
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)
Прямой доступ к чату
Иногда нужна сама модель, а не детектор. Семейства с шаблонами чата предоставляют chat(), который принимает изображение и произвольный промпт, а затем дословно возвращает декодированный текст. Используйте его для подсчёта, создания подписей или быстрых вопросов об изображении.
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() доступен в семействах с шаблонами чата (Qwen3-VL, LFM2-VL, SmolVLM2, InternVL3). Florence-2 и Kosmos-2 используют токены задач для привязки и вызывают NotImplementedError. Для них используйте predict().
Различия бэкендов
Все семейства возвращают одинаковый объект Results, но получают его по-разному. Обычно это неважно, однако различия объясняют поведение некоторых бэкендов. У семейств с чатом запрашивается JSON-массив рамок, а модели привязки используют специальные токены задач.
| Семейство | Промпт | Пространство координат | chat() |
|---|---|---|---|
| Qwen3-VL | JSON-промпт с рамками | От 0 до 1000, масштабированные | Да |
| LFM2-VL | JSON-промпт с рамками | Нормализованные от 0 до 1 | Да |
| SmolVLM2 | JSON-промпт с рамками | Нормализованные от 0 до 1 | Да |
| InternVL3 | JSON-промпт с рамками | От 0 до 1000, масштабированные | Да |
| Florence-2 | Токен задачи | Исходные пиксели | Нет |
| Kosmos-2 | Промпт привязки | Нормализованные, масштабированные | Нет |
Для семейств с чатом промпт детекции можно переопределить аргументом конструктора prompt=, а длину генерации ограничить с помощью max_new_tokens=. Устройство и dtype определяются автоматически: bf16 или fp16 на CUDA, fp32 на CPU.
Ограничения
LibreVLM обладает широкими возможностями, но всё ещё молод. Знание ограничений заранее поможет избежать неожиданностей.
- Синтетическая уверенность. Каждая рамка получает оценку 1.0. Поэтому фильтр
conf=работает по принципу «всё или ничего», а не как настоящий порог. - Нет mAP и валидации.
val()вызывает исключение, поскольку синтетические оценки сделали бы COCO mAP недостоверным. - Нет обучения и экспорта.
train()иexport()вызывают исключение. Вместо этого дообучите VLM в исходном проекте и загрузите полученные веса. - Качество трекинга снижено.
track()работает, но одинаковые оценки делают неактивным этап восстановления трекера при низкой уверенности. - По одному изображению. В v1 генерация выполняется последовательно, поэтому увеличение
batch=не ускоряет работу. - Только Python API. CLI
libreyoloпока не разрешает псевдонимы VLM.
Где LibreVLM особенно полезен
Используйте LibreVLM, когда набор классов открыт, часто меняется или его трудно разметить заранее: для быстрого прототипирования, редких категорий или сценариев «найти то, что описано словами». Если нужны откалиброванная уверенность, пропускная способность или готовый к развёртыванию артефакт, обучите YOLO9 или RF-DETR с закрытым словарём по основной документации.