AI Agents · レッスン

Claude Vision と GPT-4V による画像・テキストエージェント

API 呼び出しで画像を送信し、視覚的グラウンディングと画像を考慮したツール利用を学びます。

レッスン 1/413 ステップ

「Claude Vision と GPT-4V による画像・テキストエージェント」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。

マルチモーダルエージェント:画像+テキスト

マルチモーダルエージェントは、文章を読めるだけでなく見ることもできます。同じAPI呼び出しで画像をテキストとともに送信すると、エージェントは写真について質問に答えたり、グラフを分析したり、スクリーンショットを読んだり、図を説明したりできます。これらすべてを同じ会話ループ内で行えます。

OpenAI APIで画像を送信する

OpenAIのビジョンモデル(GPT-4o、GPT-4V)は、単純な文字列ではなくcontent配列を受け付けます。各要素はtextオブジェクトまたはimage_urlオブジェクトです。画像には公開URLまたはbase64でエンコードしたデータURLを指定できます。

from openai import OpenAI

client = OpenAI(api_key='YOUR_OPENAI_API_KEY')

# Using a public URL
response = client.chat.completions.create(
    model='gpt-4o',
    messages=[
        {
            'role': 'user',
            'content': [
                {
                    'type': 'image_url',
                    'image_url': {
                        'url': 'https://example.com/chart.png'
                    }
                },
                {
                    'type': 'text',
                    'text': 'What trend does this chart show?'
                }
            ]
        }
    ],
    max_tokens=512
)
print(response.choices[0].message.content)

Base64画像エンコーディング

公開アクセスできない画像(ローカルファイル、スクリーンショット、ユーザーのアップロードなど)は、base64としてエンコードし、data:image/jpeg;base64,...のURLスキームを使用してAPI呼び出しに直接埋め込みます。

import base64
from pathlib import Path

Path('screenshot.png').write_bytes(b'\x89PNG\r\n\x1a\n' + bytes(range(40)))

def encode_image_to_base64(image_path: str) -> str:
    with open(image_path, 'rb') as f:
        return base64.b64encode(f.read()).decode('utf-8')

def build_image_message(image_path: str, question: str, mime: str = 'jpeg') -> dict:
    b64 = encode_image_to_base64(image_path)
    data_url = f'data:image/{mime};base64,{b64}'
    return {
        'role': 'user',
        'content': [
            {'type': 'image_url', 'image_url': {'url': data_url}},
            {'type': 'text', 'text': question}
        ]
    }

message = build_image_message('screenshot.png', 'What error is shown?', mime='png')
print('Message built, image size:', len(message['content'][0]['image_url']['url']))

Claude Vision API

AnthropicのClaudeモデルもビジョンに対応しています。コンテンツブロックでは、type: base64のsourceフィールドとmedia_typeを使用します。構造はOpenAIのものと少し異なりますが、同等に強力です。

import anthropic
import base64

client = anthropic.Anthropic(api_key='YOUR_ANTHROPIC_API_KEY')

with open('diagram.png', 'rb') as f:
    image_data = base64.standard_b64encode(f.read()).decode('utf-8')

response = client.messages.create(
    model='claude-opus-4-5',
    max_tokens=512,
    messages=[
        {
            'role': 'user',
            'content': [
                {
                    'type': 'image',
                    'source': {
                        'type': 'base64',
                        'media_type': 'image/png',
                        'data': image_data
                    }
                },
                {
                    'type': 'text',
                    'text': 'Describe the architecture shown in this diagram.'
                }
            ]
        }
    ]
)
print(response.content[0].text)

ファイル拡張子からのMIMEタイプの検出

画像形式(JPEG、PNG、GIF、WebP)ごとに異なるMIMEタイプを使用します。エージェントのコードにハードコードする必要がないよう、ファイル拡張子からMIMEタイプを自動検出します。

import os
import base64

with open('photo.jpg', 'wb') as f:
    f.write(b'\xff\xd8\xff' + bytes(range(30)))

MIME_MAP = {
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.png': 'image/png',
    '.gif': 'image/gif',
    '.webp': 'image/webp'
}

def get_mime_type(image_path: str) -> str:
    ext = os.path.splitext(image_path)[1].lower()
    mime = MIME_MAP.get(ext)
    if not mime:
        raise ValueError(f'Unsupported image format: {ext}')
    return mime

def load_image_as_base64(image_path: str) -> tuple:
    """Returns (base64_string, mime_type)"""
    mime = get_mime_type(image_path)
    with open(image_path, 'rb') as f:
        b64 = base64.b64encode(f.read()).decode('utf-8')
    return b64, mime

b64, mime = load_image_as_base64('photo.jpg')
print(f'MIME: {mime}, Size: {len(b64)} bytes base64')

エージェントループでの画像分析

エージェントループでは、画像分析はツールです。エージェントは、他のツールと同じように、いつ呼び出すかを判断します。ツールスキーマで定義し、エージェントがプログラムから推論できるように構造化データ(JSON)を返します。

def analyze_image_tool(image_path: str, query: str) -> dict:
    """
    Agent tool: analyse an image and return structured findings.
    """
    import anthropic, base64
    client = anthropic.Anthropic(api_key='YOUR_API_KEY')
    b64, mime = load_image_as_base64(image_path)

    structured_query = (
        query + '\n\nRespond with JSON only: '
        '{"description": str, "objects": [str], "text_found": str, "confidence": float}'
    )
    response = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=512,
        messages=[{
            'role': 'user',
            'content': [
                {'type': 'image', 'source': {'type': 'base64',
                  'media_type': mime, 'data': b64}},
                {'type': 'text', 'text': structured_query}
            ]
        }]
    )
    import json
    return json.loads(response.content[0].text)

画像の詳細レベルの制御(OpenAI)

OpenAIのビジョンAPIは、detailパラメーターを受け付けます。low(高速で低コスト、85トークン)、high(詳細、画像をタイルに分割、最大1105トークン)、またはauto(モデルが判断)を指定できます。単純な yes/no の質問にはlowを、小さな文字の読み取りなど細かな分析にはhighを使用します。

def query_image_openai(
    image_path: str,
    question: str,
    detail: str = 'auto'  # 'low', 'high', or 'auto'
) -> str:
    import base64
    from openai import OpenAI
    client = OpenAI(api_key='YOUR_OPENAI_API_KEY')
    b64, mime = load_image_as_base64(image_path)
    data_url = f'data:{mime};base64,{b64}'

    response = client.chat.completions.create(
        model='gpt-4o',
        max_tokens=512,
        messages=[{
            'role': 'user',
            'content': [
                {
                    'type': 'image_url',
                    'image_url': {'url': data_url, 'detail': detail}
                },
                {'type': 'text', 'text': question}
            ]
        }]
    )
    return response.choices[0].message.content

複数画像の会話

1つのメッセージで複数の画像を送信することも、会話の複数のターンにわたって送信することもできます。これにより、「この2つのスクリーンショットを比較して、何が変わったか説明してください」のような比較タスクが可能になります。

def compare_two_images(
    image_path_1: str,
    image_path_2: str,
    comparison_question: str
) -> str:
    import anthropic, base64
    client = anthropic.Anthropic(api_key='YOUR_API_KEY')
    b64_1, mime_1 = load_image_as_base64(image_path_1)
    b64_2, mime_2 = load_image_as_base64(image_path_2)

    response = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=512,
        messages=[{
            'role': 'user',
            'content': [
                {'type': 'image', 'source': {'type': 'base64',
                  'media_type': mime_1, 'data': b64_1}},
                {'type': 'image', 'source': {'type': 'base64',
                  'media_type': mime_2, 'data': b64_2}},
                {'type': 'text', 'text': comparison_question}
            ]
        }]
    )
    return response.content[0].text

画像エージェント:スクリーンショットリーダー

実用的なユースケースとして、アプリケーションのスクリーンショットを読み取り、フォームフィールドの値、エラーメッセージ、UIの状態を抽出するエージェントがあります。これはテスト自動化や監視パイプラインに役立ちます。

SCREENSHOT_READER_PROMPT = (
    'You are a UI analyser. Given this application screenshot, extract:\n'
    '1. The current page/screen name\n'
    '2. Any error messages\n'
    '3. Key UI elements visible (buttons, form fields, text)\n'
    '4. The overall app state\n\n'
    'Return JSON: {"screen": str, "errors": [str], '
    '"elements": [str], "state": str}'
)

def read_screenshot(screenshot_path: str) -> dict:
    import anthropic, base64, json
    client = anthropic.Anthropic(api_key='YOUR_API_KEY')
    b64, mime = load_image_as_base64(screenshot_path)
    response = client.messages.create(
        model='claude-opus-4-5',
        max_tokens=512,
        messages=[{
            'role': 'user',
            'content': [
                {'type': 'image', 'source': {'type': 'base64',
                  'media_type': mime, 'data': b64}},
                {'type': 'text', 'text': SCREENSHOT_READER_PROMPT}
            ]
        }]
    )
    return json.loads(response.content[0].text)

ビジョン呼び出しのコスト最適化

ビジョンAPIの呼び出しは、テキストのみの呼び出しより大幅に高コストです。エンコード前に画像のサイズを変更する(多くのモデルは512×512~2048×2048を受け付けます)、単純なタスクにはdetail=lowを使用する、変更されていない画像の分析結果をキャッシュする、複数の質問を1回の呼び出しにまとめる、といった方法でコストを最適化します。

from PIL import Image
import io, base64

def resize_and_encode(
    image_path: str,
    max_dim: int = 1024
) -> tuple:
    img = Image.open(image_path)
    # Resize maintaining aspect ratio
    ratio = min(max_dim / img.width, max_dim / img.height)
    if ratio < 1.0:
        new_w = int(img.width * ratio)
        new_h = int(img.height * ratio)
        img = img.resize((new_w, new_h), Image.LANCZOS)
        print(f'Resized to {new_w}x{new_h} (from {img.width}x{img.height})')

    # Convert to JPEG for smaller size
    buf = io.BytesIO()
    img.save(buf, format='JPEG', quality=85)
    b64 = base64.b64encode(buf.getvalue()).decode('utf-8')
    return b64, 'image/jpeg'

ビジョンの制限とフォールバック

ビジョンモデルには制限があります。非常に小さな文字を確実に読めないことや、高度に圧縮された画像の処理を苦手とすることがあり、詳細を幻覚する可能性もあります。重要な抽出データ(例:グラフ上の数値)は、信頼度スコアを尋ねるフォールバックプロンプトを使って必ず検証してください。

def analyze_with_confidence(
    image_path: str,
    question: str,
    confidence_threshold: float = 0.7
) -> dict:
    import anthropic, json
    client = anthropic.Anthropic(api_key='YOUR_API_KEY')
    b64, mime = load_image_as_base64(image_path)

    prompt = (
        question + '\n\nAlso rate your confidence (0.0-1.0) in the answer.\n'
        'Return JSON: {"answer": str, "confidence": float, '
        '"uncertainty_reason": str}'
    )
    response = client.messages.create(
        model='claude-opus-4-5', max_tokens=256,
        messages=[{'role': 'user', 'content': [
            {'type': 'image', 'source': {'type': 'base64',
              'media_type': mime, 'data': b64}},
            {'type': 'text', 'text': prompt}
        ]}]
    )
    result = json.loads(response.content[0].text)
    if result['confidence'] < confidence_threshold:
        result['action'] = 'human_review_needed'
    return result

理解度チェック

OpenAIのビジョンAPIで、画像分析の詳細レベルとコストを制御するパラメーターはどれですか。

復習:画像・テキストエージェント

よくできました。学習した内容は次のとおりです。

  • OpenAIのビジョン:image_urlオブジェクトとtextオブジェクトを含むcontent配列。URLとbase64に対応
  • Claudeのビジョン:media_typeを伴うsource.type: base64
  • Base64エンコーディング:ファイルを読み取る → base64にエンコード → データURLとして埋め込む
  • 詳細レベル:高速・低コストにはlow、細かな分析にはhighを使用
  • コスト最適化:画像のサイズ変更、質問の一括処理、結果のキャッシュ

次は、Whisperによる文字起こしとTTSによる応答を使った音声・テキストエージェントのワークフローです。

無料で開始

AI チューターと学ぶ AI Agents — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
60
レッスン
239

よくある質問

「Claude Vision と GPT-4V による画像・テキストエージェント」レッスンは無料ですか?

はい。「Claude Vision と GPT-4V による画像・テキストエージェント」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。

「Claude Vision と GPT-4V による画像・テキストエージェント」で何を学びますか?

API 呼び出しで画像を送信し、視覚的グラウンディングと画像を考慮したツール利用を学びます。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

AI Agentsを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「Claude Vision と GPT-4V による画像・テキストエージェント」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このAI Agentsレッスンでコードを書いて実行できますか?

はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Claude Vision と GPT-4V による画像・テキストエージェント
  2. 音声・テキストエージェントのワークフロー
  3. エージェントにおける動画理解
  4. クロスモーダル推論のパターン
← AI Agentsに戻る