0Pricing
AI Agents · 강의

Claude Vision과 GPT-4V를 활용한 이미지 + 텍스트 에이전트

API 호출에 이미지를 전송하고 시각적 근거를 확보하며 이미지를 고려한 도구 사용을 학습합니다.

Claude Vision과 GPT-4V를 활용한 이미지 + 텍스트 에이전트은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.

멀티모달 에이전트: 이미지 + 텍스트

멀티모달 에이전트는 읽을 뿐 아니라 볼 수도 있습니다. 같은 요청에 이미지와 텍스트를 함께 보내면 에이전트는 사진에 관한 질문에 답하고, 차트를 분석하고, 화면 캡처를 읽고, 다이어그램을 설명할 수 있습니다. 이 모든 작업이 하나의 대화 과정 안에서 이루어집니다.

OpenAI 인터페이스로 이미지 보내기

OpenAI의 비전 모델(GPT-4o, GPT-4V)은 일반 문자열 대신 content 배열을 허용합니다. 각 요소는 text 객체 또는 image_url 객체입니다. 이미지는 공개 웹 주소이거나 베이스64로 인코딩된 데이터 웹 주소일 수 있습니다.

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)

베이스64 이미지 인코딩

공개적으로 접근할 수 없는 이미지(로컬 파일, 화면 캡처, 사용자 업로드)는 베이스64로 인코딩한 다음 data:image/jpeg;base64,... 웹 주소 체계를 사용해 요청에 직접 삽입합니다.

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']))

클로드 비전 인터페이스

Anthropic의 클로드 모델도 비전 기능을 지원합니다. 콘텐츠 블록은 source 필드에서 type: base64와 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, 웹피) 사용하는 MIME 유형이 다릅니다. 에이전트 코드에 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')

에이전트 실행 과정에서 이미지 분석하기

에이전트 실행 과정에서 이미지 분석은 하나의 도구입니다. 에이전트는 다른 도구와 마찬가지로 언제 이를 호출할지 결정합니다. 도구 스키마에 이미지 분석을 정의하고 구조화된 데이터로 반환하면 에이전트가 이를 프로그래밍 방식으로 추론할 수 있습니다.

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의 비전 인터페이스는 detail 매개변수를 허용합니다. low는 빠르고 저렴하며 85토큰을 사용하고, high는 이미지를 타일로 나누어 자세히 분석하며 최대 1105토큰을 사용하고, auto는 모델이 결정합니다. 간단한 예/아니요 질문에는 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

다중 이미지 대화

한 메시지에 여러 이미지를 보내거나 대화의 여러 차례에 걸쳐 이미지를 보낼 수 있습니다. 이를 통해 “이 두 화면 캡처를 비교하고 무엇이 바뀌었는지 설명하세요.”와 같은 비교 작업을 수행할 수 있습니다.

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

이미지 에이전트: 화면 캡처 판독기

실용적인 활용 사례로, 애플리케이션 화면 캡처를 읽어 양식 필드 값, 오류 메시지, 사용자 인터페이스 상태를 추출하는 에이전트가 있습니다. 이는 자동화 테스트와 처리 흐름 관찰에 유용합니다.

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)

비전 요청 비용 최적화

비전 인터페이스 요청은 텍스트만 사용하는 요청보다 훨씬 비쌉니다. 인코딩하기 전에 이미지 크기를 조정하고(대부분의 모델은 512×512~2048×2048을 허용함), 간단한 작업에는 detail=low를 사용하고, 변경되지 않은 이미지의 분석 결과를 캐시하고, 여러 질문을 한 번의 요청으로 묶어 비용을 최적화합니다.

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 비전 인터페이스에서 이미지 분석의 세부 수준과 비용을 제어하는 매개변수는 무엇인가요?

복습: 이미지-텍스트 에이전트

잘하셨습니다! 다음 내용을 학습했습니다.

  • OpenAI 비전: image_url와 text 객체를 포함하는 content 배열, 웹 주소와 베이스64 지원
  • 클로드 비전: source.type: base64와 media_type
  • 베이스64 인코딩: 파일 읽기 → 베이스64 인코딩 → 데이터 웹 주소로 삽입
  • 세부 수준: 빠르고 저렴한 작업에는 low, 세밀한 분석에는 high 사용
  • 비용 최적화: 이미지 크기 조정, 질문 묶기, 결과 캐시

다음 내용에서는 Whisper 전사와 TTS 응답을 사용하는 음성-텍스트 에이전트 작업 흐름을 살펴봅니다.

자주 묻는 질문

“Claude Vision과 GPT-4V를 활용한 이미지 + 텍스트 에이전트” 강의는 무료인가요?

네 — “Claude Vision과 GPT-4V를 활용한 이미지 + 텍스트 에이전트” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.

“Claude Vision과 GPT-4V를 활용한 이미지 + 텍스트 에이전트”에서 뭘 배우나요?

API 호출에 이미지를 전송하고 시각적 근거를 확보하며 이미지를 고려한 도구 사용을 학습합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

AI Agents을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“Claude Vision과 GPT-4V를 활용한 이미지 + 텍스트 에이전트” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Claude Vision과 GPT-4V를 활용한 이미지 + 텍스트 에이전트
  2. 오디오 + 텍스트 에이전트 작업 흐름
  3. 에이전트의 동영상 이해
  4. 교차 모달 추론 패턴
← AI Agents(으)로 돌아가기