|
|
--- |
|
|
library_name: transformers |
|
|
tags: |
|
|
- avito |
|
|
- multimodal |
|
|
- vlm |
|
|
- vision-language |
|
|
- ocr |
|
|
license: apache-2.0 |
|
|
language: |
|
|
- ru |
|
|
- en |
|
|
base_model: |
|
|
- Qwen/Qwen2.5-VL-7B-Instruct |
|
|
pipeline_tag: image-text-to-text |
|
|
--- |
|
|
|
|
|
|
|
|
# A-Vision — русскоязычная VLM Авито |
|
|
|
|
|
A-Vision — Visual-Language модель, адаптированная под русский язык и домен Авито. Она понимает изображение и текст вместе: описывает фото, отвечает на вопросы по картинке, сверяет соответствие описания и фото, извлекает бренды/надписи/произвольный текст (OCR). |
|
|
|
|
|
## Зачем и как делали |
|
|
|
|
|
* **Данные.** Собрали собственный русскоязычный мультимодальный корпус: ~200k изображений объявлений и ≈1M пар «вопрос–ответ», дополненный тщательно локализованными наборами (вместо «сырого» машинного перевода).Также перевели несколько OS-датасетов. |
|
|
* **Адаптация LLM.** Заменили токенизатор на русскоязычный; провели **freeze→unfreeze** LLM-части модели на большом корпусе русскоязычного текста. |
|
|
* **Мультимодальное SFT.** Дообучили модель на собранном датасете «изображение+вопрос → ответ». |
|
|
* **RL-этап.** Провели DPO, которое позволило добиться от модели безопасных ответов. |
|
|
* **Результат.** Ускорение модели на 50% на русских данных. Рост качества на русскоязычных и доменных тестах (Авито-метрика генерации описаний +6%, MMMU_RU +1%, RealWorldQA_RU +1%) при сохранении универсальных VLM-навыков; небольшая просадка на части англоязычных бенчмарков ожидаема из-за фокуса на русском. |
|
|
|
|
|
| Метрика | Qwen2.5-VL-7B-Instruct | **A-Vision** | |
|
|
| :--------------- | :--------------------: | :----------: | |
|
|
| AvitoImageGen_RU | 0.7259 | **0.7668** | |
|
|
| MMMU_EN | **0.543** | 0.489 | |
|
|
| MMMU_RU | 0.469 | **0.474** | |
|
|
| RealWorldQA_EN | 0.673 | **0.693** | |
|
|
| RealWorldQA_RU | 0.647 | **0.652** | |
|
|
| OCRBench_EN | **878** | 834 | |
|
|
| OCRVQA_EN | **77.506** | 74.4098 | |
|
|
| ChartQA_EN | **86.44** | 86 | |
|
|
| DocVQA_EN | 94.7458 | **94.9702** | |
|
|
|
|
|
|
|
|
В токенизаторе A-vision плотность токенизации выше, чем у Qwen2.5-VL-7B-Instruct, поэтому число токенов в контексте и при генерации стало меньше для одинаковых примеров. Кроме того, размер самой модели сократился до 7.4B, при 8.3B у Qwen2.5-VL-7B-Instruct. За счет этого одинаковые русскоязычные примеры адаптированной моделью обрабатываются быстрее в среднем на 50% в сравнении с исходной Qwen2.5-VL-7B-Instruct. |
|
|
|
|
|
## Где используем в продукте |
|
|
|
|
|
* 📝 Автогенерация описаний карточек по фото |
|
|
* 🔍 Ключевые слова для поиска (извлечение признаков с изображений) |
|
|
* 🧾 OCR брендов/надписей и их нормализация |
|
|
* ⚡ «Подача объявления в один клик» по фото товара |
|
|
* 🔧 Внутренние инструменты разметки и модерации |
|
|
|
|
|
--- |
|
|
|
|
|
## Quickstart |
|
|
|
|
|
Ниже — минимальный пример инференса VLM (текст+картинка). |
|
|
|
|
|
```python |
|
|
import torch |
|
|
from PIL import Image |
|
|
from transformers import AutoProcessor, AutoModelForImageTextToText |
|
|
from qwen_vl_utils import process_vision_info |
|
|
|
|
|
model_id = "AvitoTech/a-vision" |
|
|
|
|
|
# Модель и процессор |
|
|
model = AutoModelForImageTextToText.from_pretrained( |
|
|
model_id, |
|
|
torch_dtype="auto", |
|
|
device_map="auto", |
|
|
) |
|
|
processor = AutoProcessor.from_pretrained(model_id) |
|
|
|
|
|
img = Image.open("assets/hoodie.jpg") # выберите локально загруженное изображение |
|
|
|
|
|
messages = [ |
|
|
{ |
|
|
"role": "user", |
|
|
"content": [ |
|
|
{ |
|
|
"type": "image", |
|
|
"image": img, |
|
|
"min_pixels": 4 * 28 * 28, |
|
|
"max_pixels": 1024 * 28 * 28, |
|
|
}, |
|
|
{ |
|
|
"type": "text", |
|
|
"text": "Опиши изображение." |
|
|
} |
|
|
], |
|
|
} |
|
|
] |
|
|
|
|
|
# Подготовка входа |
|
|
chat_text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) |
|
|
image_inputs, video_inputs = process_vision_info(messages) |
|
|
inputs = processor( |
|
|
text=[chat_text], |
|
|
images=image_inputs, |
|
|
videos=video_inputs, |
|
|
padding=True, |
|
|
return_tensors="pt", |
|
|
) |
|
|
|
|
|
inputs = inputs.to("cuda") |
|
|
|
|
|
# Генерация |
|
|
generated_ids = model.generate(**inputs, max_new_tokens=256) |
|
|
generated_ids_trimmed = [ |
|
|
out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids) |
|
|
] |
|
|
response = processor.batch_decode(generated_ids, skip_special_tokens=True)[0] |
|
|
print(response) |
|
|
``` |
|
|
|
|
|
> * Для лучшей производительности имеет смысл подбирать `min_pixels/max_pixels`. |
|
|
|
|
|
--- |