{"product_id":"dọc-biểu-dồ-dồ-thị-va-slide-deck-với-claude-vision","title":"Đọc biểu đồ, đồ thị và slide deck với Claude Vision","description":"\n\u003cp\u003eBạn nhận được một deck 40 slides cần tóm tắt, hoặc một báo cáo PDF đầy biểu đồ cần lấy số liệu? Claude Vision có thể \u003cstrong\u003eđọc và phân tích trực tiếp\u003c\/strong\u003e — không cần copy-paste thủ công hay dùng phần mềm phức tạp.\u003c\/p\u003e\n\n\u003cp\u003eBài viết này hướng dẫn cách phân tích các loại biểu đồ phổ biến, xây dựng pipeline xử lý slide deck, và trích xuất dữ liệu theo cấu trúc.\u003c\/p\u003e\n\n\u003ch2\u003ePhân tích biểu đồ cơ bản\u003c\/h2\u003e\n\n\u003cp\u003eClaude hiểu được hầu hết các loại biểu đồ thông dụng:\u003c\/p\u003e\n\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBar chart\u003c\/strong\u003e — Cột dọc\/ngang so sánh giá trị\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eLine chart\u003c\/strong\u003e — Đường xu hướng theo thời gian\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003ePie\/Donut chart\u003c\/strong\u003e — Phần trăm phân phối\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eScatter plot\u003c\/strong\u003e — Tương quan giữa hai biến\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eHeatmap\u003c\/strong\u003e — Mật độ hoặc cường độ theo vùng\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eCombo chart\u003c\/strong\u003e — Kết hợp nhiều loại\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch3\u003eHàm phân tích biểu đồ tổng quát\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003eimport anthropic\nimport base64\nimport json\n\ndef analyze_chart(image_path: str, chart_type: str = \"auto\") -\u0026gt; dict:\n    \"\"\"\n    Phan tich bieu do va trich xuat du lieu.\n\n    Args:\n        image_path: Duong dan den anh bieu do\n        chart_type: Loai bieu do (\"bar\", \"line\", \"pie\", \"scatter\", \"auto\")\n\n    Returns:\n        Dict chua thong tin phan tich\n    \"\"\"\n    with open(image_path, \"rb\") as f:\n        data = base64.standard_b64encode(f.read()).decode()\n\n    type_hint = f\"Day la bieu do loai {chart_type}. \" if chart_type != \"auto\" else \"\"\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-sonnet-4-5\",\n        max_tokens=2048,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\"type\": \"base64\", \"media_type\": \"image\/png\", \"data\": data}\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"text\": f\"\"\"{type_hint}Phan tich bieu do nay va tra ve JSON voi cau truc:\n\n{{\n  \"chart_type\": \"loai bieu do\",\n  \"title\": \"tieu de bieu do hoac null\",\n  \"x_axis\": {{\"label\": \"nhan\", \"unit\": \"don vi hoac null\"}},\n  \"y_axis\": {{\"label\": \"nhan\", \"unit\": \"don vi hoac null\"}},\n  \"series\": [\n    {{\n      \"name\": \"ten series\",\n      \"data\": [\n        {{\"label\": \"nhan x\", \"value\": gia_tri_so}}\n      ]\n    }}\n  ],\n  \"key_insights\": [\"nhan xet 1\", \"nhan xet 2\"],\n  \"trend\": \"mo ta xu huong chinh\",\n  \"data_quality\": \"cao\/trung binh\/thap - giai thich ngan\"\n}}\n\nChi tra ve JSON. Neu khong chac chan gia tri chinh xac, dung null.\"\"\"\n                    }\n                ]\n            }\n        ]\n    )\n\n    try:\n        return json.loads(message.content[0].text)\n    except json.JSONDecodeError:\n        return {\"raw_analysis\": message.content[0].text}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003ePhân tích từng loại biểu đồ\u003c\/h2\u003e\n\n\u003ch3\u003eBar Chart — Trích xuất giá trị từng cột\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef read_bar_chart(image_path: str) -\u0026gt; str:\n    \"\"\"Doc gia tri cac cot trong bar chart.\"\"\"\n    with open(image_path, \"rb\") as f:\n        data = base64.standard_b64encode(f.read()).decode()\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-sonnet-4-5\",\n        max_tokens=1024,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\"type\": \"base64\", \"media_type\": \"image\/png\", \"data\": data}\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"text\": \"\"\"Doc gia tri tung cot trong bar chart nay.\n\nTra ve bang Markdown theo format:\n| Danh muc | Gia tri | Don vi |\n|----------|---------|--------|\n\nSau do them 2-3 nhan xet ve:\n- Gia tri cao nhat \/ thap nhat\n- So sanh giua cac nhom\n- Bat ky pattern dang chu y nao\"\"\"\n                    }\n                ]\n            }\n        ]\n    )\n    return message.content[0].text\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eLine Chart — Phân tích xu hướng theo thời gian\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef analyze_trend(image_path: str) -\u0026gt; str:\n    \"\"\"Phan tich xu huong trong line chart.\"\"\"\n    with open(image_path, \"rb\") as f:\n        data = base64.standard_b64encode(f.read()).decode()\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-sonnet-4-5\",\n        max_tokens=1024,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\"type\": \"base64\", \"media_type\": \"image\/png\", \"data\": data}\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"text\": \"\"\"Phan tich xu huong trong line chart nay:\n\n1. KHOANG THOI GIAN: Tu dau den cuoi?\n2. DU LIEU CHINH: Cac diem data quan trong nhat (dinh, day, diem gap, dot bien)\n3. XU HUONG: Tang\/Giam\/On dinh? Co seasonal pattern khong?\n4. DOT BIEN: Co thoi diem nao bat thuong? Nguyen nhan co the la gi?\n5. DU BAO: Neu xu huong tiep tuc, se di theo huong nao?\n\nTra ve phan tich ngan gon, tap trung vao insight thuc te.\"\"\"\n                    }\n                ]\n            }\n        ]\n    )\n    return message.content[0].text\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003ePie Chart — Đọc phần trăm\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef read_pie_chart(image_path: str) -\u0026gt; dict:\n    \"\"\"Doc ty le phan tram trong pie chart.\"\"\"\n    with open(image_path, \"rb\") as f:\n        data = base64.standard_b64encode(f.read()).decode()\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-haiku-4-5\",\n        max_tokens=512,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\"type\": \"base64\", \"media_type\": \"image\/png\", \"data\": data}\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"text\": \"\"\"Liet ke tat ca thanh phan trong pie chart voi ty le phan tram.\nTra ve JSON: {\"segments\": [{\"label\": \"ten\", \"percentage\": so}, ...], \"total_check\": tong_cong}\nChi tra ve JSON.\"\"\"\n                    }\n                ]\n            }\n        ]\n    )\n    try:\n        return json.loads(message.content[0].text)\n    except json.JSONDecodeError:\n        return {\"raw\": message.content[0].text}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003ePhân tích Slide Deck\u003c\/h2\u003e\n\n\u003cp\u003eĐây là ứng dụng thực tế nhất — tóm tắt một bài thuyết trình nhiều slides.\u003c\/p\u003e\n\n\u003ch3\u003eBước 1: Chuyển PowerPoint\/PDF thành ảnh\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003eimport subprocess\nfrom pathlib import Path\n\ndef pptx_to_images(pptx_path: str, output_dir: str = \"slides\") -\u0026gt; list:\n    \"\"\"\n    Chuyen file PowerPoint thanh danh sach anh PNG.\n    Can cai LibreOffice va ImageMagick.\n    \"\"\"\n    Path(output_dir).mkdir(exist_ok=True)\n\n    # Buoc 1: PPTX -\u0026gt; PDF bang LibreOffice\n    subprocess.run([\n        \"libreoffice\", \"--headless\", \"--convert-to\", \"pdf\",\n        \"--outdir\", output_dir, pptx_path\n    ], check=True)\n\n    # Buoc 2: PDF -\u0026gt; PNG bang pdftoppm (poppler-utils)\n    pdf_path = Path(output_dir) \/ (Path(pptx_path).stem + \".pdf\")\n    subprocess.run([\n        \"pdftoppm\", \"-r\", \"150\", \"-png\",\n        str(pdf_path), str(Path(output_dir) \/ \"slide\")\n    ], check=True)\n\n    # Lay danh sach file PNG theo thu tu\n    slides = sorted(Path(output_dir).glob(\"slide-*.png\"))\n    return [str(s) for s in slides]\n\n\ndef pdf_to_images(pdf_path: str, output_dir: str = \"slides\", dpi: int = 150) -\u0026gt; list:\n    \"\"\"Chuyen PDF thanh danh sach anh.\"\"\"\n    Path(output_dir).mkdir(exist_ok=True)\n    subprocess.run([\n        \"pdftoppm\", \"-r\", str(dpi), \"-png\",\n        pdf_path, str(Path(output_dir) \/ \"page\")\n    ], check=True)\n    pages = sorted(Path(output_dir).glob(\"page-*.png\"))\n    return [str(p) for p in pages]\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eBước 2: Phân tích từng slide\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef analyze_slide(image_path: str, slide_number: int) -\u0026gt; dict:\n    \"\"\"Phan tich mot slide don le.\"\"\"\n    with open(image_path, \"rb\") as f:\n        data = base64.standard_b64encode(f.read()).decode()\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-haiku-4-5\",  # Haiku du toc do cho batch slides\n        max_tokens=512,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\"type\": \"base64\", \"media_type\": \"image\/png\", \"data\": data}\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"text\": f\"\"\"Day la slide {slide_number} cua mot bai thuyet trinh.\nPhan tich ngan gon, tra ve JSON:\n{{\n  \"slide_number\": {slide_number},\n  \"type\": \"title\/content\/chart\/table\/image\/blank\",\n  \"title\": \"tieu de slide hoac null\",\n  \"key_points\": [\"diem chinh 1\", \"diem chinh 2\"],\n  \"has_chart\": true_or_false,\n  \"has_table\": true_or_false,\n  \"summary\": \"tom tat 1-2 cau\"\n}}\nChi tra ve JSON.\"\"\"\n                    }\n                ]\n            }\n        ]\n    )\n    try:\n        return json.loads(message.content[0].text)\n    except json.JSONDecodeError:\n        return {\"slide_number\": slide_number, \"raw\": message.content[0].text}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eBước 3: Tổng hợp toàn bộ deck\u003c\/h3\u003e\n\n\u003cpre\u003e\u003ccode\u003edef summarize_deck(slide_analyses: list) -\u0026gt; str:\n    \"\"\"\n    Tong hop phan tich toan bo deck thanh bao cao.\n    Dung Sonnet de synthesis (chat luong cao hon Haiku).\n    \"\"\"\n    # Format tat ca phan tich slide thanh text\n    slides_summary = json.dumps(slide_analyses, ensure_ascii=False, indent=2)\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-sonnet-4-5\",\n        max_tokens=2048,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": f\"\"\"Duoi day la phan tich tung slide cua mot bai thuyet trinh.\nHay tao bao cao tong hop gom:\n\n## 1. Tong quan\n- Chu de chinh cua bai thuyet trinh\n- So slides va cau truc tong the\n\n## 2. Noi dung chinh\n- Cac y chinh theo tung section\n- Data \/ so lieu quan trong\n\n## 3. Bieu do va du lieu\n- Tom tat cac bieu do co trong bai (neu co)\n\n## 4. Ket luan\n- Message chinh ma dien gia muon truyen dat\n\n---\nDu lieu phan tich cac slides:\n{slides_summary}\"\"\"\n            }\n        ]\n    )\n    return message.content[0].text\n\n\n# Pipeline hoan chinh\ndef process_presentation(file_path: str) -\u0026gt; str:\n    \"\"\"\n    Xu ly day du mot bai thuyet trinh PPTX\/PDF.\n    Tra ve bao cao tong hop.\n    \"\"\"\n    import time\n\n    # Xac dinh loai file va chuyen thanh anh\n    if file_path.endswith(\".pdf\"):\n        slide_paths = pdf_to_images(file_path)\n    else:\n        slide_paths = pptx_to_images(file_path)\n\n    print(f\"Tim thay {len(slide_paths)} slides\")\n\n    # Phan tich tung slide (Haiku - nhanh va re)\n    analyses = []\n    for i, path in enumerate(slide_paths):\n        print(f\"Dang phan tich slide {i+1}\/{len(slide_paths)}...\")\n        analysis = analyze_slide(path, i + 1)\n        analyses.append(analysis)\n        time.sleep(0.3)  # Rate limiting\n\n    # Tong hop bang Sonnet\n    print(\"Dang tao bao cao tong hop...\")\n    report = summarize_deck(analyses)\n    return report\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eTrích xuất bảng số liệu từ ảnh\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003edef extract_table_from_image(image_path: str, format: str = \"markdown\") -\u0026gt; str:\n    \"\"\"\n    Trich xuat bang so lieu tu anh.\n\n    Args:\n        format: \"markdown\", \"csv\", hoac \"json\"\n    \"\"\"\n    with open(image_path, \"rb\") as f:\n        data = base64.standard_b64encode(f.read()).decode()\n\n    format_instructions = {\n        \"markdown\": \"Tra ve bang Markdown voi header ro rang.\",\n        \"csv\": \"Tra ve CSV (dau phay phan cach), dong dau la header.\",\n        \"json\": 'Tra ve JSON array: [{\"col1\": val1, \"col2\": val2, ...}, ...]'\n    }\n\n    client = anthropic.Anthropic()\n    message = client.messages.create(\n        model=\"claude-sonnet-4-5\",\n        max_tokens=2048,\n        messages=[\n            {\n                \"role\": \"user\",\n                \"content\": [\n                    {\n                        \"type\": \"image\",\n                        \"source\": {\"type\": \"base64\", \"media_type\": \"image\/png\", \"data\": data}\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"text\": f\"\"\"Trich xuat toan bo du lieu bang trong hinh anh nay.\n{format_instructions.get(format, format_instructions[\"markdown\"])}\nDam bao:\n- Giu nguyen so lieu chinh xac\n- Khong them hoac bot hang\/cot\n- Xu ly merge cells bang cach lap lai gia tri\nChi tra ve du lieu, khong them nhan xet.\"\"\"\n                    }\n                ]\n            }\n        ]\n    )\n    return message.content[0].text\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eVí dụ thực tế: Báo cáo kinh doanh\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003edef analyze_business_report(pdf_path: str) -\u0026gt; dict:\n    \"\"\"Phan tich bao cao kinh doanh PDF day du.\"\"\"\n\n    # Chuyen PDF sang anh\n    page_paths = pdf_to_images(pdf_path, dpi=200)  # DPI cao hon cho text nho\n\n    results = {\n        \"pages\": len(page_paths),\n        \"charts\": [],\n        \"tables\": [],\n        \"key_metrics\": [],\n        \"summary\": \"\"\n    }\n\n    client = anthropic.Anthropic()\n\n    for i, path in enumerate(page_paths):\n        with open(path, \"rb\") as f:\n            data = base64.standard_b64encode(f.read()).decode()\n\n        # Phan tich tung trang\n        response = client.messages.create(\n            model=\"claude-haiku-4-5\",\n            max_tokens=1024,\n            messages=[{\n                \"role\": \"user\",\n                \"content\": [\n                    {\"type\": \"image\",\n                     \"source\": {\"type\": \"base64\", \"media_type\": \"image\/png\", \"data\": data}},\n                    {\"type\": \"text\",\n                     \"text\": f\"\"\"Trang {i+1} cua bao cao kinh doanh. Phan tich JSON:\n{{\n  \"page\": {i+1},\n  \"contains_chart\": bool,\n  \"contains_table\": bool,\n  \"key_metrics\": [\"KPI hoac so lieu quan trong\"],\n  \"chart_description\": \"mo ta bieu do neu co, null neu khong\",\n  \"section_title\": \"tieu de section hoac null\"\n}}\"\"\"}\n                ]\n            }]\n        )\n\n        try:\n            page_data = json.loads(response.content[0].text)\n            if page_data.get(\"contains_chart\"):\n                results[\"charts\"].append(page_data)\n            if page_data.get(\"contains_table\"):\n                results[\"tables\"].append(page_data)\n            results[\"key_metrics\"].extend(page_data.get(\"key_metrics\", []))\n        except Exception:\n            pass\n\n    return results\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eGiới hạn và lưu ý\u003c\/h2\u003e\n\n\u003ch3\u003eĐộ chính xác số liệu\u003c\/h3\u003e\n\n\u003cp\u003eClaude đọc số liệu từ biểu đồ với độ chính xác khoảng \u003cstrong\u003e80-95%\u003c\/strong\u003e tùy chất lượng ảnh và loại biểu đồ. Với bar chart có nhãn số rõ ràng: rất chính xác. Với pie chart không có nhãn phần trăm: có thể sai 3-5%.\u003c\/p\u003e\n\n\u003cp\u003eLuôn yêu cầu Claude báo cáo mức độ chắc chắn:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003e# Them vao prompt\n\"Voi moi gia tri, cho biet muc do tu tin: [Chinh xac \/ Uoc tinh \/ Khong ro]\"\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eBiểu đồ 3D\u003c\/h3\u003e\n\n\u003cp\u003eBiểu đồ 3D khó đọc hơn biểu đồ 2D — cả với người và AI. Nếu có thể, dùng ảnh 2D flat view.\u003c\/p\u003e\n\n\u003ch3\u003eNhiều biểu đồ trên một trang\u003c\/h3\u003e\n\n\u003cp\u003eNếu một slide có nhiều biểu đồ nhỏ, dùng Crop Tool để yêu cầu Claude phân tích từng biểu đồ riêng.\u003c\/p\u003e\n\n\u003ch2\u003eTổng kết\u003c\/h2\u003e\n\n\u003cp\u003eClaude Vision là công cụ mạnh để tự động hóa việc đọc và tổng hợp thông tin từ báo cáo và trình bày:\u003c\/p\u003e\n\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBar\/Line\/Pie chart\u003c\/strong\u003e — Trích xuất số liệu và insight tự động\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eSlide deck\u003c\/strong\u003e — Pipeline Haiku (phân tích từng slide) + Sonnet (tổng hợp)\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBảng số liệu\u003c\/strong\u003e — Xuất ra Markdown, CSV, hoặc JSON\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBáo cáo PDF\u003c\/strong\u003e — Tách trang, phân tích, tổng hợp\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cp\u003eTiếp theo: Xem \u003ca href=\"\/collections\/nang-cao\"\u003eSub-Agent Pattern\u003c\/a\u003e để tối ưu chi phí khi xử lý tài liệu lớn với hàng chục đến hàng trăm trang.\u003c\/p\u003e\n","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47721834971348,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/d_c-bi_u-d_-d_-th_-va-slide-deck-v_i-claude-vision.jpg?v=1774521747","url":"https:\/\/claude.vn\/products\/d%e1%bb%8dc-bi%e1%bb%83u-d%e1%bb%93-d%e1%bb%93-th%e1%bb%8b-va-slide-deck-v%e1%bb%9bi-claude-vision","provider":"CLAUDE.VN","version":"1.0","type":"link"}