🚀 GME-VARCO-VISION-Embedding
GME-VARCO-VISION-Embedding
は、高次元の埋め込み空間でテキスト、画像、動画間の意味的類似性を計算するマルチモーダル埋め込みモデルです。特に、画像検索よりも複雑性と文脈理解が求められる動画検索に特化しています。シーンベースの検索、説明ベースの検索、質問応答ベースの検索など、様々なシナリオで高い検索精度と強い汎化性能を実現します。
📺 デモビデオ
当社のマルチモーダル埋め込みモデルの動作を紹介するデモビデオをご覧ください。
このデモでは、埋め込みモデルがAIエージェントと連携して、ユーザーのクエリに基づいて関連する動画を検索し、検索された動画コンテンツを使用して応答を生成する様子を示しています。
🧠 モデルアーキテクチャと学習方法
GME-VARCO-VISION-Embedding
は、Qwen/Qwen2-VL-7B-Instruct
をベースに構築されており、Alibaba-NLP/gme-Qwen2-VL-7B-Instruct
のパラメータを使用して、モデルの一般的な検索能力を向上させています。
1. 動画嗜好データセットでの微調整(対照学習)
モデルを効率的に微調整するために、ShareGPTVideoの17k動画嗜好データセット を利用しています。このデータセットには、プロンプト、動画、正解、選択拒否テキストペアが含まれています。プロンプトと動画をクエリとして扱い、拒否された応答を正解に対するハードネガティブとして使用します。各クエリは、バッチ内のネガティブと1つのハードネガティブを使用して、InfoNCE損失で学習されます。モデルは、8台のA100 GPUでバッチサイズ8で2エポック完全に微調整され、学習にはわずか数時間しかかかりません。
2. 検索ベクトルの追加
学習インスタンスの不足を補い、微調整されたモデルの汎化能力を強化するために、Qwen/Qwen2-VL-7B-Instruct
の元のモデルの重みから、Qwen2-VLベースの画像テキスト検索モデルである Alibaba-NLP/gme-Qwen2-VL-7B-Instruct
の重みを減算することで、検索ベクトル 𝜏 を計算します。このアプローチは、ベースモデルとチャット最適化モデルの重みの差から得られるベクトルを追加することで、事前学習された言語モデルに新しい言語でのチャット機能を備えさせる方法であるChat Vectorにインスパイアされています。
📈 性能
当社のモデルは、2025年7月現在、MultiVENT2.0データセットで 最先端(SOTA)のゼロショット性能 を達成しています。詳細な結果は、公式リーダーボード を参照してください。
💻 使用例
基本的な使用法
import torch
import requests
from PIL import Image
from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info
model_name = "NCSOFT/GME-VARCO-VISION-Embedding"
model = Qwen2VLForConditionalGeneration.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
attn_implementation="flash_attention_2",
device_map="auto",
)
processor = AutoProcessor.from_pretrained(model_name)
tokenizer = processor.tokenizer
device = model.device
qry_msg = [
{
"role": "user",
"content": [
{"type": "text", "text": "Find a photo of a cat."},
],
},
]
qry_txt = processor.apply_chat_template(
qry_msg, tokenize=False, add_generation_prompt=True
) + tokenizer.eos_token
qry_input = processor(
text=[qry_txt],
padding=True,
return_tensors="pt",
).to(device)
img_msg = [
{
"role": "user",
"content": [{
"type": "image",
"image": "image"
}]
}
]
img_txt = processor.apply_chat_template(
img_msg, tokenize=False, add_generation_prompt=True
) + tokenizer.eos_token
candidate_imgs= [
{
"role": "user",
"content": [{
"type": "image",
"image": "http://images.cocodataset.org/val2017/000000039769.jpg"}]
},
{
"role": "user",
"content": [{
"type": "image",
"image": "https://farm1.staticflickr.com/116/290755713_a5de6c1079_z.jpg"}]
},
{
"role": "user",
"content": [{
"type": "image",
"image": "http://farm3.staticflickr.com/2418/2193688811_d9f5e23bbd_z.jpg"}]
},
{
"role": "user",
"content": [{
"type": "image",
"image":"http://farm7.staticflickr.com/6049/6329686751_997c68fff9_z.jpg"}]
},
]
candidate_images, _ = process_vision_info(candidate_imgs)
image_inputs = processor(
text=[img_txt] * len(candidate_images),
images=candidate_images,
padding=True,
return_tensors="pt",
).to(device)
with torch.inference_mode():
qry_emb = model(
**qry_input, output_hidden_states=True, return_dict=True
).hidden_states[-1][:, -1, :]
img_emb = model(
**image_inputs, output_hidden_states=True, return_dict=True
).hidden_states[-1][:, -1, :]
qry_emb = F.normalize(qry_emb, dim=-1)
img_emb = F.normalize(img_emb, dim=-1)
score = qry_emb @ img_emb.t()
高度な使用法
vid_message = [
{
"role": "user",
"content": [{
"type": "video",
"video": video_path,
"max_pixels": 262144,
"fps": 2.0,}]
}
]
video_text = processor.apply_chat_template(
vid_message, tokenize=False, add_generation_prompt=True
) + tokenizer.eos_token
image_input, video_input = process_vision_info(vid_message)
video_input = processor(
text=[video_text],
images=image_input,
videos=video_input,
padding=True,
return_tensors="pt",
).to(device)
with torch.inference_mode():
video_emb = model(
**video_input, output_hidden_states=True, return_dict=True
).hidden_states[-1][:, -1, :]
video_emb = F.normalize(video_emb, dim=-1)
📄 ライセンス
このプロジェクトは、CC BY-NC 4.0ライセンスの下で公開されています。