Trung cấpHướng dẫnClaude APINguồn: Anthropic

Vision + Tool Use — Trích xuất dữ liệu từ hình ảnh

Nghe bài viết
00:00

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1 Công cụ AI sẽ thay đổi cách bạn làm việc: Vision alone chỉ gửi ảnh và hỏi cho output dạng text tự nhiên: Chi dung Vision - output khong nhat quan response =. Điểm mấu chốt là biết cách đặt prompt đúng để nhận kết quả có thể sử dụng ngay.
  2. 2 Một điều ít người đề cập: import anthropic import base64 import json from pathlib import Path client = anthropic.Anthropic nutritiontool = {. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
  3. 3 Điểm nhấn quan trọng: def displaynutritiondata: """In thong tin dinh duong dep mat""" print"=" 50 if data.get"productname": printf"SAN PHAM:. Đây là phần mang lại giá trị thực tiễn cao nhất trong toàn bài viết.
  4. 4 Bước đầu tiên bạn nên làm: import asyncio from concurrent.futures import ThreadPoolExecutor def batchextractnutritionimageurls, maxworkers=5: """. Áp dụng đúng cách sẽ thấy kết quả rõ rệt từ tuần đầu tiên.
  5. 5 Một điều ít người đề cập: Tình huống Cách xử lý Ảnh mờ, khuất Field confidence: "low" + notes mô tả vấn đề Nhãn tiếng nước ngoài Claude đọc được. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
an abstract image of a network of dots

Một trong những ứng dụng thú vị nhất của Claude API là kết hợp Vision (phân tích hình ảnh) với Tool Use (output có cấu trúc). Kết quả: bạn có thể gửi một bức ảnh và nhận về JSON data — không cần OCR riêng, không cần computer vision model chuyên biệt.

Bài này xây dựng pipeline trích xuất thông tin dinh dưỡng từ ảnh nhãn thực phẩm — bài toán thực tế cho app theo dõi sức khỏe, hệ thống quản lý kho thực phẩm, hoặc ứng dụng đọc nhãn cho người khiếm thị.

Tại sao kết hợp Vision + Tool Use?

Vision alone (chỉ gửi ảnh và hỏi) cho output dạng text tự nhiên:

# Chi dung Vision - output khong nhat quan
response = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=512,
    messages=[{
        "role": "user",
        "content": [
            {"type": "image", "source": {"type": "url", "url": image_url}},
            {"type": "text", "text": "Bao nhieu calories trong san pham nay?"}
        ]
    }]
)
# Output co the la:
# "San pham nay chua khoang 250 calories moi khau phan."
# "Calories: 250 kcal"
# "250 Cal (dua tren khau phan 30g)"
# Moi lan chay khac nhau!

Vision + Tool Use cho output JSON có cấu trúc, nhất quán 100%:

# Vision + Tool Use - output co cau truc bao dam
# {
#   "calories": 250,
#   "serving_size": "30g",
#   "fat_total_g": 12.5,
#   "cholesterol_mg": 0,
#   "sodium_mg": 180,
#   "carbohydrates_g": 31,
#   "protein_g": 3,
#   ...
# }

Định nghĩa Nutrition Tool

import anthropic
import base64
import json
from pathlib import Path

client = anthropic.Anthropic()

nutrition_tool = {
    "name": "print_nutrition_info",
    "description": "Hien thi thong tin dinh duong tu nhan thuc pham da duoc doc tu hinh anh",
    "input_schema": {
        "type": "object",
        "properties": {
            "product_name": {
                "type": "string",
                "description": "Ten san pham (neu doc duoc tu nhan)"
            },
            "serving_size": {
                "type": "string",
                "description": "Khau phan an, VD: '30g', '1 cup (240ml)'"
            },
            "servings_per_container": {
                "type": "number",
                "description": "So khau phan trong bao bi, null neu khong co"
            },
            "calories": {
                "type": "number",
                "description": "Calories moi khau phan (kcal)"
            },
            "calories_from_fat": {
                "type": "number",
                "description": "Calories tu chat beo, null neu khong co"
            },
            "fat_total_g": {
                "type": "number",
                "description": "Tong chat beo (gram)"
            },
            "fat_saturated_g": {
                "type": "number",
                "description": "Chat beo bao hoa (gram), null neu khong co"
            },
            "fat_trans_g": {
                "type": "number",
                "description": "Chat beo trans (gram), null neu khong co"
            },
            "cholesterol_mg": {
                "type": "number",
                "description": "Cholesterol (miligram)"
            },
            "sodium_mg": {
                "type": "number",
                "description": "Natri/Muoi (miligram)"
            },
            "carbohydrates_g": {
                "type": "number",
                "description": "Tong carbohydrate (gram)"
            },
            "fiber_g": {
                "type": "number",
                "description": "Chat xo (gram), null neu khong co"
            },
            "sugar_g": {
                "type": "number",
                "description": "Duong (gram), null neu khong co"
            },
            "protein_g": {
                "type": "number",
                "description": "Protein (gram)"
            },
            "vitamins_minerals": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "amount": {"type": "string"},
                        "daily_value_percent": {"type": "number"}
                    }
                },
                "description": "Danh sach vitamins va khoang chat (neu co)"
            },
            "confidence": {
                "type": "string",
                "enum": ["high", "medium", "low"],
                "description": "Do tin cay cua viec doc nhan - high: nhan ro net, low: nhan mo/bi che"
            },
            "notes": {
                "type": "string",
                "description": "Ghi chu them (nhan bi che mot phan, don vi khac thuong, v.v.)"
            }
        },
        "required": ["serving_size", "calories", "fat_total_g", "cholesterol_mg",
                     "sodium_mg", "carbohydrates_g", "protein_g", "confidence"]
    }
}

Gửi Ảnh đến Claude

Claude hỗ trợ hai cách gửi ảnh: URL trực tiếp hoặc base64 encoded.

Cách 1: Gửi qua URL

def extract_nutrition_from_url(image_url):
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        tools=[nutrition_tool],
        tool_choice={"type": "tool", "name": "print_nutrition_info"},
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "url",
                        "url": image_url
                    }
                },
                {
                    "type": "text",
                    "text": "Doc va trich xuat thong tin dinh duong day du tu nhan thuc pham trong hinh."
                }
            ]
        }]
    )

    if response.content[0].type == "tool_use":
        return response.content[0].input
    return None

Cách 2: Gửi file local qua base64

def extract_nutrition_from_file(image_path):
    # Doc file va chuyen sang base64
    with open(image_path, "rb") as f:
        image_data = base64.standard_b64encode(f.read()).decode("utf-8")

    # Xac dinh media type tu extension
    ext = Path(image_path).suffix.lower()
    media_types = {
        ".jpg": "image/jpeg",
        ".jpeg": "image/jpeg",
        ".png": "image/png",
        ".gif": "image/gif",
        ".webp": "image/webp"
    }
    media_type = media_types.get(ext, "image/jpeg")

    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        tools=[nutrition_tool],
        tool_choice={"type": "tool", "name": "print_nutrition_info"},
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": media_type,
                        "data": image_data
                    }
                },
                {
                    "type": "text",
                    "text": "Doc va trich xuat thong tin dinh duong day du tu nhan thuc pham trong hinh."
                }
            ]
        }]
    )

    if response.content[0].type == "tool_use":
        return response.content[0].input
    return None

Hiển thị Kết quả

def display_nutrition(data):
    """In thong tin dinh duong dep mat"""
    print("=" * 50)
    if data.get("product_name"):
        print(f"SAN PHAM: {data['product_name']}")
    print(f"Khau phan: {data['serving_size']}")
    if data.get("servings_per_container"):
        print(f"So khau phan: {data['servings_per_container']}")
    print("=" * 50)
    print(f"{'Calories':<30} {data['calories']} kcal")
    if data.get("calories_from_fat"):
        print(f"  Tu chat beo: {data['calories_from_fat']} kcal")
    print("-" * 50)
    print(f"{'Tong chat beo':<30} {data['fat_total_g']}g")
    if data.get("fat_saturated_g") is not None:
        print(f"  Chat beo bao hoa: {data['fat_saturated_g']}g")
    if data.get("fat_trans_g") is not None:
        print(f"  Chat beo trans: {data['fat_trans_g']}g")
    print(f"{'Cholesterol':<30} {data['cholesterol_mg']}mg")
    print(f"{'Natri':<30} {data['sodium_mg']}mg")
    print(f"{'Tong Carbohydrate':<30} {data['carbohydrates_g']}g")
    if data.get("fiber_g") is not None:
        print(f"  Chat xo: {data['fiber_g']}g")
    if data.get("sugar_g") is not None:
        print(f"  Duong: {data['sugar_g']}g")
    print(f"{'Protein':<30} {data['protein_g']}g")

    if data.get("vitamins_minerals"):
        print("-" * 50)
        print("Vitamins va Khoang chat:")
        for vm in data["vitamins_minerals"]:
            dv = f"({vm['daily_value_percent']}% DV)" if vm.get("daily_value_percent") else ""
            print(f"  {vm['name']}: {vm['amount']} {dv}")

    print("=" * 50)
    print(f"Do tin cay: {data['confidence'].upper()}")
    if data.get("notes"):
        print(f"Ghi chu: {data['notes']}")

# Test voi anh nutrition label tu web
test_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Nutricion.jpg/400px-Nutricion.jpg"
result = extract_nutrition_from_url(test_url)
if result:
    display_nutrition(result)

Xử lý nhiều ảnh cùng lúc

import asyncio
from concurrent.futures import ThreadPoolExecutor

def batch_extract_nutrition(image_urls, max_workers=5):
    """
    Trich xuat thong tin dinh duong tu nhieu anh song song.
    Tra ve list ket qua theo thu tu input.
    """
    results = []
    errors = []

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = {
            executor.submit(extract_nutrition_from_url, url): i
            for i, url in enumerate(image_urls)
        }

        indexed_results = [None] * len(image_urls)
        for future in futures:
            idx = futures[future]
            try:
                indexed_results[idx] = {
                    "url": image_urls[idx],
                    "data": future.result(),
                    "success": True
                }
            except Exception as e:
                indexed_results[idx] = {
                    "url": image_urls[idx],
                    "error": str(e),
                    "success": False
                }

    return indexed_results

# Test voi nhieu anh
urls = [
    "https://example.com/product1-label.jpg",
    "https://example.com/product2-label.jpg",
    "https://example.com/product3-label.jpg",
]

results = batch_extract_nutrition(urls)
for r in results:
    if r["success"]:
        print(f"OK: {r['url']}")
        print(f"  Calories: {r['data']['calories']}")
    else:
        print(f"LOI: {r['url']} - {r['error']}")

Ứng dụng thực tế

1. App theo dõi dinh dưỡng

User chụp ảnh thức ăn, app trích xuất thông tin và tự động cộng vào nhật ký dinh dưỡng hàng ngày. Với Claude Vision + Tool Use, chỉ cần vài trăm dòng code để có feature này.

2. Hệ thống so sánh sản phẩm

Scan nhiều nhãn sản phẩm, so sánh nutritional profile, gợi ý lựa chọn lành mạnh hơn. Kết hợp với database sản phẩm để build recommendation engine.

3. Accessibility tool

Người dùng khiếm thị chụp ảnh nhãn sản phẩm, hệ thống đọc to thông tin dinh dưỡng quan trọng. Confidence field giúp cảnh báo khi ảnh không rõ.

4. Quality control trong sản xuất

Kiểm tra tự động xem nhãn in trên sản phẩm có đúng format, đủ thông tin bắt buộc theo quy định hay không.

Giới hạn và Xử lý Edge Cases

Tình huống Cách xử lý
Ảnh mờ, khuất Field confidence: "low" + notes mô tả vấn đề
Nhãn tiếng nước ngoài Claude đọc được nhiều ngôn ngữ — thêm instruction "dịch sang tiếng Việt"
Đơn vị khác thường Field notes để Claude ghi rõ đơn vị gốc
Không phải nhãn dinh dưỡng Claude trả về confidence: "low" và notes giải thích
Ảnh quá lớn Resize xuống 1024x1024 trước khi gửi — Claude không cần resolution cao để đọc text

Tối ưu Chi phí

Vision requests tốn nhiều token hơn text-only. Một số tips:

  • Resize ảnh trước khi gửi — 800x800 thường đủ để đọc text rõ
  • Crop vùng nhãn thay vì gửi cả ảnh sản phẩm — giảm 50-70% image tokens
  • Dùng claude-haiku cho batch processing lớn — rẻ hơn nhiều, vẫn đọc text tốt
  • Cache kết quả theo image hash — tránh phân tích lại ảnh đã xử lý
import hashlib

# Cache don gian dung in-memory dict
_nutrition_cache = {}

def extract_with_cache(image_url):
    # Tao cache key tu URL
    cache_key = hashlib.md5(image_url.encode()).hexdigest()

    if cache_key in _nutrition_cache:
        print(f"[Cache hit] {cache_key}")
        return _nutrition_cache[cache_key]

    result = extract_nutrition_from_url(image_url)
    _nutrition_cache[cache_key] = result
    return result

Tổng kết: Vision + Tool Use Pattern

Pattern Vision + Tool Use hoạt động tốt cho bất kỳ bài toán nào cần trích xuất structured data từ visual content:

  • Đọc hóa đơn, receipt — extract line items, total, date
  • Phân tích business card — extract tên, email, phone, company
  • Đọc bảng trong ảnh — convert sang JSON/CSV
  • Trích xuất thông số từ ảnh sản phẩm kỹ thuật
  • Phân tích chart/biểu đồ — extract data points

Chỉ cần định nghĩa tool schema phù hợp với cấu trúc data bạn cần, gửi ảnh kèm tool, và đọc tool.input — Claude làm phần còn lại.

Đây là điểm kết thúc của series Tool Use cơ bản. Bước tiếp theo trong hành trình Claude API: tìm hiểu về Prompt Caching để giảm chi phí khi làm việc với system prompts dài và Streaming để cải thiện UX trong ứng dụng chat thời gian thực.

Tính năng liên quan:Tool UseVisionMultimodalData ExtractionStructured Output

Bai viet co huu ich khong?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

Bình luận (0)
Ảnh đại diện
Đăng nhập để bình luận...
Đăng nhập để bình luận
  • Đang tải bình luận...

Đăng ký nhận bản tin

Nhận bài viết hay nhất về sản phẩm và vận hành, gửi thẳng vào hộp thư của bạn.

Bảo mật thông tin. Hủy đăng ký bất cứ lúc nào. Chính sách bảo mật.