Direct API を使用して VLM を実行する
| 項目 | 値 |
|---|---|
| カテゴリ | GenAI |
| 難易度 | 中級 |
| 推定所要時間 | 10-15 minutes |
| ラベル | genai, vlm, image, cache, multimodal |
ビジョン-言語モデルは、テキストと画像テンソルを受け入れることができます。1つの質問に対して、画像を GenerationRequest.images に直接添付します。繰り返し質問する場合は、画像を1回エンコードし、後続のリクエストでキャッシュされた画像埋め込みを再利用します。
ウォークスルー
VLM と画像をロードする
デプロイされた LLiMa モデルディレクトリから VisionLanguageModel をロードし、ディスクから画像をデコードします。
OpenCV を使用して画像を読み込みます。Neat は、3チャンネルの cv::Mat 入力を BGR として扱い、内部的に RGB に変換します。
genai::VisionLanguageModel model(args.model);
cv::Mat image = cv::imread(args.image.string(), cv::IMREAD_COLOR);
if (image.empty()) {
throw std::runtime_error("failed to read image: " + args.image.string());
}
直接画像を添付して質問する
最初のリクエストに画像を直接添付します。これは最も簡単な方法であり、多くの場合、一度限りの視覚的な質問には十分です。
genai::GenerationRequest direct;
direct.prompt = "Describe this image in one sentence.";
direct.images = {image};
direct.max_new_tokens = 96;
const genai::GenerationResult first = model.run(direct);
std::cout << "direct image: " << first.text << "\n\n";
画像埋め込みをキャッシュする
encode(...) を呼び出して、モデルに画像埋め込みをキャッシュします。この呼び出しは、画像が受け入れられ、キャッシュされた場合に true を返します。
if (!model.encode(image)) {
throw std::runtime_error("VLM did not accept the image for caching");
}
std::cout << "cached_images=" << model.cached_image_count() << "\n";
後続の質問をする
キャッシュされた画像を使用する必要がある各リクエストで、use_cached_images = true を設定します。同じキャッシュされた画像について、複数の質問をすることができます。このフラグがないリクエストは通常どおりに動作します。テキストのみのリクエストでは画像は使用されず、直接画像リクエストでは独自の images が使用され、別の encode(...) 呼び出しによってキャッシュされた画像が置き換えられます。
genai::GenerationRequest cached;
cached.prompt = "What details should I inspect more closely?";
cached.use_cached_images = true;
cached.max_new_tokens = 96;
const genai::GenerationResult follow_up = model.run(cached);
std::cout << "cached image: " << follow_up.text << "\n\n";
genai::GenerationRequest second_cached;
second_cached.prompt = "Summarize the image in three keywords.";
second_cached.use_cached_images = true;
second_cached.max_new_tokens = 48;
const genai::GenerationResult second_follow_up = model.run(second_cached);
std::cout << "cached image keywords: " << second_follow_up.text << "\n\n";
チャットメッセージに画像を添付する
messages を使用する場合は、必要なユーザーメッセージに画像を添付します。これにより、画像が関連する正確なテキストの隣に配置されます。
genai::ChatMessage image_message;
image_message.role = "user";
image_message.content = "What is the main subject of this image?";
image_message.images = {image};
genai::GenerationRequest message_request;
message_request.messages = {image_message};
message_request.max_new_tokens = 96;
const genai::GenerationResult message_result = model.run(message_request);
std::cout << "message image: " << message_result.text << "\n";
実行
Modalix DevKit で、Hugging Face から LLiMa CLI を使用して LFM2-VL 1.6B VLM をダウンロードします。
llima pull LFM2-VL-1.6B-a16w4
Modalix で、DevKit ローカルモデルディレクトリとローカル画像を使用して、チュートリアルを実行します。
C++ (prebuilt):
./lib/sima-neat/tutorials/tutorial_020_run_a_vlm \
--model /media/nvme/llima/models/LFM2-VL-1.6B-a16w4 \
--image tests/images/people.jpg
C++ (build from source):
./build.sh --target tutorial_020_run_a_vlm
./build/tutorials-standalone/tutorial_020_run_a_vlm \
--model /media/nvme/llima/models/LFM2-VL-1.6B-a16w4 \
--image tests/images/people.jpg
期待される出力は、直接的な画像リクエストに対する1つの回答、キャッシュされた画像を再利用する複数のフォローアップ回答、およびメッセージレベルの画像リクエストに対する1つの回答です。
実践
ユーザーが同じフレーム、製品画像、図、またはドキュメントページについて複数の質問をする場合、画像キャッシュを使用します。各リクエストで異なる画像を使用する場合は、キャッシュを避けてください。なぜなら、直接的な画像パスの方がシンプルで、プロンプトの状態を明確に保つことができるからです。
一部のモデルファミリーでは、キャッシュされた画像の再利用がサポートされていない場合があります。その場合は、各リクエストで直接的な画像を使用してください。
会話を構築し、1つのメッセージにのみ画像を含める必要がある場合は、ChatMessage.imagesを使用します。よりシンプルな単一プロンプト形式の場合は、最上位レベルのGenerationRequest.imagesを使用します。