{"product_id":"sub-agent-pattern-dung-haiku-phan-tich-opus-tổng-hợp","title":"Sub-Agent Pattern — Dùng Haiku phân tích, Opus tổng hợp","description":"\n\u003cp\u003eBạn cần phân tích một tài liệu 100 trang — mỗi trang là một ảnh scan. Nếu dùng Claude Opus cho tất cả, chi phí sẽ rất cao. Nếu dùng Haiku cho tất cả, kết quả tổng hợp sẽ thiếu chiều sâu.\u003c\/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eSub-Agent Pattern\u003c\/strong\u003e giải quyết điều này: dùng model nhẹ (Haiku) làm \"công nhân\" xử lý từng đơn vị nhỏ, sau đó model mạnh (Sonnet\/Opus) đóng vai \"giám đốc\" tổng hợp kết quả thành báo cáo hoàn chỉnh.\u003c\/p\u003e\n\n\u003ch2\u003eTại sao cần phân chia model?\u003c\/h2\u003e\n\n\u003cp\u003eSo sánh chi phí xử lý 100 ảnh (mỗi ảnh ~1000 tokens input, 200 tokens output):\u003c\/p\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003eChiến lược\u003c\/th\u003e\n\u003cth\u003eChi phí ước tính\u003c\/th\u003e\n\u003cth\u003eChất lượng\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003eTất cả bằng Opus\u003c\/td\u003e\n\u003ctd\u003e~$15-20\u003c\/td\u003e\n\u003ctd\u003eTốt nhất\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eTất cả bằng Haiku\u003c\/td\u003e\n\u003ctd\u003e~$0.50-1\u003c\/td\u003e\n\u003ctd\u003eKhá tốt (thiếu synthesis)\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eHaiku worker + Sonnet synthesis\u003c\/td\u003e\n\u003ctd\u003e~$1-2\u003c\/td\u003e\n\u003ctd\u003eRất tốt (gần Opus)\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003cp\u003ePattern này \u003cstrong\u003etiết kiệm 85-90% chi phí\u003c\/strong\u003e so với dùng toàn Opus, trong khi chất lượng tổng hợp cuối vẫn đạt mức cao nhờ Sonnet\/Opus có đủ thông tin chi tiết từ Haiku workers.\u003c\/p\u003e\n\n\u003ch2\u003eKiến trúc Sub-Agent Pattern\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003e# Luong xu ly:\n#\n#  [Tai lieu goc (100 trang)]\n#          |\n#          v\n#  [Split thanh cac don vi nho]  -- Client code\n#          |\n#     _____|_____\n#    |     |     |\n#    v     v     v\n# [Haiku] [Haiku] [Haiku]  -- Sub-agents (workers)\n# Trang 1  Trang 2  ...\n#    |     |     |\n#         |    \/\n#      v   v   v\n#  [Ket qua trung gian]   -- Structured summaries\n#          |\n#          v\n#  [Sonnet\/Opus]           -- Orchestrator (synthesis)\n#          |\n#          v\n#  [Bao cao cuoi cung]\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eImplementation cơ bản\u003c\/h2\u003e\n\n\u003ch3\u003eBước 1: Worker function (Haiku)\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003eimport anthropic\nimport base64\nimport json\nimport time\nfrom pathlib import Path\nfrom concurrent.futures import ThreadPoolExecutor, as_completed\n\ndef haiku_analyze_page(\n    image_path: str,\n    page_number: int,\n    task_description: str\n) -\u0026gt; dict:\n    \"\"\"\n    Worker: Haiku phan tich mot trang\/anh.\n\n    Args:\n        image_path: Duong dan den anh\n        page_number: So trang (de tham chieu)\n        task_description: Mo ta nhiem vu (gi can trich xuat?)\n\n    Returns:\n        Dict chua ket qua phan tich\n    \"\"\"\n    with open(image_path, \"rb\") as f:\n        data = base64.standard_b64encode(f.read()).decode()\n\n    ext = Path(image_path).suffix.lower()\n    media_type = {\n        \".jpg\": \"image\/jpeg\", \".jpeg\": \"image\/jpeg\",\n        \".png\": \"image\/png\", \".webp\": \"image\/webp\"\n    }.get(ext, \"image\/jpeg\")\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-haiku-4-5\",\n        max_tokens=1024,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\"type\": \"base64\", \"media_type\": media_type, \"data\": data}\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"text\": f\"\"\"Trang {page_number}. Nhiem vu: {task_description}\n\nTra ve JSON voi cau truc nay (chi JSON, khong them gi):\n{{\n  \"page\": {page_number},\n  \"has_content\": true_or_false,\n  \"content_type\": \"text\/table\/chart\/image\/mixed\/blank\",\n  \"key_points\": [\"diem chinh 1\", \"diem chinh 2\"],\n  \"extracted_data\": \"du lieu quan trong duoc trich xuat hoac null\",\n  \"summary\": \"tom tat 1-3 cau ve noi dung trang\"\n}}\"\"\"\n                    }\n                ]\n            }\n        ]\n    )\n\n    try:\n        result = json.loads(message.content[0].text)\n    except json.JSONDecodeError:\n        result = {\n            \"page\": page_number,\n            \"has_content\": True,\n            \"summary\": message.content[0].text,\n            \"parse_error\": True\n        }\n\n    return result\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eBước 2: Orchestrator function (Sonnet\/Opus)\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef synthesize_results(\n    page_analyses: list,\n    synthesis_task: str,\n    model: str = \"claude-sonnet-4-5\"\n) -\u0026gt; str:\n    \"\"\"\n    Orchestrator: Sonnet\/Opus tong hop ket qua tu cac workers.\n\n    Args:\n        page_analyses: Danh sach ket qua tu Haiku workers\n        synthesis_task: Nhiem vu tong hop cu the\n        model: Model dung de tong hop\n\n    Returns:\n        Bao cao tong hop cuoi cung\n    \"\"\"\n    # Loc bo nhung trang trong\/khong co noi dung\n    relevant_pages = [p for p in page_analyses if p.get(\"has_content\", True)]\n\n    # Format cac ket qua trung gian\n    analyses_text = json.dumps(relevant_pages, ensure_ascii=False, indent=2)\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=model,\n        max_tokens=4096,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": f\"\"\"Ban la chuyen gia phan tich tai lieu.\nDuoi day la ket qua phan tich tung trang (tong {len(relevant_pages)} trang co noi dung):\n\n{analyses_text}\n\nNhiem vu tong hop: {synthesis_task}\n\nHay tao bao cao day du va chuyen nghiep dua tren thong tin tren.\nDam bao:\n- Su dung toan bo thong tin quan trong tu tat ca cac trang\n- Cau truc ro rang voi heading va subheading\n- Chi ra so trang nguon khi trich dan thong tin cu the\n- Nhan dien pattern hoac chu de xuyen suot tai lieu\"\"\"\n            }\n        ]\n    )\n    return message.content[0].text\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eBước 3: Pipeline hoàn chỉnh với parallel processing\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef process_document_multimodel(\n    image_paths: list,\n    extraction_task: str,\n    synthesis_task: str,\n    max_workers: int = 5,\n    synthesis_model: str = \"claude-sonnet-4-5\"\n) -\u0026gt; dict:\n    \"\"\"\n    Pipeline day du: Haiku workers + Sonnet orchestrator.\n\n    Args:\n        image_paths: Danh sach duong dan anh (theo thu tu trang)\n        extraction_task: Gi can trich xuat tu moi trang\n        synthesis_task: Ket qua cuoi cung can gi\n        max_workers: So luong Haiku workers chay song song\n        synthesis_model: Model dung de tong hop\n\n    Returns:\n        Dict chua page_analyses va final_report\n    \"\"\"\n    print(f\"Bat dau xu ly {len(image_paths)} trang voi {max_workers} workers...\")\n    start_time = time.time()\n\n    # Phase 1: Haiku workers xu ly song song\n    page_analyses = [None] * len(image_paths)\n    failed_pages = []\n\n    with ThreadPoolExecutor(max_workers=max_workers) as executor:\n        future_to_page = {\n            executor.submit(\n                haiku_analyze_page,\n                path,\n                i + 1,\n                extraction_task\n            ): i\n            for i, path in enumerate(image_paths)\n        }\n\n        completed = 0\n        for future in as_completed(future_to_page):\n            page_idx = future_to_page[future]\n            try:\n                result = future.result()\n                page_analyses[page_idx] = result\n                completed += 1\n                print(f\"  [{completed}\/{len(image_paths)}] Trang {page_idx+1} hoan thanh\")\n            except Exception as e:\n                print(f\"  LOI trang {page_idx+1}: {e}\")\n                failed_pages.append(page_idx + 1)\n                page_analyses[page_idx] = {\n                    \"page\": page_idx + 1,\n                    \"has_content\": False,\n                    \"error\": str(e)\n                }\n\n    phase1_time = time.time() - start_time\n    print(f\"\nPhase 1 hoan thanh trong {phase1_time:.1f}s\")\n    if failed_pages:\n        print(f\"Cac trang loi: {failed_pages}\")\n\n    # Phase 2: Sonnet tong hop\n    print(f\"\nPhase 2: {synthesis_model} dang tong hop...\")\n    final_report = synthesize_results(\n        page_analyses,\n        synthesis_task,\n        model=synthesis_model\n    )\n\n    total_time = time.time() - start_time\n    print(f\"Hoan thanh trong {total_time:.1f}s tong cong\")\n\n    return {\n        \"total_pages\": len(image_paths),\n        \"processed_pages\": len(image_paths) - len(failed_pages),\n        \"failed_pages\": failed_pages,\n        \"page_analyses\": page_analyses,\n        \"final_report\": final_report,\n        \"processing_time_seconds\": total_time\n    }\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eVí dụ thực tế: Phân tích hợp đồng 100 trang\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003efrom pathlib import Path\n\ndef analyze_legal_contract(pdf_path: str) -\u0026gt; str:\n    \"\"\"Phan tich hop dong phap ly nhieu trang.\"\"\"\n\n    # Buoc 1: Chuyen PDF sang anh\n    import subprocess\n    output_dir = \"contract_pages\"\n    Path(output_dir).mkdir(exist_ok=True)\n    subprocess.run([\n        \"pdftoppm\", \"-r\", \"150\", \"-png\",\n        pdf_path, f\"{output_dir}\/page\"\n    ], check=True)\n\n    page_paths = sorted(Path(output_dir).glob(\"page-*.png\"))\n    page_paths = [str(p) for p in page_paths]\n\n    # Buoc 2: Chay pipeline\n    result = process_document_multimodel(\n        image_paths=page_paths,\n        extraction_task=\"\"\"Trich xuat thong tin tu trang hop dong:\n        - Cac dieu khoan chinh (neu co)\n        - Nghia vu cua cac ben\n        - Ngay thang quan trong, deadline\n        - So tien hoac gia tri (neu co)\n        - Bat ky dieu khoan quan trong hoac rui ro nao\"\"\",\n        synthesis_task=\"\"\"Tao tom tat hop dong voi cau truc:\n        1. THONG TIN CHUNG (ten hop dong, ben ky, ngay ky, gia tri)\n        2. CAC DIEU KHOAN CHINH (danh sach theo thu tu quan trong)\n        3. NGHIA VU TUNG BEN (Ben A \/ Ben B)\n        4. NGAY THANG QUAN TRONG (deadline, gia han, v.v.)\n        5. DIEU KHOAN RUI RO DANG CHU Y\n        6. KHUYEN NGHI (cac diem can luu y hoac dam phan them)\"\"\",\n        max_workers=8,\n        synthesis_model=\"claude-opus-4-5\"  # Dung Opus cho hop dong phap ly\n    )\n\n    return result[\"final_report\"]\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eVí dụ: Phân tích báo cáo tài chính hàng quý\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003edef analyze_financial_report(pages: list) -\u0026gt; dict:\n    \"\"\"Phan tich bao cao tai chinh.\"\"\"\n\n    result = process_document_multimodel(\n        image_paths=pages,\n        extraction_task=\"\"\"Trich xuat so lieu tai chinh:\n        - Doanh thu, loi nhuan, EBITDA (neu co)\n        - Bang can doi ke toan (assets, liabilities, equity)\n        - Dong tien (operating, investing, financing)\n        - KPI nganh cu the\n        - So sanh year-over-year hoac quarter-over-quarter\n        - Cac ghi chu quan trong cua ban lanh dao\"\"\",\n        synthesis_task=\"\"\"Tao bao cao phan tich tai chinh:\n        ## Tom tat dieu hanh (Executive Summary)\n        ## Ket qua kinh doanh chinh\n        ## Phan tich xu huong\n        ## Diem manh \/ Diem yeu\n        ## Rui ro duoc neu trong bao cao\n        ## So lieu chot (bang)\"\"\",\n        max_workers=10,\n        synthesis_model=\"claude-sonnet-4-5\"\n    )\n\n    return result\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eTùy chỉnh nâng cao\u003c\/h2\u003e\n\n\u003ch3\u003eAdaptive worker selection — Tự động chọn model theo độ phức tạp\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef smart_worker(image_path: str, page_num: int, task: str) -\u0026gt; dict:\n    \"\"\"\n    Dung Haiku truoc, upgrade len Sonnet neu Haiku khong du.\n    \"\"\"\n    # Haiku thu truoc\n    result = haiku_analyze_page(image_path, page_num, task)\n\n    # Neu Haiku bao la phuc tap hoac khong chac chan\n    needs_upgrade = (\n        result.get(\"confidence\", \"high\") == \"low\" or\n        result.get(\"complex_content\", False) or\n        result.get(\"parse_error\", False)\n    )\n\n    if needs_upgrade:\n        print(f\"  Trang {page_num}: upgrade len Sonnet\")\n        # Retry bang Sonnet\n        result = sonnet_analyze_page(image_path, page_num, task)\n        result[\"upgraded\"] = True\n\n    return result\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eRetry logic cho pages bị lỗi\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef analyze_with_retry(image_path: str, page_num: int, task: str, max_retries: int = 3) -\u0026gt; dict:\n    \"\"\"Worker voi retry logic.\"\"\"\n    for attempt in range(max_retries):\n        try:\n            return haiku_analyze_page(image_path, page_num, task)\n        except anthropic.RateLimitError:\n            if attempt \u0026lt; max_retries - 1:\n                wait_time = 2 ** attempt  # Exponential backoff: 1s, 2s, 4s\n                print(f\"  Rate limit, doi {wait_time}s...\")\n                time.sleep(wait_time)\n            else:\n                raise\n        except Exception as e:\n            if attempt == max_retries - 1:\n                return {\"page\": page_num, \"error\": str(e), \"has_content\": False}\n            time.sleep(1)\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eBenchmark chi phí thực tế\u003c\/h2\u003e\n\n\u003cp\u003eDưới đây là chi phí ước tính cho tài liệu 100 trang (mỗi trang ~800 tokens ảnh, Haiku output ~300 tokens, Sonnet input tổng hợp ~30,000 tokens):\u003c\/p\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003eComponent\u003c\/th\u003e\n\u003cth\u003eModel\u003c\/th\u003e\n\u003cth\u003eTokens\u003c\/th\u003e\n\u003cth\u003eChi phí\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003e100 workers (input)\u003c\/td\u003e\n\u003ctd\u003eHaiku\u003c\/td\u003e\n\u003ctd\u003e80,000\u003c\/td\u003e\n\u003ctd\u003e~$0.02\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e100 workers (output)\u003c\/td\u003e\n\u003ctd\u003eHaiku\u003c\/td\u003e\n\u003ctd\u003e30,000\u003c\/td\u003e\n\u003ctd\u003e~$0.04\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e1 synthesis (input)\u003c\/td\u003e\n\u003ctd\u003eSonnet\u003c\/td\u003e\n\u003ctd\u003e35,000\u003c\/td\u003e\n\u003ctd\u003e~$0.10\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e1 synthesis (output)\u003c\/td\u003e\n\u003ctd\u003eSonnet\u003c\/td\u003e\n\u003ctd\u003e3,000\u003c\/td\u003e\n\u003ctd\u003e~$0.05\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003eTong cong\u003c\/strong\u003e\u003c\/td\u003e\n\u003ctd\u003e-\u003c\/td\u003e\n\u003ctd\u003e-\u003c\/td\u003e\n\u003ctd\u003e\u003cstrong\u003e~$0.21\u003c\/strong\u003e\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003cp\u003eSo sánh: Nếu dùng 100% Opus (~$15-20), pattern này \u003cstrong\u003etiết kiệm hơn 98%\u003c\/strong\u003e trong khi chất lượng synthesis vẫn cao vì Sonnet nhận đủ thông tin chi tiết từ Haiku workers.\u003c\/p\u003e\n\n\u003ch2\u003eKhi nào nên dùng pattern này?\u003c\/h2\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003eTình huống\u003c\/th\u003e\n\u003cth\u003eKhuyến nghị\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003eTài liệu 5-10 trang, cần phân tích sâu\u003c\/td\u003e\n\u003ctd\u003eDùng Sonnet\/Opus trực tiếp\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eTài liệu 20+ trang, cần tổng hợp\u003c\/td\u003e\n\u003ctd\u003eSub-Agent Pattern\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eBatch hàng trăm tài liệu khác nhau\u003c\/td\u003e\n\u003ctd\u003eSub-Agent Pattern + caching\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eReal-time, cần kết quả nhanh\u003c\/td\u003e\n\u003ctd\u003eHaiku trực tiếp\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eTài liệu pháp lý quan trọng\u003c\/td\u003e\n\u003ctd\u003eHaiku workers + Opus synthesis\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003ch2\u003eTổng kết\u003c\/h2\u003e\n\n\u003cp\u003eSub-Agent Pattern là một trong những kỹ thuật cost-optimization mạnh nhất cho vision workloads:\u003c\/p\u003e\n\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eHaiku workers\u003c\/strong\u003e — Nhanh, rẻ, chạy song song — xử lý từng đơn vị nhỏ\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eSonnet\/Opus orchestrator\u003c\/strong\u003e — Chất lượng cao, tổng hợp toàn bộ thông tin\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTiết kiệm 80-98%\u003c\/strong\u003e chi phí so với dùng model mạnh nhất cho mọi tác vụ\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eParallel processing\u003c\/strong\u003e — ThreadPoolExecutor giúp xử lý nhanh hơn nhiều\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003ePattern này áp dụng được không chỉ cho vision mà còn cho bất kỳ task nào có thể chia nhỏ thành nhiều đơn vị độc lập — text summarization, data extraction, content moderation, v.v.\u003c\/p\u003e\n\n\u003cp\u003eXem thêm: \u003ca href=\"\/collections\/nang-cao\"\u003eCrop Tool Pattern\u003c\/a\u003e để kết hợp với Sub-Agent khi cần phân tích chi tiết từng trang, và \u003ca href=\"\/collections\/san-pham\"\u003eClaude API fundamentals\u003c\/a\u003e để hiểu sâu hơn về pricing và rate limits.\u003c\/p\u003e\n","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47721835004116,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/sub-agent-pattern-dung-haiku-phan-tich-opus-t_ng-h_p.jpg?v=1774521750","url":"https:\/\/claude.vn\/products\/sub-agent-pattern-dung-haiku-phan-tich-opus-t%e1%bb%95ng-h%e1%bb%a3p","provider":"CLAUDE.VN","version":"1.0","type":"link"}