メインコンテンツへスキップ
友田 陽大
Llama・オープンウェイトLLM
Llama
マルチモーダル
生成AI
AWS Bedrock
OCR
TypeScript
Python

Llama 4 マルチモーダル実践:画像理解を本番の『型安全な構造化抽出』に使う

Llama 4 はネイティブマルチモーダル。帳票・レシート・名刺・図面・スクショといった画像を、推測させずに構造化データへ落とす本番パイプラインを、AWS Bedrock Converse の画像入力・Zodによる境界検証・信頼度ゲート・人手レビュー・PII保護まで実コードで解説します。

公開日
読了時間
9分
著者
友田 陽大
シェア

この記事のゴール

Llama 4 はネイティブマルチモーダル——テキストと画像を後付けではなく最初から同じモデルで扱います(early fusion)。これが効くのは、**「画像を見て、構造化データを返す」**タスクです。帳票・レシート・名刺・図面・スクリーンショット・本人確認書類……現場には“紙とスクショ”が溢れています。

本稿は、その画像理解をデモではなく本番——推測させない・型で縛る・誤れない値を守る・PIIを漏らさない——に仕上げます。

信頼性の開示:「生成に数値を推測させず、誤れない値はマスタ照合に分業させる」という設計は、私が音声接客の事例で型番・サイズの誤答を構造的に潰したときの中核思想です。本稿の画像抽出も同じ規律——LLMは読み取りの言葉、真実は検証——で組みます。


どんな場面で効くか

入力画像抽出したい構造価値
請求書・領収書取引先・金額・日付・明細経理の手入力ゼロ化
名刺氏名・会社・役職・連絡先CRM 自動登録
図面・仕様書型番・寸法・材質見積もり・発注の前処理
スクリーンショットエラー文・UI状態サポート/QAの自動分類
本人確認書類氏名・生年月日・番号KYC(※PII保護が前提)

共通するのは「非構造な画像 → 後段システムが使える構造化データ」。ここを LLM のマルチモーダルで埋めると、人手の転記が消えます。


投入する:Bedrock Converse の画像入力

Bedrock の Converse API は、メッセージに画像ブロックを混ぜられます。形式は formatpng / jpeg / gif / webp)+ source.bytesAWS SDK が base64 化を肩代わりするので、生バイトを渡すだけです。

# llama_vision.py — 画像+指示を Llama 4 に渡し、テキストで理解させる
import boto3
from botocore.config import Config

_bedrock = boto3.client(
    "bedrock-runtime", region_name="us-east-1",
    config=Config(retries={"max_attempts": 4, "mode": "adaptive"}, read_timeout=60),
)
MODEL_ID = "us.meta.llama4-maverick-17b-instruct-v1:0"  # 画像理解は上位のMaverickが堅い

def read_image(path: str) -> dict:
    with open(path, "rb") as f:
        data = f.read()  # SDKがbase64を処理するので生バイトでよい
    ext = path.rsplit(".", 1)[-1].lower()
    fmt = "jpeg" if ext == "jpg" else ext  # jpg→jpeg に正規化
    return {"image": {"format": fmt, "source": {"bytes": data}}}

def describe(image_path: str, instruction: str) -> str:
    resp = _bedrock.converse(
        modelId=MODEL_ID,
        messages=[{"role": "user", "content": [read_image(image_path), {"text": instruction}]}],
        inferenceConfig={"maxTokens": 1024, "temperature": 0.0},  # 抽出は温度0で揺らさない
    )
    return resp["output"]["message"]["content"][0]["text"]

📌 制約(公式):1メッセージあたり画像は最大20枚、各画像は3.75MB・8000px 以下。多ページ帳票はページ単位に分割して投入します。温度は抽出では 0.0 が基本——創造性は不要、毎回同じに読むことが品質です。


型で縛る:画像から構造化データへ(推測させない)

画像理解の出力も信頼境界の外側です。自由文ではなくスキーマ準拠のJSONを要求し、Zodで境界検証して初めて後段に流します。Vercel AI SDK なら画像パートと generateObject を組み合わせられます。

// lib/extract-receipt.ts — レシート画像 → 型安全な構造化データ
import { bedrock } from "@ai-sdk/amazon-bedrock";
import { generateObject } from "ai";
import { z } from "zod";

const Receipt = z.object({
  merchant: z.string().min(1),
  total: z.number().nonnegative(),
  currency: z.enum(["JPY", "USD", "EUR"]),
  purchasedAt: z.string().date(),                 // YYYY-MM-DD
  items: z.array(z.object({ name: z.string(), price: z.number() })).max(100),
  confidence: z.number().min(0).max(1),           // モデルに自己申告させる読み取り確度
});

export async function extractReceipt(image: Uint8Array) {
  const { object, usage } = await generateObject({
    model: bedrock("us.meta.llama4-maverick-17b-instruct-v1:0"),
    schema: Receipt,
    messages: [{
      role: "user",
      content: [
        { type: "image", image },
        { type: "text", text: "レシート画像から構造化データのみ抽出。読み取れない値は推測せず、confidenceを下げる。" },
      ],
    }],
  });
  // object は Receipt 準拠が型レベルで保証された安全な値。usage は画像トークン課金の可観測性。
  return { receipt: object, usage };
}

何を返そうと Receipt を通った値しか後段に流れない——これで「崩れたJSON」「想定外フィールド」を構造的に排除できます。


誤れない値を守る:信頼度ゲートと分業

ここが本番の肝です。金額・型番・本人情報のような“誤ると事故”の値を、モデルの一発出力で確定させてはいけません。音声接客で「数字はLLMでなくマスタ照合」と分業したのと同じ規律を、画像抽出にも敷きます。

// 抽出結果を“信頼度”と“検証可能性”で振り分ける(自動確定はしない)
type Routed =
  | { status: "auto"; receipt: Receipt }       // 高確度かつ検算一致 → 自動採用
  | { status: "review"; receipt: Receipt };     // 低確度 or 検算不一致 → 人手レビュー

function route(receipt: Receipt): Routed {
  const sumOfItems = receipt.items.reduce((a, b) => a + b.price, 0);
  const arithmeticOk = Math.abs(sumOfItems - receipt.total) < 1; // 明細合計と総額の検算
  const confident = receipt.confidence >= 0.9;
  return confident && arithmeticOk ? { status: "auto", receipt } : { status: "review", receipt };
}

ポイントは検算(明細合計=総額)という“モデルに依存しない真実”で裏取りしていること。LLM は読み取りの労を担い、正しさはコードが保証します。これにより、人手レビューを「全件」から「怪しい一部だけ」に絞れ、品質とコストを両立できます。


落とし穴と対策

  • 幻覚フィールド:読めない欄を“それっぽく”埋める。→ プロンプトで「推測禁止・不明はnull/低confidence」を明示し、temperature=0。スキーマで nullable を許容して“空”を表現可能にする。
  • 低解像度・傾き・影:読み取り精度が落ちる。→ 前処理(リサイズ・回転補正・コントラスト)を1段挟む。8000px 上限・3.75MB 制約にも前処理で寄せる。
  • 多ページ:1リクエストに詰めすぎる。→ ページ分割し、ページごとに抽出して統合。
  • 画像トークン課金:画像は入力トークンを多く消費する。→ 解像度を必要十分に落とす、難しい画像だけ上位モデルに回す(コスト設計)。
  • 評価不在:見た目で判断。→ 正解付き評価セットでフィールド一致率(精度/再現率)を測り、回帰を検出してから出す。

セキュリティ:画像は PII の塊

帳票・名刺・本人確認書類は個人情報そのものです。設計に保護を織り込みます。

  • ログにバイト列・抽出本文を残さない:可観測性はメタデータ(モデル・トークン数・confidence・処理時間)だけで足ります。
  • 最小権限:画像ストレージ(S3等)は最小権限・暗号化・短命URL。処理後は保持ポリシーに従い削除。
  • マスキング:番号類は後段で必要最小限に。表示UIでは伏字(アクセシブルに——読み上げで全桁を露出しない)。
  • 入力検証:ファイル形式・サイズ・枚数を境界で検証してから投入(型安全の規律)。

抽出した構造化データは、最終的に人が使う画面へ流れます。伏字・ラベル・エラー表現をアクセシブルに設計してこそ、抽出パイプラインは“プロダクト”になります。


よくある質問(FAQ)

Q. OCR専用サービスと何が違う? A. 従来OCRは「文字を読む」まで。Llama 4 は「読んで、意味を理解し、構造化して返す」まで一気通貫。レイアウトが多様な帳票や、文脈依存の項目抽出に強い。一方で誤れない値は必ず検算/マスタ照合で裏取りする設計は OCR と同じく必須です。

Q. どのモデルを使うべき? A. 画像理解は Maverick が堅い。大量・簡単なものは Scout でコストを抑え、難しい画像だけ上位へ回すルーティングが費用対効果の最適点です。

Q. 日本語の帳票も読める? A. 読めます。ただし手書き・低解像度・特殊フォントは精度が落ちるので、前処理と信頼度ゲート、人手レビュー経路を必ず用意してください。

Q. 何枚まで一度に渡せる? A. 公式制約で1メッセージ最大20枚・各3.75MB/8000px。多ページや高解像度はページ分割・リサイズで寄せます。

Q. セルフホストでも画像理解できる? A. できます。vLLM で Scout/Maverick をサーブすれば、OpenAI互換の画像入力で同様に扱えます。データを外に出せない KYC 等はこちら。


まとめ

Llama 4 のマルチモーダルは、「紙とスクショを、後段が使えるデータに変える」実務の道具です。鍵は派手な使い方ではなく、規律にあります。

  1. Converse の画像ブロックで投入(format+bytes、温度0)。
  2. Zodで境界検証し、崩れた出力を構造的に排除する。
  3. 誤れない値は検算/マスタ照合で裏取りし、自動確定しない。
  4. PII保護(ログ非出力・最小権限・マスキング)を織り込む。
  5. 評価セットで精度を測り、回帰を見てから出す。

帳票・本人確認・図面などの画像理解を、検算・人手レビュー・PII保護・コスト設計まで含めて本番に載せたいなら、実績をご覧のうえご相談ください。一人 × 生成AIで、速く・安く・安全に。

出典・公式リソース

※ モデル・制約・料金は更新されます。実装前に一次情報を確認し、正解付き評価で精度を検証してください。

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事で解説した技術の適用事例

生成AI音声チャットボット

ケーススタディを見る