{"product_id":"batch-processing-xử-ly-hang-loạt-request-với-claude-api","title":"Batch Processing — Xử lý hàng loạt request với Claude API","description":"\n\u003cp\u003eBạn đang xử lý hàng nghìn tài liệu, phân loại hàng loạt email, hay chạy evaluations trên dataset lớn? Thay vì gọi API từng request một và chờ đợi, \u003cstrong\u003eMessage Batches API\u003c\/strong\u003e của Anthropic cho phép bạn gửi tối đa 10.000 request trong một lần, xử lý bất đồng bộ, và tiết kiệm đến \u003cstrong\u003e50% chi phí\u003c\/strong\u003e.\u003c\/p\u003e\n\n\u003cp\u003eBài viết này hướng dẫn toàn diện về Batch Processing — từ cách tạo batch, theo dõi trạng thái, lấy kết quả, đến xử lý lỗi và các kỹ thuật nâng cao.\u003c\/p\u003e\n\n\u003ch2\u003eTại sao cần Batch Processing?\u003c\/h2\u003e\n\n\u003cp\u003eKhi xử lý dữ liệu quy mô lớn, bạn thường gặp ba vấn đề:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTốc độ:\u003c\/strong\u003e Gọi API tuần tự (sequential) mất rất nhiều thời gian — 1.000 request × 2 giây\/request = gần 34 phút\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eRate limits:\u003c\/strong\u003e Gọi song song (concurrent) thường bị throttle ở tốc độ cao\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eChi phí:\u003c\/strong\u003e Standard API pricing không có discount cho volume lớn\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eMessage Batches API giải quyết cả ba: bạn submit tất cả cùng lúc, Anthropic xử lý trong nền, và bạn trả \u003cstrong\u003e50% giá so với standard API\u003c\/strong\u003e.\u003c\/p\u003e\n\n\u003ch2\u003eGiới hạn và điều kiện\u003c\/h2\u003e\n\n\u003cul\u003e\n  \u003cli\u003eTối đa \u003cstrong\u003e10.000 requests\u003c\/strong\u003e mỗi batch\u003c\/li\u003e\n  \u003cli\u003eKích thước batch tối đa: \u003cstrong\u003e32 MB\u003c\/strong\u003e\n\u003c\/li\u003e\n  \u003cli\u003eThời gian xử lý: thường hoàn thành trong vòng \u003cstrong\u003e24 giờ\u003c\/strong\u003e\n\u003c\/li\u003e\n  \u003cli\u003eKết quả được lưu trong \u003cstrong\u003e29 ngày\u003c\/strong\u003e sau khi tạo\u003c\/li\u003e\n  \u003cli\u003eBatch không thể bị hủy sau khi 60% requests đã xử lý\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eBước 1: Tạo một Batch\u003c\/h2\u003e\n\n\u003cp\u003eMỗi request trong batch cần có một \u003ccode\u003ecustom_id\u003c\/code\u003e duy nhất để bạn map kết quả về sau:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003eimport anthropic\n\nclient = anthropic.Anthropic()\n\n# Tạo danh sách requests\nrequests = []\ndocuments = [\n    {\"id\": \"doc_001\", \"text\": \"Sản phẩm này rất tốt, tôi rất hài lòng!\"},\n    {\"id\": \"doc_002\", \"text\": \"Giao hàng chậm và đóng gói kém chất lượng.\"},\n    {\"id\": \"doc_003\", \"text\": \"Giá cả hợp lý, chất lượng tạm ổn.\"},\n    # ... thêm hàng nghìn documents\n]\n\nfor doc in documents:\n    requests.append(\n        anthropic.types.message_create_params.MessageCreateParamsNonStreaming(\n            custom_id=doc[\"id\"],\n            params={\n                \"model\": \"claude-haiku-4-5\",\n                \"max_tokens\": 100,\n                \"messages\": [\n                    {\n                        \"role\": \"user\",\n                        \"content\": f\"Phân loại cảm xúc: POSITIVE, NEGATIVE, hay NEUTRAL?\n\nText: {doc['text']}\n\nChỉ trả lời một từ.\"\n                    }\n                ]\n            }\n        )\n    )\n\n# Tạo batch\nbatch = client.messages.batches.create(requests=requests)\nprint(f\"Batch ID: {batch.id}\")\nprint(f\"Trạng thái: {batch.processing_status}\")\nprint(f\"Tổng requests: {batch.request_counts.processing}\")\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eAPI trả về ngay lập tức với \u003ccode\u003ebatch.id\u003c\/code\u003e — bạn dùng ID này để theo dõi và lấy kết quả.\u003c\/p\u003e\n\n\u003ch2\u003eBước 2: Theo dõi trạng thái\u003c\/h2\u003e\n\n\u003cp\u003eBatch có thể mất từ vài phút đến vài giờ tùy kích thước. Có hai cách theo dõi:\u003c\/p\u003e\n\n\u003ch3\u003ePolling thủ công\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003eimport time\n\ndef wait_for_batch(batch_id, poll_interval=60):\n    \"\"\"Chờ batch hoàn thành, poll mỗi poll_interval giây.\"\"\"\n    while True:\n        batch = client.messages.batches.retrieve(batch_id)\n\n        counts = batch.request_counts\n        total = counts.processing + counts.succeeded + counts.errored + counts.canceled + counts.expired\n\n        print(f\"[{batch.processing_status}] \"\n              f\"Đang xử lý: {counts.processing}\/{total} | \"\n              f\"Thành công: {counts.succeeded} | \"\n              f\"Lỗi: {counts.errored}\")\n\n        if batch.processing_status == \"ended\":\n            print(\"Batch hoàn thành!\")\n            return batch\n\n        time.sleep(poll_interval)\n\nbatch = wait_for_batch(batch.id, poll_interval=30)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eKiểm tra status counts\u003c\/h3\u003e\n\n\u003cp\u003eTrường \u003ccode\u003erequest_counts\u003c\/code\u003e cho biết chi tiết:\u003c\/p\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003eTrạng thái\u003c\/th\u003e\n\u003cth\u003eÝ nghĩa\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eprocessing\u003c\/code\u003e\u003c\/td\u003e\n\u003ctd\u003eĐang được xử lý\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003esucceeded\u003c\/code\u003e\u003c\/td\u003e\n\u003ctd\u003eHoàn thành thành công\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eerrored\u003c\/code\u003e\u003c\/td\u003e\n\u003ctd\u003eGặp lỗi (invalid request, v.v.)\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecanceled\u003c\/code\u003e\u003c\/td\u003e\n\u003ctd\u003eBị hủy bởi user\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eexpired\u003c\/code\u003e\u003c\/td\u003e\n\u003ctd\u003eHết hạn 24 giờ chưa xử lý xong\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003ch2\u003eBước 3: Lấy kết quả\u003c\/h2\u003e\n\n\u003cp\u003eSau khi batch \u003ccode\u003eended\u003c\/code\u003e, dùng \u003ccode\u003estream_results()\u003c\/code\u003e để iterate qua từng kết quả:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003eresults = {}\n\nfor result in client.messages.batches.results(batch.id):\n    custom_id = result.custom_id\n\n    if result.result.type == \"succeeded\":\n        message = result.result.message\n        text = message.content[0].text\n        results[custom_id] = {\n            \"status\": \"success\",\n            \"output\": text,\n            \"input_tokens\": message.usage.input_tokens,\n            \"output_tokens\": message.usage.output_tokens,\n        }\n    elif result.result.type == \"errored\":\n        error = result.result.error\n        results[custom_id] = {\n            \"status\": \"error\",\n            \"error_type\": error.type,\n            \"error_message\": error.message,\n        }\n\n# In kết quả\nfor doc_id, result in results.items():\n    if result[\"status\"] == \"success\":\n        print(f\"{doc_id}: {result['output']}\")\n    else:\n        print(f\"{doc_id}: ERROR - {result['error_message']}\")\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eXử lý lỗi và Retry\u003c\/h2\u003e\n\n\u003cp\u003eMột số requests trong batch có thể thất bại vì nhiều lý do: timeout, invalid input, content policy. Chiến lược xử lý tốt nhất là \u003cstrong\u003etạo retry batch\u003c\/strong\u003e chỉ với những request lỗi:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003edef retry_failed_requests(original_requests, results):\n    \"\"\"Tạo batch mới với các requests bị lỗi.\"\"\"\n    failed_ids = {\n        custom_id\n        for custom_id, result in results.items()\n        if result[\"status\"] == \"error\"\n    }\n\n    if not failed_ids:\n        print(\"Không có lỗi nào cần retry!\")\n        return None\n\n    # Filter requests gốc\n    retry_requests = [\n        req for req in original_requests\n        if req.custom_id in failed_ids\n    ]\n\n    print(f\"Retry {len(retry_requests)} requests bị lỗi...\")\n    retry_batch = client.messages.batches.create(requests=retry_requests)\n    return retry_batch.id\n\nretry_batch_id = retry_failed_requests(requests, results)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eXử lý nhiều loại message khác nhau trong một batch\u003c\/h2\u003e\n\n\u003cp\u003eSức mạnh thực sự của Batch API: mỗi request hoàn toàn độc lập — bạn có thể mix nhiều loại task, model, và cấu hình trong cùng một batch:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003emixed_requests = [\n    # Task 1: Phân loại ngắn gọn với Haiku\n    anthropic.types.message_create_params.MessageCreateParamsNonStreaming(\n        custom_id=\"classify_001\",\n        params={\n            \"model\": \"claude-haiku-4-5\",\n            \"max_tokens\": 50,\n            \"messages\": [{\"role\": \"user\", \"content\": \"Classify: SPAM or HAM?\nEmail: Win a free iPhone now!\"}]\n        }\n    ),\n    # Task 2: Tóm tắt dài hơn với Sonnet\n    anthropic.types.message_create_params.MessageCreateParamsNonStreaming(\n        custom_id=\"summarize_001\",\n        params={\n            \"model\": \"claude-sonnet-4-5\",\n            \"max_tokens\": 500,\n            \"system\": \"Bạn là chuyên gia tóm tắt văn bản. Tóm tắt ngắn gọn, súc tích.\",\n            \"messages\": [{\"role\": \"user\", \"content\": \"Tóm tắt bài viết sau:\n\n[Nội dung dài 5000 từ...]\"}]\n        }\n    ),\n    # Task 3: Translation với system prompt khác\n    anthropic.types.message_create_params.MessageCreateParamsNonStreaming(\n        custom_id=\"translate_001\",\n        params={\n            \"model\": \"claude-haiku-4-5\",\n            \"max_tokens\": 200,\n            \"system\": \"Translate the following text to Vietnamese. Keep technical terms in English.\",\n            \"messages\": [{\"role\": \"user\", \"content\": \"Machine learning models require large datasets.\"}]\n        }\n    ),\n]\n\nbatch = client.messages.batches.create(requests=mixed_requests)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eTính chi phí và so sánh\u003c\/h2\u003e\n\n\u003cp\u003eGiả sử bạn cần phân loại \u003cstrong\u003e10.000 emails\u003c\/strong\u003e, mỗi email ~500 input tokens và response ~50 tokens:\u003c\/p\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003ePhương pháp\u003c\/th\u003e\n\u003cth\u003eThời gian\u003c\/th\u003e\n\u003cth\u003eChi phí (Haiku)\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003eStandard API (sequential)\u003c\/td\u003e\n\u003ctd\u003e~5 giờ\u003c\/td\u003e\n\u003ctd\u003e$3.75\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eStandard API (concurrent)\u003c\/td\u003e\n\u003ctd\u003e~30 phút\u003c\/td\u003e\n\u003ctd\u003e$3.75\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003eBatch API\u003c\/strong\u003e\u003c\/td\u003e\n\u003ctd\u003e~2-4 giờ\u003c\/td\u003e\n\u003ctd\u003e\u003cstrong\u003e$1.88 (giảm 50%)\u003c\/strong\u003e\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003cp\u003eVới 10.000 emails, bạn tiết kiệm gần \u003cstrong\u003e$1.87\u003c\/strong\u003e. Với 1 triệu emails mỗi tháng, tiết kiệm hơn \u003cstrong\u003e$187\u003c\/strong\u003e.\u003c\/p\u003e\n\n\u003ch2\u003eLiệt kê và quản lý Batches\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003e# Liệt kê tất cả batches gần đây\nfor batch in client.messages.batches.list(limit=10):\n    print(f\"ID: {batch.id}\")\n    print(f\"  Status: {batch.processing_status}\")\n    print(f\"  Created: {batch.created_at}\")\n    print(f\"  Requests: {batch.request_counts}\")\n    print()\n\n# Hủy batch đang chạy (nếu chưa quá 60%)\ntry:\n    canceled = client.messages.batches.cancel(batch_id)\n    print(f\"Đã hủy batch: {canceled.processing_status}\")\nexcept Exception as e:\n    print(f\"Không thể hủy: {e}\")\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eKhi nào nên dùng Batch API?\u003c\/h2\u003e\n\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eNên dùng:\u003c\/strong\u003e Phân tích dataset lớn, chạy evaluations, xử lý tài liệu offline, ETL pipelines\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eKhông nên dùng:\u003c\/strong\u003e Chatbots real-time, ứng dụng cần response ngay lập tức, tasks cần kết quả theo thứ tự\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eBatch Processing là công cụ không thể thiếu khi làm việc với dữ liệu quy mô lớn. Kết hợp với \u003ca href=\"\/collections\/nang-cao\"\u003ePrompt Caching\u003c\/a\u003e để tối ưu hóa chi phí tối đa.\u003c\/p\u003e\n\n\u003chr\u003e\n\u003ch3\u003eBài viết liên quan\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"\/products\/calculator-tool-bai-h%E1%BB%8Dc-d%E1%BA%A7u-tien-v%E1%BB%81-tool-use-v%E1%BB%9Bi-claude\"\u003eCalculator Tool — Bài học đầu tiên về Tool Use với Claude\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/fine-tuning-claude-tren-aws-bedrock-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-t%E1%BB%ABng-b%C6%B0%E1%BB%9Bc\"\u003eFine-tuning Claude trên AWS Bedrock — Hướng dẫn từng bước\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/content-moderation-xay-d%E1%BB%B1ng-b%E1%BB%99-l%E1%BB%8Dc-n%E1%BB%99i-dung-v%E1%BB%9Bi-claude\"\u003eContent Moderation — Xây dựng bộ lọc nội dung với Claude\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/claude-cho-engineering-system-design-interviews-va-planning\"\u003eClaude cho Engineering: System Design interviews và planning\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/building-effective-agents-v%E1%BB%9Bi-claude-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn-ki%E1%BA%BFn-truc\"\u003eBuilding Effective Agents với Claude — Hướng dẫn kiến trúc\u003c\/a\u003e\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47721829040340,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/batch-processing-x_-ly-hang-lo_t-request-v_i-claude-api.jpg?v=1774521010","url":"https:\/\/claude.vn\/products\/batch-processing-x%e1%bb%ad-ly-hang-lo%e1%ba%a1t-request-v%e1%bb%9bi-claude-api","provider":"CLAUDE.VN","version":"1.0","type":"link"}