Gọi request đầu tiên đến Claude

2 — Gọi Claude qua APICơ bản20 phút

Sau 3 bài đầu, bạn đã biết: - Claude có nhiều tier (Opus/Sonnet/Haiku) - Request đi qua 5 bước từ client → server → API - Cách lấy và bảo vệ API key

Bạn sẽ học được
  • Cài đặt Anthropic Python SDK và cấu hình client
  • Thực hiện request đầu tiên với đầy đủ 4 tham số bắt buộc
  • Giải mã response object và extract text
  • Hiểu ý nghĩa của từng tham số trong messages.create()
  • Phân biệt user message và assistant message

Cài đặt SDK

Anthropic có SDK chính thức cho Python, TypeScript, Go, Ruby, Java. Trong khóa này dùng Python.

Cài package

Trong virtual env của project (source .venv/bin/activate):

Verify:

pip install anthropic python-dotenv

Cài package

Nếu in OK — SDK cài thành công.

Trong Jupyter notebook

python -c "from anthropic import Anthropic; print('OK')"

Trong Jupyter notebook

Lưu ý dùng %pip thay vì !pip: %pip cài vào đúng kernel của notebook, !pip có thể cài vào Python khác.

%pip install anthropic python-dotenv

Request đầu tiên — Full example

Tạo file 01_first_request.ipynb hoặc .py. Gõ từng dòng (không copy — cơ tay cần nhớ):

Cell 1: Setup

Phân tích:

Cell 2: Tạo messages

  • load_dotenv() — đọc file .env vào os.environ
  • Anthropic() — tạo client. Tự đọc ANTHROPIC_API_KEY từ env.
  • model — biến lưu model ID. Pin snapshot để production stable.
from dotenv import load_dotenv
load_dotenv()

from anthropic import Anthropic

client = Anthropic()
model = "claude-sonnet-5-20260205"

Cell 2: Tạo messages

Phân tích:

Cell 3: Gọi API

  • messages là list of dicts
  • Mỗi dict có 2 trường: role và content
  • role phải là "user" hoặc "assistant"
  • content là text bạn muốn gửi
messages = [
    {
        "role": "user",
        "content": "What is quantum computing? Answer in one sentence."
    }
]

Cell 3: Gọi API

Phân tích tham số:

Cell 4: Extract text

Tham sốKiểuÝ nghĩa
modelstrModel ID (đã gán ở cell 1)
max_tokensintTrần cứng cho output
messageslistLịch sử hội thoại
message = client.messages.create(
    model=model,
    max_tokens=1000,
    messages=messages,
)

Cell 4: Extract text

Phân tích:

Output dự kiến:

  • message là object Anthropic Message
  • .content là list content blocks
  • [0] = block đầu tiên (usually chỉ có 1)
  • .text = text content của block
print(message.content[0].text)

Request đầu tiên — Full example (tiếp)

Chúc mừng — bạn vừa gọi Claude API thành công!

Quantum computing is a form of computation that leverages the principles
of quantum mechanics—such as superposition and entanglement—to process
information in fundamentally different ways than classical computers.

Đi sâu vào response object

Thay vì chỉ .content[0].text, in full object để hiểu:

Output (rút gọn):

print(message)

Đi sâu vào response object (tiếp)

Mỗi trường có ý nghĩa gì?

┌──────────────────────────────────────────────────┐
│                                                  │
│  id           → Unique identifier của message    │
│                  Dùng để log, debug, reference   │
│                                                  │
│  role         → Luôn là "assistant" (Claude)     │
│                                                  │
│  model        → Model thật đã chạy (full date)   │
│                                                  │
│  content      → List content block               │
│     TextBlock → type='text', text='...'          │
│     (sau này)  ToolUseBlock, ThinkingBlock       │
│                                                  │
│  stop_reason  → Vì sao dừng (bài 6.4)            │
│                                                  │
│  usage        → Metrics billing                  │
│     input_tokens   → Tính tiền input             │
│     output_tokens  → Tính tiền output            │
│                                                  │
└──────────────────────────────────────────────────┘
Message(
    id='msg_01XYZ...',
    type='message',
    role='assistant',
    model='claude-sonnet-5-20260205',
    content=[
        TextBlock(
            type='text',
            text='Quantum computing is...'
        )
    ],
    stop_reason='end_turn',
    stop_sequence=None,
    usage=Usage(
        input_tokens=15,
        output_tokens=62,
        cache_creation_input_tokens=0,
        cache_read_input_tokens=0
    )
)

max_tokens — Cần lưu ý gì?

max_tokens là trần cứng cho output, không phải target.

Ví dụ

# max_tokens=50, câu hỏi ngắn
msg = client.messages.create(
    model=model,
    max_tokens=50,
    messages=[{"role": "user", "content": "Say hi"}]
)
# Output: "Hi! How can I help you today?"
# output_tokens: 9
# → Dừng sớm do end_turn, KHÔNG chạm 50

Ví dụ

Quy tắc chọn max_tokens

Pro tip: Set max_tokens gấp 1.5x số bạn dự kiến. Vừa đủ safety margin, vừa không lãng phí.

Use casemax_tokens đề xuất
Classification (yes/no)10
Short answer chat500
Medium chat response1000-2000
Long explanation4000
Article / document8000-16000
Reasoning chain16000-32000
Max Sonnet 5 output64000
# max_tokens=50, câu hỏi cần trả lời dài
msg = client.messages.create(
    model=model,
    max_tokens=50,
    messages=[{"role": "user", "content": "Write a 500-word essay about AI"}]
)
# Output: "AI is a rapidly evolving field that..."
# output_tokens: 50
# stop_reason: 'max_tokens' ← Bị cắt!

Messages — cấu trúc chi tiết

Single-turn (1 user message)

Multi-turn (conversation history)

messages = [
    {"role": "user", "content": "Hello"}
]

Multi-turn (conversation history)

Quy tắc cứng

1. Phải bắt đầu bằng user:

messages = [
    {"role": "user", "content": "What is 2+2?"},
    {"role": "assistant", "content": "2+2 equals 4."},
    {"role": "user", "content": "What about 3+3?"}
]

Quy tắc cứng

2. Role phải alternating:

# ❌ Sai
messages = [{"role": "assistant", "content": "Hi!"}]

# ✅ Đúng
messages = [{"role": "user", "content": "Hi"}]

Messages — cấu trúc chi tiết (tiếp)

3. Message cuối phải là user (để Claude có gì để reply):

# ❌ Sai — 2 user liên tiếp
messages = [
    {"role": "user", "content": "Hello"},
    {"role": "user", "content": "Are you there?"}
]

# ✅ Đúng — xen kẽ user/assistant
messages = [
    {"role": "user", "content": "Hello"},
    {"role": "assistant", "content": "Yes!"},
    {"role": "user", "content": "Are you there?"}
]

Messages — cấu trúc chi tiết (tiếp)

# ❌ Sai — kết thúc bằng assistant, Claude không biết phải nói gì
messages = [
    {"role": "user", "content": "Hi"},
    {"role": "assistant", "content": "Hello!"}
]
# Nếu gọi với messages này, Claude sẽ continue từ assistant → kỳ quặc

Ví dụ thực chiến: Query về dữ liệu công ty

Tình huống

Bạn là HR Manager, muốn test xem Claude có trả lời tốt câu hỏi policy không.

Bước 1: Setup

Bước 2: Câu hỏi đầu tiên

from dotenv import load_dotenv
load_dotenv()
from anthropic import Anthropic

client = Anthropic()
model = "claude-sonnet-5-20260205"

Bước 2: Câu hỏi đầu tiên

Bước 3: Đọc response

Claude có thể trả lời:

messages = [
    {
        "role": "user",
        "content": "Công ty tôi có policy về work from home như sau: nhân viên được WFH tối đa 2 ngày/tuần, thứ 2 phải có mặt. Giải thích lý do có thể có cho policy này."
    }
]

msg = client.messages.create(
    model=model,
    max_tokens=800,
    messages=messages,
)

print(msg.content[0].text)

Bước 3: Đọc response

Bước 4: Xem usage

Có nhiều lý do hợp lý cho policy WFH này:

1. **Thứ 2 là ngày quan trọng**: Đây thường là ngày kick-off tuần, 
   cần họp planning, align priorities...

2. **Giới hạn 2 ngày đảm bảo collaboration**: Face-to-face 3 ngày/tuần...

3. **Cân bằng quyền lợi**: WFH giúp work-life balance, đặc biệt với...

Bước 4: Xem usage

Kết quả

Thời gian: ~3 giây. Cost: 100 VNĐ. Chất lượng: Sẵn sàng dùng trong app nội bộ.

print(f"Input tokens: {msg.usage.input_tokens}")
print(f"Output tokens: {msg.usage.output_tokens}")

# Input tokens: 85
# Output tokens: 247

# Cost tính:
# input: 85 / 1M * $3 = $0.000255
# output: 247 / 1M * $15 = $0.003705
# Total: ~$0.004 (~100 VNĐ)

Case studies theo ngành

📊 Data Analyst

Task: Generate SQL query từ câu hỏi tiếng Việt.

Output: Query PostgreSQL chuẩn. Cost: $0.002/query.

📝 Content Writer

Task: Rewrite title cho SEO.

messages = [{
    "role": "user",
    "content": """
    Schema:
    - orders(id, user_id, amount, created_at)
    - users(id, name, email)
    
    Câu hỏi: Liệt kê top 10 user có tổng đơn hàng cao nhất trong 30 ngày.
    Trả về SQL query.
    """
}]
msg = client.messages.create(model=model, max_tokens=300, messages=messages)

📝 Content Writer

🎧 Support Ops

Task: Classify intent của ticket.

messages = [{
    "role": "user",
    "content": "Rewrite thành 5 tiêu đề SEO khác nhau: 'Cách dùng Claude API'"
}]

🎧 Support Ops

messages = [{
    "role": "user",
    "content": """
    Phân loại ticket sau vào 1 trong 4 category: refund, technical, feature_request, other
    
    Ticket: "Tôi không login được app từ hôm qua, màn hình trắng xóa"
    
    Trả về duy nhất tên category, không giải thích.
    """
}]
msg = client.messages.create(
    model="claude-haiku-4-5",  # Haiku đủ cho task này
    max_tokens=10,
    messages=messages
)
# Output: "technical"

Anti-patterns phổ biến

❌ Quên load_dotenv()

Hiện tượng: AuthenticationError: missing API key

Fix: Gọi load_dotenv() TRƯỚC khi tạo Anthropic().

❌ messages không là list

Hiện tượng: BadRequestError: messages must be a list

❌ Access .content như string

# ❌ Sai
messages = {"role": "user", "content": "Hi"}

# ✅ Đúng (wrap trong list)
messages = [{"role": "user", "content": "Hi"}]

❌ Access .content như string

❌ Không handle exceptions

Hiện tượng: App crash khi có network blip.

Fix:

# ❌ Sai
print(message.content)  # In [TextBlock(...)] → không đẹp

# ✅ Đúng
print(message.content[0].text)  # In text thật

❌ Không handle exceptions

❌ Set max_tokens quá cao "for safety"

Ví dụ: max_tokens=64000 cho chatbot ngắn.

Hậu quả: Không hỏng code, nhưng tính tiền sai. Nhiều cloud provider charge dựa trên max_tokens reserved, không phải actual output.

Fix: Set realistic, tăng khi cần.

from anthropic import APIError, RateLimitError

try:
    msg = client.messages.create(...)
except RateLimitError:
    # Wait and retry
    time.sleep(60)
    msg = client.messages.create(...)
except APIError as e:
    print(f"API error: {e}")
    # Graceful degrade

Áp dụng ngay

Bài tập 1: "Hello World" với 3 câu hỏi khác nhau (15 phút)

Trong notebook 01_first_request.ipynb, làm 3 request:

Với mỗi request, in ra:

Bài tập 2: Viết utility function (15 phút)

Viết function ask(prompt: str, model: str = None) -> str:

Mở rộng (optional): Thêm tham số max_tokens với default = 1000, và print usage nếu verbose=True.

  • Classification: "Phân loại cảm xúc của câu: 'Hôm nay trời đẹp quá!'" — dùng Haiku
  • Creative: "Viết 1 câu thơ về mùa thu Hà Nội" — dùng Sonnet
  • Reasoning: "Nếu A > B và B > C, A có > C không? Giải thích" — dùng Sonnet
  • Response text
  • input_tokens và output_tokens
  • Model đã dùng
  • stop_reason
def ask(prompt: str, model: str = None) -> str:
    """
    Gửi prompt đơn giản tới Claude, trả về text response.
    """
    # Code của bạn
    pass

# Test
print(ask("What is 2+2?"))
# Output: "2+2 equals 4."

Tóm tắt bài học

🎯 Setup 3 dòng: load_dotenv() → Anthropic() → model_id. Mọi request sau dùng client này.

🎯 messages.create() cần 3 tham số bắt buộc: model, max_tokens, messages. Đủ cho 80% use case.

🎯 Messages là list dict với role alternating (user → assistant → user...). Phải bắt đầu và kết thúc bằng user.

🎯 Extract text bằng message.content[0].text. Check stop_reason trước khi trust response.

🎯 max_tokens là trần cứng, không phải target. Set realistic cho use case cụ thể.

Tài liệu tham khảo
  • Anthropic Python SDK
  • Messages API reference
  • anthropic-cookbook/quickstart
Nội dung này có hữu ích không?