Après un an d'efforts acharnés, nous sommes aujourd'hui ravis de sortir Qwen2-VL ! Qwen2-VL est la dernière version des modèles de langage de vision des familles de modèles Qwen.
Compréhension SoTA d'images de différentes résolutions et ratios : Qwen2-VL atteint des performances de pointe sur les tests de compréhension visuelle, notamment MathVista, DocVQA, RealWorldQA, MTVQA, etc.
Comprendre les vidéos de plus de 20 minutes : grâce aux capacités de streaming en ligne, Qwen2-VL peut comprendre les vidéos de plus de 20 minutes grâce à des réponses aux questions vidéo de haute qualité, des dialogues, la création de contenu, etc.
Agent capable de faire fonctionner vos mobiles, robots, etc. : doté de capacités de raisonnement et de prise de décision complexes, Qwen2-VL peut être intégré à des appareils tels que des téléphones mobiles, des robots, etc., pour un fonctionnement automatique basé sur un environnement visuel et des instructions textuelles.
Support multilingue : pour servir les utilisateurs du monde entier, outre l'anglais et le chinois, Qwen2-VL prend désormais en charge la compréhension des textes dans différentes langues à l'intérieur des images, y compris la plupart des langues européennes, le japonais, le coréen, l'arabe, le vietnamien, etc.
Résolution dynamique naïve : contrairement à avant, Qwen2-VL peut gérer des résolutions d'image arbitraires, en les mappant en un nombre dynamique de jetons visuels, offrant une expérience de traitement visuel plus humaine.
Incorporation de position rotative multimodale (M-ROPE) : décompose l'intégration de position en parties pour capturer des informations de position textuelles 1D, visuelles 2D et vidéo 3D, améliorant ainsi ses capacités de traitement multimodal.
Nous disposons de modèles Qwen2-VL open source, notamment Qwen2-VL-2B et Qwen2-VL-7B sous licence Apache 2.0, ainsi que Qwen2-VL-72B sous licence Qwen. Ces modèles sont désormais intégrés à Hugging Face Transformers, vLLM et d'autres frameworks tiers. Nous espérons que vous apprécierez leur utilisation !
2024.09.19 : Le modèle Qwen2-VL-72B optimisé pour les instructions et sa version quantifiée [AWQ, GPTQ-Int4, GPTQ-Int8] sont désormais disponibles. Nous avons également publié simultanément l'article Qwen2-VL.
30/08/2024 : Nous avons lancé la série Qwen2-VL. Les modèles 2B et 7B sont désormais disponibles, et le modèle 72B pour l'open source arrive bientôt. Pour plus de détails, veuillez consulter notre blog !
Référence | SoTA précédent (LVLM open source) | Claude-3.5 Sonnet | GPT-4o | Qwen2-VL-72B (? ? | Qwen2-VL-7B (? ?) | Qwen2-VL-2B (??) |
---|---|---|---|---|---|---|
Valeur MMMU | 58.3 | 68,3 | 69.1 | 64,5 | 54.1 | 41.1 |
MMMU-Pro | 46,9 | 51,5 | 51,9 | 46.2 | 43,5 | 37,6 |
Test DocVQA | 94.1 | 95.2 | 92,8 | 96,5 | 94,5 | 90,1 |
Test InfoVQA | 82,0 | - | - | 84,5 | 76,5 | 65,5 |
Test ChartQA | 88,4 | 90,8 | 85,7 | 88,3 | 83,0 | 73,5 |
TexteVQA val | 84,4 | - | - | 85,5 | 84,3 | 79,7 |
Banc OCR | 852 | 788 | 736 | 877 | 845 | 794 |
MTVQA | 17.3 | 25,7 | 27,8 | 30,9 | 25.6 | 18.1 |
Magnétoscope et facile | 84,67 | 63,85 | 91.55 | 91,93 | 89.70 | 81.45 |
Magnétoscope zh facile | 22.09 | 1.0 | 14.87 | 65.37 | 59,94 | 46.16 |
Monde réelQA | 72.2 | 60,1 | 75,4 | 77,8 | 70.1 | 62,9 |
somme MME | 2414.7 | 1920.0 | 2328.7 | 2482.7 | 2326.8 | 1872.0 |
Test MMBench-FR | 86,5 | 79,7 | 83,4 | 86,5 | 83,0 | 74,9 |
Test MMBench-CN | 86,3 | 80,7 | 82.1 | 86,6 | 80,5 | 73,5 |
Test MMBench-V1.1 | 85,5 | 78,5 | 82,2 | 85,9 | 80,7 | 72.2 |
Test MMT-Banc | 63,4 | - | 65,5 | 71,7 | 63,7 | 54,5 |
MMStar | 67.1 | 62.2 | 63,9 | 68,3 | 60,7 | 48,0 |
MMVet GPT-4-Turbo | 65,7 | 66,0 | 69.1 | 74,0 | 62,0 | 49,5 |
Moy. HallBench | 55.2 | 49,9 | 55,0 | 58.1 | 50,6 | 41,7 |
Test MathVista mini | 67,5 | 67,7 | 63,8 | 70,5 | 58.2 | 43,0 |
MathVision | 16.97 | - | 30.4 | 25.9 | 16.3 | 12.4 |
Référence | SoTA précédent (LVLM open source) | Gémeaux 1.5-Pro | GPT-4o | Qwen2-VL-72B (? ?) | Qwen2-VL-7B (? ?) | Qwen2-VL-2B (??) |
---|---|---|---|---|---|---|
MVBench | 69,6 | - | - | 73,6 | 67,0 | 63.2 |
Test de perception | 66,9 | - | - | 68,0 | 62,3 | 53,9 |
Test EgoSchema | 62,0 | 63.2 | 72.2 | 77,9 | 66,7 | 54,9 |
Vidéo-MME (avec/avec sous-marins) | 66,3/69,6 | 75,0 / 81,3 | 71,9/77,2 | 71,2/77,8 | 63,3/69,0 | 55,6/60,4 |
Référence | Métrique | SoTA précédent | GPT-4o | Qwen2-VL-72B | |
---|---|---|---|---|---|
Général | Appel Fn [1] | MT | - | 90,2 | 93.1 |
EM | - | 50,0 | 53.2 | ||
Jeu | Droite numérique | RS | 89.4 [2] | 91,5 | 100,0 |
BlackJack | RS | 40.2 [2] | 34,5 | 42,6 | |
EZPoint | RS | 50,0 [2] | 85,5 | 100,0 | |
Point24 | RS | 2.6 [2] | 3.0 | 4.5 | |
Androïde | AITZ | MT | 83,0 [3] | 70,0 | 89,6 |
EM | 47,7 [3] | 35.3 | 72.1 | ||
AI2THOR | ALFRED valide-invisible | RS | 67,7 [4] | - | 67,8 |
CG | 75.3 [4] | - | 75,8 | ||
VLN | R2R valide-invisible | RS | 79,0 | 43,7 [5] | 51,7 |
REVERIE valide-invisible | RS | 61,0 | 31,6 [5] | 31,0 |
SR, GC, TM et EM sont les abréviations de taux de réussite, réussite des conditions d'objectif, correspondance de type et correspondance exacte. ALFRED est pris en charge par SAM [6] .
Benchmark d'appel de fonction auto-organisé par l'équipe Qwen
Affiner les grands modèles de vision et de langage en tant qu'agents décisionnels via l'apprentissage par renforcement
Android dans le zoo : chaîne de réflexion pour les agents GUI
ThinkBot : suivi d'instructions incorporées avec raisonnement en chaîne de pensées
MapGPT : invite guidée par carte avec planification de chemin adaptative pour la navigation par vision et langage
Segmentez n'importe quoi.
Modèles | RA | DE | FR | IL | JA | KO | RU | ÈME | VI | MOYENNE |
---|---|---|---|---|---|---|---|---|---|---|
Qwen2-VL-72B | 20,7 | 36,5 | 44.1 | 42,8 | 21.6 | 37.4 | 15.6 | 17.7 | 41,6 | 30,9 |
GPT-4o | 20.2 | 34.2 | 41.2 | 32,7 | 20,0 | 33,9 | 11.5 | 22,5 | 34.2 | 27,8 |
Claude3 Opus | 15.1 | 33.4 | 40,6 | 34.4 | 19.4 | 27.2 | 13,0 | 19,5 | 29.1 | 25,7 |
Gémeaux Ultra | 14.7 | 32.3 | 40,0 | 31,8 | 12.3 | 17.2 | 11.8 | 20.3 | 28,6 | 23.2 |
Ces résultats sont évalués sur le benchmark MTVQA.
Ci-dessous, nous fournissons des exemples simples pour montrer comment utiliser Qwen2-VL avec ? ModelScope et ? Transformateurs.
Le code de Qwen2-VL a été présent dans les derniers transformateurs Hugging Face et nous vous conseillons de compiler à partir des sources avec la commande :
pip install git+https://github.com/huggingface/transformers@21fac7abba2a37fae86106f87fcf9974fd1e3830 accelerate
ou vous pourriez rencontrer l'erreur suivante :
KeyError: 'qwen2_vl'
REMARQUE : la dernière version actuelle des transformers
présente un bug lors du chargement de la configuration Qwen2-VL, vous devez donc installer une version spécifique des transformateurs comme ci-dessus.
Nous proposons une boîte à outils pour vous aider à gérer plus facilement différents types d’entrées visuelles, comme si vous utilisiez une API. Cela inclut le base64, les URL et les images et vidéos entrelacées. Vous pouvez l'installer à l'aide de la commande suivante :
# Il est fortement recommandé d'utiliser la fonctionnalité `[decord]` pour un chargement vidéo plus rapide.pip install qwen-vl-utils[decord]
Si vous n'utilisez pas Linux, vous ne pourrez peut-être pas installer decord
depuis PyPI. Dans ce cas, vous pouvez utiliser pip install qwen-vl-utils
qui reviendra à utiliser torchvision pour le traitement vidéo. Cependant, vous pouvez toujours installer le décor à partir de la source pour que le décor soit utilisé lors du chargement de la vidéo.
Nous montrons ici un extrait de code pour vous montrer comment utiliser le modèle de chat avec transformers
et qwen_vl_utils
:
à partir des transformateurs import Qwen2VLForConditionalGeneration, AutoTokenizer, AutoProcessorfrom qwen_vl_utils import process_vision_info# default : Charger le modèle sur le(s) périphérique(s) disponible(s)model = Qwen2VLForConditionalGeneration.from_pretrained("Qwen/Qwen2-VL-7B-Instruct", torch_dtype="auto", device_map= "auto")# Nous vous recommandons d'activer flash_attention_2 pour une meilleure accélération et une meilleure économie de mémoire, en particulier dans les scénarios multi-images et vidéo.# model = Qwen2VLForConditionalGeneration.from_pretrained(# "Qwen/Qwen2-VL-7B-Instruct",# torch_dtype=torch. bfloat16,# attn_implementation="flash_attention_2",# device_map="auto",# )# default processerprocessor = AutoProcessor.from_pretrained("Qwen/Qwen2-VL-7B-Instruct")# La plage par défaut pour le nombre de jetons visuels par image dans le modèle est 4-16384.# Vous pouvez définir min_pixels et max_pixels en fonction de vos besoins, comme une plage de jetons de 256 à 1280, pour équilibrer les performances et le coût.# min_pixels = 256*28*28# max_pixels = 1280*28 *28# processeur = AutoProcessor.from_pretrained("Qwen/Qwen2-VL-7B-Instruct", min_pixels=min_pixels, max_pixels=max_pixels)messages = [ {"role": "utilisateur", "contenu": [ {"type": "image","image": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg", }, {"type": "text", "text": "Décrivez cette image."}, ], } ]# Préparation pour l'inférencetext = processeur.apply_chat_template(messages, tokenize=False, add_Generation_prompt=True)image_inputs, video_inputs = process_vision_info(messages)inputs = processeur(text=[text],images=image_inputs,videos=video_inputs,padding=True, return_tensors="pt", )inputs = inputs.to("cuda")# Inférence : Génération de la sortiegenerated_ids = model.generate(**inputs, max_new_tokens=128)generated_ids_trimmed = [out_ids[len(in_ids) :] pour in_ids, out_ids dans zip(inputs .input_ids, généré_ids) ]output_text = processeur.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)print(output_text)
# Messages contenant plusieurs images et un texte de requêtemessages = [ {"role": "utilisateur", "contenu": [ {"type": "image", "image": "file:///path/to/image1.jpg"}, {"type": "image", "image": "file:///path/to/image2.jpg"}, {"type": "text", "text": "Identifiez les similitudes entre ces images."}, ], } ]# Préparation pour l'inférencetext = processeur.apply_chat_template(messages, tokenize=False, add_Generation_prompt=True)image_inputs, video_inputs = process_vision_info(messages)inputs = processeur(text=[text],images=image_inputs,videos=video_inputs,padding=True, return_tensors="pt", )inputs = inputs.to("cuda")# Inferencegenerated_ids = model.generate(**inputs, max_new_tokens=128)generated_ids_trimmed = [out_ids[len(in_ids) :] pour in_ids, out_ids dans zip(inputs.input_ids, generate_ids) ]output_text = processeur.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)print(output_text)
# Messages contenant une liste d'images sous forme de vidéo et de texte querymessages = [ {"role": "utilisateur", "contenu": [ {"type": "video","video": ["file:///path/to/frame1.jpg","file:///path/to/frame2.jpg","file:/// chemin/vers/frame3.jpg","fichier:///chemin/vers/frame4.jpg", ], }, {"type": "text", "text": "Décrivez cette vidéo."}, ], } ]# Messages contenant un chemin vidéo local et une requête textuellemessages = [ {"role": "utilisateur", "contenu": [ {"type": "video","video": "file:///path/to/video1.mp4","max_pixels": 360 * 420,"fps": 1.0, }, {"type": "text", "text": "Décrivez cette vidéo."}, ], } ]# Messages contenant une URL vidéo et un message de requête texte = [ {"role": "utilisateur", "contenu": [ {"type": "video","video": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen2-VL/space_woaudio.mp4", }, {"type": "text", "text": "Décrivez cette vidéo."}, ], } ]# Préparation pour l'inférencetext = processeur.apply_chat_template(messages, tokenize=False, add_Generation_prompt=True)image_inputs, video_inputs = process_vision_info(messages)inputs = processeur(text=[text],images=image_inputs,videos=video_inputs,padding=True, return_tensors="pt", )inputs = inputs.to("cuda")# Inferencegenerated_ids = model.generate(**inputs, max_new_tokens=128)generated_ids_trimmed = [out_ids[len(in_ids) :] pour in_ids, out_ids dans zip(inputs.input_ids, generate_ids) ]output_text = processeur.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)print(output_text)
La compatibilité des URL vidéo dépend en grande partie de la version de la bibliothèque tierce. Les détails sont dans le tableau ci-dessous. changez le backend par FORCE_QWENVL_VIDEO_READER=torchvision
ou FORCE_QWENVL_VIDEO_READER=decord
si vous préférez ne pas utiliser celui par défaut.
Back-end | HTTP | HTTPS |
---|---|---|
vision de la torche >= 0.19.0 | ✅ | ✅ |
vision de la torche < 0.19.0 | ❌ | ❌ |
décor | ✅ | ❌ |
# Exemples de messages pour les messages d'inférence par lots1 = [ {"role": "utilisateur", "contenu": [ {"type": "image", "image": "file:///path/to/image1.jpg"}, {"type": "image", "image": "file:///path/to/image2.jpg"}, {"type": "text", "text": "Quels sont les éléments communs dans ces images ?"}, ], } ]messages2 = [ {"role": "system", "content": "Vous êtes un assistant utile."}, {"role": "user", "content": "Qui êtes-vous ?"}, ]# Combiner les messages pour le traitement par lotsmessages = [messages1, messages2]# Préparation pour l'inférence par lotstexts = [processor.apply_chat_template(msg, tokenize=False, add_Generation_prompt=True)pour msg dans les messages]image_inputs, video_inputs = process_vision_info(messages)inputs = processeur (text=textes,images=image_inputs,videos=video_inputs,padding=True,return_tensors="pt", )inputs = inputs.to("cuda")# Batch Inferencegenerated_ids = model.generate(**inputs, max_new_tokens=128)generated_ids_trimmed = [out_ids[len(in_ids) :] pour in_ids, out_ids dans zip(inputs.input_ids, generate_ids ) ]output_texts = processeur.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)print(output_texts)
Nous conseillons fortement aux utilisateurs, en particulier ceux de Chine continentale, d'utiliser ModelScope. snapshot_download
peut vous aider à résoudre les problèmes liés au téléchargement des points de contrôle.
Pour les images d'entrée, nous prenons en charge les fichiers locaux, base64 et les URL. Pour les vidéos, nous ne prenons actuellement en charge que les fichiers locaux.
# Vous pouvez directement insérer un chemin de fichier local, une URL ou une image encodée en base64 à l'endroit souhaité dans le texte.## Chemin de fichier localmessages = [ {"role": "utilisateur", "contenu": [ {"type": "image", "image": "file:///path/to/your/image.jpg"}, {"type": "text", "text": "Décrivez cette image."}, ], } ]## Messages URL de l'image = [ {"role": "utilisateur", "contenu": [ {"type": "image", "image": "http://chemin/vers/votre/image.jpg"}, {"type": "text", "text": "Décrivez cette image."}, ], } ]## Messages d'image codés en Base64 = [ {"role": "utilisateur", "contenu": [ {"type": "image", "image": "data:image;base64,/9j/..."}, {"type": "text", "text": "Décrivez cette image."}, ], } ]
Le modèle prend en charge une large gamme d’entrées de résolution. Par défaut, il utilise la résolution native pour l'entrée, mais des résolutions plus élevées peuvent améliorer les performances au prix de davantage de calculs. Les utilisateurs peuvent définir le nombre minimum et maximum de pixels pour obtenir une configuration optimale adaptée à leurs besoins, comme une plage de nombre de jetons de 256 à 1 280, afin d'équilibrer la vitesse et l'utilisation de la mémoire.
min_pixels = 256 * 28 * 28max_pixels = 1280 * 28 * 28processor = AutoProcessor.from_pretrained("Qwen/Qwen2-VL-7B-Instruct", min_pixels=min_pixels, max_pixels=max_pixels)
En outre, nous proposons deux méthodes pour un contrôle précis de la taille de l'image entrée dans le modèle :
Spécifiez les dimensions exactes : définissez directement resized_height
et resized_width
. Ces valeurs seront arrondies au multiple de 28 le plus proche.
Définissez min_pixels et max_pixels : les images seront redimensionnées pour conserver leur rapport hauteur/largeur dans la plage min_pixels et max_pixels.
# resized_height et resized_widthmessages = [ {"role": "utilisateur", "contenu": [ {"type": "image","image": "fichier:///chemin/vers/votre/image.jpg","resized_height": 280,"resized_width": 420, }, {"type": "text", "text": "Décrivez cette image."}, ], } ]# min_pixels et max_pixelsmessages = [ {"role": "utilisateur", "contenu": [ {"type": "image","image": "file:///path/to/your/image.jpg","min_pixels": 50176,"max_pixels": 50176, }, {"type": "text", "text": "Décrivez cette image."}, ], } ]
Par défaut, les images et le contenu vidéo sont directement inclus dans la conversation. Lorsque vous manipulez plusieurs images, il est utile d'ajouter des étiquettes aux images et aux vidéos pour une meilleure référence. Les utilisateurs peuvent contrôler ce comportement avec les paramètres suivants :
conversation = [ {"role": "user","content": [{"type": "image"}, {"type": "text", "text": "Bonjour, comment vas-tu ?"}], }, {"role": "assistant","content": "Je vais bien, merci de votre demande. Comment puis-je vous aider aujourd'hui ?", }, {"role": "utilisateur", "contenu": [ {"type": "text", "text": "Pouvez-vous décrire ces images et cette vidéo ?"}, {"type": "image"}, {"type": "image"}, {"type": "vidéo"}, {"type": "text", "text": "Ceci viennent de mes vacances."}, ], }, {"role": "assistant","content": "Je serais heureux de décrire les images et la vidéo pour vous. Pourriez-vous s'il vous plaît fournir plus de contexte sur vos vacances ?", }, {"role": "user","content": "C'était un voyage à la montagne. Pouvez-vous voir les détails dans les images et la vidéo ?", }, ]# default :prompt_without_id = processeur.apply_chat_template(conversation, add_generation_prompt=True)# Sortie exceptée : '<|im_start|>systemnVous êtes un assistant utile.<|im_end|>n<|im_start|>usern<|vision_start|>< |image_pad|><|vision_end|>Bonjour, comment vas-tu ?<|im_end|>n<|im_start|>assistantnJe vais bien, merci d'avoir demandé. Comment puis-je vous aider aujourd'hui ?<|im_end|>n<|im_start|>usernPouvez-vous décrire ces images et vidéos ?<|vision_start|><|image_pad|><|vision_end|><|vision_start|><|image_pad| ><|vision_end|><|vision_start|><|video_pad|><|vision_end|>Celles-ci proviennent de mes vacances.<|im_end|>n<|im_start|>assistantnJe serais heureux de décrire les images et la vidéo pour toi. Pourriez-vous s'il vous plaît fournir plus de contexte sur vos vacances ?<|im_end|>n<|im_start|>usernC'était un voyage à la montagne. Pouvez-vous voir les détails dans les images et la vidéo ?<|im_end|>n<|im_start|>assistantn'# add idsprompt_with_id = processeur.apply_chat_template(conversation, add_Generation_prompt=True, add_vision_id=True)# Sortie exceptée : '<|im_start |>systemnVous êtes un assistant utile.<|im_end|>n<|im_start|>usernImage 1 : <|vision_start|><|image_pad|><|vision_end|>Bonjour, comment allez-vous ?<|im_end|>n< |im_start|>assistantnJe vais bien, merci d'avoir demandé. Comment puis-je vous aider aujourd'hui ?<|im_end|>n<|im_start|>usernPouvez-vous décrire ces images et vidéos ?Image 2 : <|vision_start|><|image_pad|><|vision_end|>Image 3 : <|vision_start |><|image_pad|><|vision_end|>Vidéo 1 : <|vision_start|><|video_pad|><|vision_end|>Celles-ci datent de mes vacances.<|im_end|>n<|im_start|>assistantnI'd soyez heureux de décrire les images et la vidéo pour vous. Pourriez-vous s'il vous plaît fournir plus de contexte sur vos vacances ?<|im_end|>n<|im_start|>usernC'était un voyage à la montagne. Pouvez-vous voir les détails dans les images et la vidéo ?<|im_end|>n<|im_start|>assistantn'
Tout d’abord, assurez-vous d’installer la dernière version de Flash Attention 2 :
pip install -U flash-attn --no-build-isolation
De plus, vous devez disposer d'un matériel compatible avec Flash-Attention 2. Pour en savoir plus, consultez la documentation officielle du référentiel Flash Attention. FlashAttention-2 ne peut être utilisé que lorsqu'un modèle est chargé dans torch.float16
ou torch.bfloat16
.
Pour charger et exécuter un modèle à l'aide de Flash Attention-2, ajoutez simplement attn_implementation="flash_attention_2"
lors du chargement du modèle comme suit :
à partir des transformateurs import Qwen2VLForConditionalGenerationmodel =