Danh sách bài viết

Bài 32: Anthropic Claude API — alternative với context dài

Bài 31 đã đi qua OpenAI API. Bài này gói gọn provider lớn thứ hai — Anthropic Claude API. Trọng tâm: setup SDK Python, first call với client.messages.create(), ba khác biệt cấu trúc với OpenAI (system message tách thành parameter riêng, max_tokens bắt buộc, response là list content blocks), model lineup 2025-2026 (Opus / Sonnet / Haiku 4.x, Claude 3.7 thinking, claude-opus-4-7 cho code), vision và PDF input, tool use cơ bản, streaming, prompt caching ephemeral, Batch API, extended thinking với budget_tokens, rate limit theo tier, error handling, AsyncAnthropic, cost 05/2026, framework chọn giữa OpenAI và Anthropic, và LiteLLM làm interface unified.

25/05/2026
13 phút đọc
0 lượt xem
1

Mục tiêu bài học

Sau bài này, bạn cần:

  • Đăng ký Anthropic console, tạo API key, set ANTHROPIC_API_KEY và nạp credit.
  • Gọi được client.messages.create() với claude-opus-4-7 và lấy text từ message.content[0].text.
  • Phân biệt ba khác biệt cấu trúc với OpenAI: system tách parameter, max_tokens required, response là list content blocks.
  • Biết model lineup 2025-2026 (Opus / Sonnet / Haiku 4.x, Claude 3.7 thinking, claude-opus-4-7 cho code) và mỗi tier dùng khi nào.
  • Dùng được vision (image base64), document (PDF), tool use cơ bản, streaming.
  • Bật prompt caching với cache_control={"type": "ephemeral"} và biết khi nào nó hoà vốn.
  • Hiểu extended thinking — thinking={"type": "enabled", "budget_tokens": ...} — và trade-off latency / cost.
  • Xử lý error RateLimitError, APITimeoutError, APIError.
  • So sánh chi phí và năng lực OpenAI vs Anthropic cho task cụ thể; dùng LiteLLM để switch provider qua một interface.

Bài này tiếp thẳng Bài 31 (OpenAI API) và làm nền cho Bài 33 (Streaming response — deep-dive).

2

Anthropic — vị trí trong landscape

Anthropic là provider commercial LLM lớn thứ hai (sau OpenAI) tính theo doanh thu API năm 2025-2026, founded bởi cựu nhân viên OpenAI (Dario và Daniela Amodei, 2021). Series model là Claude. Điểm hay được nhắc trong tài liệu chính thức và benchmark:

  • Context dài: 200K token là mặc định cho mọi model Claude 3.5+ trên public API. Một số tier có 1M context (Claude Sonnet 4 1M qua API public từ 2025, Claude Opus 4 1M cho Tier 4 / enterprise).
  • Safety / alignment: Anthropic phát triển kỹ thuật RLHF và Constitutional AI (paper 2022, arXiv 2212.08073). Model có xu hướng từ chối các yêu cầu rõ ràng có hại; cũng có cost: đôi khi over-refusal cho prompt vô hại.
  • Coding: Claude Sonnet 3.5 và họ Claude 4 thường top benchmark code (SWE-bench Verified, HumanEval). Tool Claude Code (CLI, 2024-) dùng claude-opus-4-7.
  • Tool use: training có mục tiêu tool use trực tiếp, parse rate JSON argument cao.
  • Long-form writing: phong cách output dài, có cấu trúc, hay được dùng cho draft document.

Đây là quan sát công khai từ doc và benchmark độc lập, không phải tuyên bố tuyệt đối — task cụ thể vẫn cần A/B test. Bài này tập trung mặt API, không so sánh chất lượng.

3

Setup account, API key, env

  1. Vào console.anthropic.com, đăng ký bằng email hoặc Google. Xác thực số điện thoại nếu được yêu cầu.
  2. Tab API KeysCreate Key. Đặt tên (ví dụ laptop-dev), copy ngay — key chỉ hiện một lần.
  3. Tab Plans & Billing → nạp credit (Anthropic dùng prepaid credit, không bill cuối tháng cho dev tier). Mức tối thiểu thường $5; lượng nạp ảnh hưởng tier rate limit (xem bước 19).
  4. Set env trong shell:
    export ANTHROPIC_API_KEY="sk-ant-..."
    Hoặc cho zsh / fish lưu vào ~/.zshrc, ~/.config/fish/config.fish.
  5. Production: dùng secrets manager (AWS Secrets Manager, GCP Secret Manager, Doppler). Tuyệt đối không commit key vào git.

SDK Python tự đọc ANTHROPIC_API_KEY. Nếu cần override: Anthropic(api_key="sk-ant-...").

4

Cài SDK Python

pip install anthropic

Package anthropic trên PyPI là SDK chính thức. Bản 0.40+ (cuối 2024-2025) đã hỗ trợ extended thinking, prompt caching, batch, tool use, streaming. Kiểm tra version:

python -c "import anthropic; print(anthropic.__version__)"

Ngoài Python, Anthropic cũng có SDK chính thức cho TypeScript / Node (@anthropic-ai/sdk), Go, Java, Ruby. Bài này dùng Python; pattern các SDK khác tương đương vì REST API chung.

5

First call — Messages API

from anthropic import Anthropic

client = Anthropic()   # đọc ANTHROPIC_API_KEY từ env

message = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Xin chào"},
    ],
)
print(message.content[0].text)

Bốn điểm cần để ý ngay:

  • Endpoint là messages.create() (không phải chat.completions.create() như OpenAI).
  • max_tokens là tham số bắt buộc — giới hạn số token model sinh ra. Bỏ → BadRequestError.
  • messages chỉ chứa role userassistant. Role system không nằm trong list — xem bước 8.
  • Text response truy cập qua message.content[0].text. content luôn là list (xem bước 11).
6

Ba khác biệt cấu trúc với OpenAI

So sánh nhanh để code chuyển từ OpenAI sang không bị bất ngờ:

                          OpenAI                          Anthropic
─────────────────────────────────────────────────────────────────────────────────
Endpoint            chat.completions.create()         messages.create()
System message      {"role": "system", ...} trong     parameter riêng system="..."
                    list messages
max_tokens          optional (default 4096+)          REQUIRED
Lấy text            response.choices[0]               message.content[0].text
                    .message.content
Stop reason         response.choices[0].finish_reason  message.stop_reason
Usage               response.usage.prompt_tokens /    message.usage.input_tokens /
                    completion_tokens                  output_tokens
Tool call           response.choices[0].message       content block với
                    .tool_calls                       type="tool_use"

Phần lớn pattern còn lại (multi-turn, role user / assistant, multimodal content list) tương tự nhau về tinh thần, chỉ khác key/cấu trúc dict.

7

Model lineup 2025-2026

Đặt theo ba size tier như cách Anthropic dùng từ Claude 3:

  • Claude Opus 4.x — flagship. Năng lực reasoning, coding, math cao nhất; latency và giá cao nhất. Dùng cho task khó, draft dài, agent quan trọng.
  • Claude Sonnet 4.x — balanced. Cân bằng cost / latency / quality. Là tier mặc định cho production app phổ thông.
  • Claude Haiku 4.x — fast, cheap. Phù hợp classification, extraction đơn giản, bulk processing.
  • Claude 3.7 Sonnet (thinking) — bản reasoning có chế độ extended thinking (xem bước 18). Phù hợp math, code khó, multi-step planning.
  • Claude code (claude-opus-4-7) — variant tối ưu cho code (driver của Claude Code CLI). Có 1M context option. Dùng cho code generation / refactor / agent code-base.

Naming convention thực tế: ID model trên API là string dạng claude-opus-4-7, claude-sonnet-4-..., claude-haiku-4-..., claude-3-7-sonnet-.... Anthropic định kỳ release alias -latest; production khuyến nghị pin ID đầy đủ để tránh hành vi đổi ngầm.

8

System message — parameter riêng

message = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    system="You are a Python expert. Trả lời ngắn, code có comment.",
    messages=[
        {"role": "user", "content": "Explain decorator"},
    ],
)
print(message.content[0].text)

Ý nghĩa:

  • system là string (hoặc list content block — xem bước 16 cho cache). Không phải dict role/content.
  • Đặt persona, hướng dẫn format, ngôn ngữ. Tương đương {"role": "system", ...} của OpenAI.
  • System áp dụng cho toàn cuộc hội thoại; không cần lặp lại mỗi turn.

Khi port code từ OpenAI: bóc message đầu tiên có role == "system" ra thành system parameter, phần còn lại đẩy vào messages.

9

Multi-turn messages

messages = [
    {"role": "user",      "content": "Hello"},
    {"role": "assistant", "content": "Hi! How can I help?"},
    {"role": "user",      "content": "What's Python?"},
]

message = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=512,
    messages=messages,
)

Hai ràng buộc Anthropic ép từ đầu:

  • Message đầu phải có role: "user". Không bắt đầu bằng assistant.
  • Role phải alternate: user → assistant → user → assistant... Hai message cùng role liên tiếp → BadRequestError.

API Anthropic không lưu hội thoại — bạn phải tự append response vào list và gửi lại cả history mỗi turn (giống OpenAI). Để giảm token: tổng kết các turn cũ thành đoạn ngắn ở system prompt sau N message, hoặc bật prompt caching cho prefix cố định (bước 16).

10

Parameters chính

  • model (required) — ID model.
  • max_tokens (required) — tối đa token output sinh ra (không tính input).
  • system — string hoặc list block.
  • messages — list dict role + content.
  • temperature — 0.0 đến 1.0, default 1.0. Khác OpenAI (0-2). 0 = deterministic gần như, 1 = sampling rộng.
  • top_p — nucleus sampling. Không khuyến nghị set chung với temperature (chọn một).
  • top_k — chỉ chọn top-k token mỗi step. Hiếm dùng app thường.
  • stop_sequences — list string; model dừng ngay khi sinh ra một trong các string này. Để parse có ranh giới, ví dụ ["\n\nHuman:", "END"].
  • metadata — dict đính kèm cho usage tracking; có user_id để Anthropic phát hiện abuse.
  • tools, tool_choice — bước 14.
  • thinking — bước 18.
  • stream — bool; dùng kèm helper messages.stream() tiện hơn (bước 15).

Sampling theory chi tiết (temperature / top-p / top-k) đã đi qua ở Bài 30 — không lặp lại.

11

Response object — content blocks

Output object có dạng:

message.id              # "msg_01..." — id duy nhất, dùng cho log
message.model           # "claude-opus-4-7"
message.role            # "assistant"
message.content         # list[ContentBlock]
message.stop_reason     # "end_turn" | "max_tokens" | "stop_sequence" | "tool_use"
message.stop_sequence   # string nếu dừng vì stop_sequences, None nếu khác
message.usage.input_tokens
message.usage.output_tokens
message.usage.cache_creation_input_tokens   # khi dùng prompt caching
message.usage.cache_read_input_tokens

message.content là list các block, mỗi block có type:

  • type == "text" → có .text: chuỗi response thuần.
  • type == "tool_use" → có .name, .input, .id: model gọi tool.
  • type == "thinking" (khi bật extended thinking) → có .thinking: nội dung reasoning nội bộ.

Khi không bật tool và không bật thinking, thường chỉ có một block text duy nhất → message.content[0].text là toàn bộ response. Khi có tool / thinking, phải loop qua content và xử lý theo type:

for block in message.content:
    if block.type == "text":
        print("TEXT:", block.text)
    elif block.type == "tool_use":
        print("TOOL:", block.name, block.input)

stop_reason đáng để check trong production: max_tokens nghĩa là response bị cắt — cần tăng max_tokens hoặc gửi tiếp turn để model viết nốt.

12

Vision — image input

Mọi model Claude 3+ đều multimodal — chấp nhận ảnh trong content list:

import base64
from pathlib import Path

img_bytes = Path("photo.jpg").read_bytes()
b64 = base64.standard_b64encode(img_bytes).decode("utf-8")

message = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "image",
                "source": {
                    "type": "base64",
                    "media_type": "image/jpeg",
                    "data": b64,
                },
            },
            {"type": "text", "text": "What's in this image?"},
        ],
    }],
)
print(message.content[0].text)

Một số chi tiết:

  • media_type: image/jpeg, image/png, image/gif, image/webp.
  • Có thể truyền "source": {"type": "url", "url": "https://..."} nếu Anthropic được phép fetch URL.
  • Một message có thể chứa nhiều ảnh — Claude sẽ refer theo thứ tự xuất hiện. Mỗi ảnh tính theo công thức token Anthropic công bố trong doc Vision.
13

PDF / document input

Từ Claude 3.5 Sonnet (2024) Anthropic hỗ trợ block document nhận PDF trực tiếp:

pdf_bytes = Path("paper.pdf").read_bytes()
pdf_b64 = base64.standard_b64encode(pdf_bytes).decode("utf-8")

message = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=2048,
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "document",
                "source": {
                    "type": "base64",
                    "media_type": "application/pdf",
                    "data": pdf_b64,
                },
            },
            {"type": "text", "text": "Tóm tắt main contribution của paper."},
        ],
    }],
)

Hành vi server-side: Anthropic extract text + parse layout, đồng thời gửi từng trang dưới dạng ảnh nội bộ cho model — Claude vừa thấy text vừa thấy layout (table, figure). Token tính theo nội dung extract + ảnh.

Giới hạn:

  • Mỗi PDF tối đa 32 MB và 100 trang (kiểm tra doc Anthropic Documents cập nhật).
  • Không support file Office (docx, xlsx) trực tiếp — phải convert sang PDF trước.
14

Tool use cơ bản

Khai báo tool và để Claude tự quyết khi nào gọi:

tools = [{
    "name": "get_weather",
    "description": "Get current weather for a city",
    "input_schema": {
        "type": "object",
        "properties": {
            "city": {"type": "string",
                     "description": "City name, e.g. Hanoi"},
        },
        "required": ["city"],
    },
}]

message = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "Weather in Hanoi?"}],
)

for block in message.content:
    if block.type == "tool_use":
        print(block.name, block.input)
        # → "get_weather", {"city": "Hanoi"}

Khi stop_reason == "tool_use", bước tiếp theo:

  1. Chạy hàm Python tương ứng (gọi API weather thật).
  2. Append một message role: "user" với content block type: "tool_result" kèm tool_use_idcontent (kết quả).
  3. Gọi lại messages.create() với history mới — Claude sẽ tổng hợp câu trả lời từ kết quả tool.

Pattern đầy đủ (agent loop, multi-tool, parallel tool call) sẽ deep-dive ở Bài 42+ trong nhóm Agents.

15

Streaming response

with client.messages.stream(
    model="claude-opus-4-7",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Viết hàm Python fibonacci."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

final = stream.get_final_message()
print("\nusage:", final.usage)

SDK cung cấp context manager messages.stream(...) tiện hơn nhiều so với set stream=True và xử lý SSE thô. Cơ chế chi tiết (event message_start, content_block_delta, message_stop, backpressure, partial JSON streaming cho tool argument) sẽ là nội dung Bài 33.

16

Prompt caching — ephemeral

Prompt caching (GA 2024) cho phép cache prefix cố định để các request sau dùng lại — tính cost giảm đáng kể cho phần cached. Cách dùng: đánh dấu cache_control={"type": "ephemeral"} trên block muốn cache.

long_doc = open("knowledge_base.txt").read()   # ví dụ 50K token

message = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=512,
    system=[
        {"type": "text",
         "text": "You are a customer support assistant."},
        {"type": "text",
         "text": long_doc,
         "cache_control": {"type": "ephemeral"}},
    ],
    messages=[{"role": "user", "content": "Refund policy là gì?"}],
)
print(message.usage.cache_creation_input_tokens)   # lần đầu = tạo cache
print(message.usage.cache_read_input_tokens)       # lần sau = đọc cache

Cơ chế:

  • Prefix được cache trong vài phút (TTL mặc định ~5 phút, có option tăng).
  • Cache hit → cost cho phần cache ~10% giá input thường (Anthropic công bố discount ~90% cho cache read).
  • Cache miss đầu tiên có cost cao hơn input thường ~25% (cost ghi cache).
  • Hoà vốn: khoảng 2-3 request reuse cache trong TTL. Trên đó, càng reuse càng rẻ.

Use case điển hình: system prompt 10K-100K token (knowledge base, instruction dài), nhiều user turn liên tiếp. Trong agent loop nhiều step trên cùng context, đặt cache marker ở cuối prefix cố định.

17

Batch API

Cho workload không cần realtime (batch labeling, embedding bulk text, eval offline), Anthropic có Message Batches API: submit nhiều request, Anthropic xử lý async trong tối đa 24 giờ, giá rẻ hơn ~50% so với realtime.

batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": "task-1",
            "params": {
                "model": "claude-haiku-4",
                "max_tokens": 256,
                "messages": [{"role": "user", "content": "Tóm tắt: ..."}],
            },
        },
        # ... đến 10 000 request mỗi batch
    ],
)
print(batch.id, batch.processing_status)

# Poll cho đến khi processing_status == "ended"
results = client.messages.batches.results(batch.id)
for r in results:
    print(r.custom_id, r.result.type)   # "succeeded" | "errored"

Khái niệm tương tự Batch API OpenAI (đã đi qua ở Bài 31). Lưu ý: latency có thể tới 24h, không phù hợp cho online inference.

18

Extended Thinking — Claude 3.7+

Extended Thinking là chế độ Claude sinh phần reasoning nội bộ trước khi trả response cuối — kỹ thuật tương đương o-series OpenAI. Bật bằng tham số thinking:

message = client.messages.create(
    model="claude-3-7-sonnet-latest",
    max_tokens=2000,
    thinking={
        "type": "enabled",
        "budget_tokens": 8000,
    },
    messages=[
        {"role": "user",
         "content": "Chứng minh tổng 3 góc tam giác = 180 độ."},
    ],
)

for block in message.content:
    if block.type == "thinking":
        print("[reasoning]", block.thinking[:200])
    elif block.type == "text":
        print("[answer]", block.text)

Ý nghĩa các trường:

  • budget_tokens: trần số token reasoning model được phép sinh. Phải nhỏ hơn max_tokens.
  • Token reasoning được tính vào output token thường (không có giá riêng).
  • Block thinking phải được giữ lại nguyên vẹn khi gửi lại trong multi-turn (Anthropic verify chữ ký nội bộ). Nếu cắt bớt → API reject.

Trade-off: tăng budget_tokens → accuracy task khó cao hơn, latency và cost cùng tăng. Task đơn giản thường không cần thinking; bật khi task math, code khó, multi-step planning.

19

Rate limits và tier

Anthropic dùng hệ thống usage tier 1-4:

  • Tier 1 mặc định sau khi nạp credit. RPM (request / phút), TPM (token / phút), TPD (token / ngày) thấp.
  • Sau khoảng thời gian sử dụng + tổng chi tiêu vượt ngưỡng, account tự lên tier 2, 3, 4. Mỗi tier limit nhân lên 4-10 lần.
  • Limit khác nhau theo model — Opus thường thấp hơn Haiku.
  • Một số feature (Claude Opus 4 1M context) yêu cầu tier cao hoặc enterprise plan.

Console Anthropic có dashboard hiển thị tier hiện tại và limit từng model. Khi vượt: API trả RateLimitError với retry-after header — nên đọc và backoff đúng giây thay vì retry ngay.

20

Error handling

from anthropic import (
    APIError, APITimeoutError, RateLimitError,
    APIConnectionError, BadRequestError, AuthenticationError,
)

try:
    message = client.messages.create(
        model="claude-opus-4-7",
        max_tokens=1024,
        messages=[{"role": "user", "content": "..."}],
    )
except RateLimitError as e:
    print("Rate limited, retry after:", e.response.headers.get("retry-after"))
except APITimeoutError:
    print("Timeout — retry với timeout cao hơn")
except APIConnectionError:
    print("Network — kiểm tra mạng / proxy")
except BadRequestError as e:
    print("Request sai schema:", e.message)
except AuthenticationError:
    print("API key sai hoặc revoke")
except APIError as e:
    print(f"Lỗi khác từ API: {e}")

SDK đã có retry tự động cho RateLimitErrorAPIConnectionError với exponential backoff (mặc định 2 retry). Cấu hình:

client = Anthropic(
    max_retries=4,
    timeout=60.0,    # giây
)
21

AsyncAnthropic

import asyncio
from anthropic import AsyncAnthropic

client = AsyncAnthropic()

async def ask(prompt: str) -> str:
    message = await client.messages.create(
        model="claude-haiku-4",
        max_tokens=256,
        messages=[{"role": "user", "content": prompt}],
    )
    return message.content[0].text

async def main():
    results = await asyncio.gather(
        ask("Capital of Japan?"),
        ask("Capital of France?"),
        ask("Capital of Vietnam?"),
    )
    print(results)

asyncio.run(main())

Pattern này phù hợp khi cần xử lý song song nhiều prompt độc lập (batch nhỏ, FastAPI endpoint, agent fan-out). Vẫn bị chặn bởi rate limit RPM/TPM, nên kết hợp với semaphore (asyncio.Semaphore(N)) để giới hạn concurrent.

22

Cost 05/2026

Giá liệt kê dưới đây là khoảng tham chiếu thời điểm soạn bài (05/2026), trước khi áp prompt caching và batch discount. Trước khi tính cost prod, kiểm tra trang pricing chính thức cho con số mới nhất.

Model                  Input $/1M token   Output $/1M token
─────────────────────────────────────────────────────────────────
Claude Haiku 4.x       ~$0.25 – $0.80     ~$1 – $4
Claude Sonnet 4.x      ~$3                ~$15
Claude Opus 4.x        ~$15               ~$75

Modifier áp lên giá gốc:

  • Prompt cache read: ~10% giá input (discount ~90%).
  • Prompt cache write: ~125% giá input (lần đầu).
  • Batch API: ~50% giá realtime cho cả input và output.
  • Vision và document tính token theo công thức trong doc; ảnh ~1500-3000 token tùy size.

So với OpenAI cùng tier (đã thấy ở Bài 31): Haiku ngang giá GPT-4o-mini, Sonnet ngang GPT-4o, Opus đắt hơn GPT-4o. Khoảng cách giá thay đổi vài tháng một lần.

23

OpenAI vs Anthropic — chọn cái nào

Không có "tốt hơn" chung. Khung quyết định theo trục:

Trục                    OpenAI                       Anthropic
─────────────────────────────────────────────────────────────────────────
Coding bench            GPT-4o / o-series khá         Claude Sonnet 4 /
                                                     Opus 4 thường dẫn top
Reasoning (math, plan)  o-series                      Claude 3.7 thinking
Multimodal              GPT-4o (image, audio, video) Claude (image, PDF
                                                     document)
Context window          1M (GPT-4.1, 2025+)           200K mặc định, 1M có
                                                     cho Sonnet 4 / Opus 4
Ecosystem               Assistants API, Files,        Tool use, Messages,
                        Realtime, Sora                Claude Code CLI
Cost Haiku-tier         GPT-4o-mini ngang Haiku       Haiku ngang GPT-4o-mini
Cost flagship           GPT-4o < Claude Opus 4         Claude Opus 4 đắt nhất
Latency P50             Tương đương                    Tương đương
Safety / refusal        Trung tính                    Refusal mạnh hơn cho
                                                     prompt edge-case

Pattern thực tế thường gặp trong app prod:

  • Default routing: Sonnet 4 hoặc GPT-4o cho task chung; Haiku / GPT-4o-mini cho bulk.
  • Fallback cross-provider khi một bên down — đặc biệt với app SLA cao.
  • Task coding agent: Claude (Sonnet 4 / claude-opus-4-7) đang là default phổ biến trong cộng đồng.
  • Task multimodal voice/realtime: OpenAI có lợi thế nhờ Realtime API.

Không cần "thề" một provider. Code App nên design tách abstraction giữa app và LLM client.

24

LiteLLM — interface unified

litellm (Berri AI, OSS từ 2023) gói >100 provider sau một interface duy nhất giống OpenAI:

from litellm import completion

resp = completion(
    model="claude-opus-4-7",
    messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)

resp = completion(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)

Ý nghĩa:

  • Cùng signature kiểu OpenAI; LiteLLM tự map sang Anthropic Messages API ở bên dưới (chuyển system message, set max_tokens, parse content blocks).
  • Hỗ trợ streaming, tool use, vision với mapping tương ứng.
  • LiteLLM Proxy: chạy như server gateway, route theo cost/latency, retry / fallback giữa provider, observability built-in.

Khi nào dùng:

  • App đa provider, không muốn duy trì hai code path.
  • Cần A/B test nhiều model bằng cách đổi string.
  • Cần proxy tập trung cho budget, log, retry.

Nhược điểm: phụ thuộc thêm một layer, đôi khi feature mới của provider lên LiteLLM chậm vài tuần. Production critical thường vẫn gọi SDK gốc cho path nóng.

25

Code Python tổng hợp

(a) First call:

from anthropic import Anthropic

client = Anthropic()
m = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=512,
    messages=[{"role": "user", "content": "Xin chào"}],
)
print(m.content[0].text)

(b) System message + multi-turn:

history = [
    {"role": "user",      "content": "Tôi đang học Python."},
    {"role": "assistant", "content": "OK, bạn đang ở mức nào?"},
    {"role": "user",      "content": "Mới biết list và dict."},
]

m = client.messages.create(
    model="claude-sonnet-4",
    max_tokens=512,
    system="Bạn là tutor Python, trả lời ngắn gọn, có ví dụ.",
    messages=history,
    temperature=0.3,
)
print(m.content[0].text)

(c) Vision:

import base64
from pathlib import Path

img_b64 = base64.standard_b64encode(
    Path("chart.png").read_bytes()
).decode()

m = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=512,
    messages=[{
        "role": "user",
        "content": [
            {"type": "image",
             "source": {"type": "base64",
                        "media_type": "image/png",
                        "data": img_b64}},
            {"type": "text", "text": "Mô tả chart này."},
        ],
    }],
)
print(m.content[0].text)

(d) Error handling production:

from anthropic import APIError, RateLimitError, APITimeoutError
import time

def ask_with_retry(prompt: str, max_retry: int = 3) -> str:
    for attempt in range(max_retry):
        try:
            m = client.messages.create(
                model="claude-haiku-4",
                max_tokens=256,
                messages=[{"role": "user", "content": prompt}],
            )
            return m.content[0].text
        except RateLimitError as e:
            wait = int(e.response.headers.get("retry-after", "5"))
            time.sleep(wait)
        except APITimeoutError:
            time.sleep(2 ** attempt)
        except APIError:
            if attempt == max_retry - 1:
                raise
            time.sleep(2 ** attempt)
    raise RuntimeError("Hết retry")

Bốn snippet trên là core đủ để build một app nhỏ. Streaming sẽ ghép tiếp ở Bài 33.

26

Bài tập

  1. Đăng ký console.anthropic.com, tạo key, nạp credit tối thiểu. Set ANTHROPIC_API_KEY trong shell rc và viết script hello.py in ra response của claude-haiku-4 cho prompt "Hello". In thêm message.usage để xem token in/out.
  2. Build chatbot CLI (file chat.py): vòng lặp input(), giữ history multi-turn, dùng system mô tả persona (ví dụ tutor Python). Cho phép user gõ /reset để xoá history, /sys <text> để đổi system.
  3. Test prompt caching: viết script gửi cùng một system prompt dài 5K-20K token (ví dụ tài liệu nội bộ) qua 5 turn user khác nhau. Lần 1 không bật cache, lần 2 bật cache_control={"type": "ephemeral"}. So sánh cache_creation_input_tokens, cache_read_input_tokens, latency và cost ước tính.
  4. So sánh GPT-4o-mini và Claude Haiku 4 trên 20 prompt cùng task (extraction sản phẩm từ description, classification sentiment). Đo: parse rate, accuracy thủ công (5 mẫu), latency P50, cost tổng. Báo cáo 1 bảng.
  5. (Tùy chọn) Cài litellm, viết wrapper llm_call(model, messages) dùng completion(). Test cùng code với model="gpt-4o-mini"model="claude-haiku-4" — verify output structure giống nhau từ phía caller.