JSON Mode — Buộc Claude trả về JSON chính xác
Điểm nổi bật
Nhấn để đến mục tương ứng
- 1 Áp dụng ngay: Cách đơn giản nhất — mô tả schema trong prompt: import anthropic import json client = anthropic.Anthropic response = — phần này cung cấp quy trình cụ thể giúp bạn triển khai hiệu quả mà không cần thử nghiệm nhiều lần.
- 2 Thành thật mà nói: Claude không thể nói gì trước JSON nếu bạn đã điền sẵn ký tự đầu tiên: response = client.messages.create. Phương pháp này hiệu quả trong hầu hết trường hợp, nhưng bạn cần điều chỉnh cho phù hợp ngữ cảnh riêng.
- 3 Không thể bỏ qua: Kết hợp với prefill, stop sequences giúp kiểm soát chính xác điểm kết thúc: response = client.messages.create. Đây là kiến thức nền tảng mà mọi người làm việc với AI đều cần hiểu rõ.
- 4 Để đạt hiệu quả tối đa: """ text = text.strip Strategy 1: Parse trực tiếp try: return json.loadstext except json.JSONDecodeError: pass Strategy. Nhiều người bỏ qua bước này và mất thời gian gấp đôi để đạt cùng kết quả.
- 5 Một điều ít người đề cập: Sau khi parse, validate schema bằng Pydantic để catch lỗi sớm: from pydantic import BaseModel, Field, validator from. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
Khi tích hợp Claude vào ứng dụng, bạn thường cần parse output của Claude thành dữ liệu có cấu trúc. Nếu Claude trả về text tự do, code của bạn sẽ break. Câu hỏi là: làm sao đảm bảo Claude luôn trả về JSON hợp lệ?
Claude không có "JSON mode" như một số model khác, nhưng có nhiều kỹ thuật kết hợp lại cho kết quả rất đáng tin cậy. Bài này trình bày tất cả các kỹ thuật từ đơn giản đến nâng cao.
Kỹ thuật 1: Yêu cầu JSON trong prompt
Cách đơn giản nhất — mô tả schema trong prompt:
import anthropic
import json
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=500,
messages=[{
"role": "user",
"content": """Phân tích review sản phẩm sau và trả về JSON.
Review: "Điện thoại này pin trâu, camera đẹp, nhưng hơi nặng và đắt."
Trả về JSON với format:
{
"sentiment": "positive|negative|neutral|mixed",
"pros": ["điểm tốt 1", "điểm tốt 2"],
"cons": ["điểm chưa tốt 1"],
"score": 1-10,
"summary": "tóm tắt ngắn"
}
Chỉ trả về JSON, không có text khác."""
}],
temperature=0.0,
)
text = response.content[0].text
data = json.loads(text)
print(data["sentiment"]) # "mixed"
print(data["pros"]) # ["pin trâu", "camera đẹp"]
Cách này hoạt động tốt trong 90% trường hợp. Vấn đề: đôi khi Claude thêm text trước hoặc sau JSON ("Đây là JSON: {...} Hy vọng hữu ích!").
Kỹ thuật 2: Prefill với "{" — Đáng tin cậy nhất
Trick mạnh nhất: bắt đầu response bằng ký tự mở JSON. Claude không thể nói gì trước JSON nếu bạn đã điền sẵn ký tự đầu tiên:
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=500,
messages=[
{
"role": "user",
"content": """Phân tích review: "Điện thoại pin trâu, camera đẹp nhưng hơi nặng."
Trả về JSON với: sentiment, pros (array), cons (array), score (1-10)"""
},
# Prefill: bắt đầu response của Claude với "{"
{
"role": "assistant",
"content": "{"
}
],
temperature=0.0,
)
# Response chỉ chứa phần còn lại của JSON (sau "{")
partial_json = response.content[0].text
full_json = "{" + partial_json # Ghép lại
data = json.loads(full_json)
print(data)
Kỹ thuật này đảm bảo 100% response bắt đầu bằng JSON object. Claude không thể nói gì khác vì đã bị "lock in" vào JSON format.
Kỹ thuật 3: Stop Sequences
Kết hợp với prefill, stop sequences giúp kiểm soát chính xác điểm kết thúc:
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=500,
messages=[
{"role": "user", "content": "Trả về JSON object có key 'result' với giá trị là số nguyên tố đầu tiên lớn hơn 100."},
{"role": "assistant", "content": "{"}
],
stop_sequences=["}"], # Dừng ngay sau khi đóng JSON object
temperature=0.0,
)
# Cần thêm "}" vào cuối vì stop sequence không được include
partial = response.content[0].text
full_json = "{" + partial + "}"
# Hoặc dùng stop_reason để detect
if response.stop_reason == "stop_sequence":
full_json = "{" + response.content[0].text + "}"
data = json.loads(full_json)
print(data["result"]) # 101
Lưu ý: Stop sequences hữu ích nhất khi JSON object nhỏ và không có nested objects phức tạp (vì "}" xuất hiện nhiều lần trong nested JSON).
Kỹ thuật 4: XML wrapper + Extraction
Cho phép Claude "suy nghĩ" trước khi output JSON, tránh hallucination:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1000,
messages=[{
"role": "user",
"content": """Phân tích báo cáo tài chính sau và extract thông tin key.
Báo cáo: "Quý 3/2024: Doanh thu đạt 150 tỷ VND, tăng 23% so với cùng kỳ.
Chi phí hoạt động là 95 tỷ, lợi nhuận ròng 55 tỷ. Số nhân viên: 1.200 người."
Suy nghĩ kỹ, sau đó trả về trong tag :
{
"quarter": "Q3/2024",
"revenue_billion_vnd": 150,
"revenue_growth_percent": 23,
"operating_cost_billion_vnd": 95,
"net_profit_billion_vnd": 55,
"employees": 1200
}
"""
}],
temperature=0.0,
)
import re
text = response.content[0].text
# Extract JSON từ XML tag
match = re.search(r"(.*?) ", text, re.DOTALL)
if match:
json_str = match.group(1).strip()
data = json.loads(json_str)
print(f"Revenue: {data['revenue_billion_vnd']}B VND")
print(f"Growth: {data['revenue_growth_percent']}%")
Kỹ thuật 5: Robust JSON parsing
Dù dùng kỹ thuật nào, production code nên có fallback parsing mạnh:
import json
import re
def robust_json_parse(text: str) -> dict:
"""
Parse JSON từ text với nhiều fallback strategies.
"""
text = text.strip()
# Strategy 1: Parse trực tiếp
try:
return json.loads(text)
except json.JSONDecodeError:
pass
# Strategy 2: Tìm JSON object đầu tiên bằng regex
match = re.search(r"{.*}", text, re.DOTALL)
if match:
try:
return json.loads(match.group())
except json.JSONDecodeError:
pass
# Strategy 3: Tìm JSON trong code block
code_block = re.search(r"'''(?:json)?
?(.*?)
?'''", text, re.DOTALL)
if code_block:
try:
return json.loads(code_block.group(1).strip())
except json.JSONDecodeError:
pass
# Strategy 4: Tìm JSON trong XML tag
xml_match = re.search(r"(.*?) ", text, re.DOTALL)
if xml_match:
try:
return json.loads(xml_match.group(1).strip())
except json.JSONDecodeError:
pass
raise ValueError(f"Không thể parse JSON từ text: {text[:200]}")
# Test
test_cases = [
'{"key": "value"}',
'Here is the JSON: {"key": "value"} Hope this helps!',
''''json
{"key": "value"}
'''',
'{"key": "value"} ',
]
for tc in test_cases:
try:
result = robust_json_parse(tc)
print(f"OK: {result}")
except ValueError as e:
print(f"FAIL: {e}")
Kỹ thuật 6: Pydantic validation
Sau khi parse, validate schema bằng Pydantic để catch lỗi sớm:
from pydantic import BaseModel, Field, validator
from typing import List, Optional
class ProductReview(BaseModel):
sentiment: str = Field(..., pattern="^(positive|negative|neutral|mixed)$")
pros: List[str] = Field(default_factory=list)
cons: List[str] = Field(default_factory=list)
score: int = Field(..., ge=1, le=10)
summary: Optional[str] = None
@validator("pros", "cons", each_item=True)
def not_empty(cls, v):
if not v.strip():
raise ValueError("Items cannot be empty")
return v.strip()
def get_structured_review(review_text: str) -> ProductReview:
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=400,
messages=[
{
"role": "user",
"content": f"""Phân tích review: "{review_text}"
Trả về JSON với: sentiment (positive/negative/neutral/mixed),
pros (array), cons (array), score (1-10), summary (string)"""
},
{"role": "assistant", "content": "{"}
],
temperature=0.0,
)
json_str = "{" + response.content[0].text
data = robust_json_parse(json_str)
# Validate với Pydantic — raises ValidationError nếu sai schema
return ProductReview(**data)
try:
review = get_structured_review("Sản phẩm ổn nhưng giá hơi cao, giao hàng nhanh.")
print(f"Sentiment: {review.sentiment}")
print(f"Score: {review.score}/10")
print(f"Pros: {review.pros}")
except Exception as e:
print(f"Error: {e}")
Chọn kỹ thuật nào?
| Kỹ thuật | Độ tin cậy | Phức tạp | Khi nào dùng |
|---|---|---|---|
| Prompt đơn giản | 90% | Thấp | Prototype, testing |
| Prefill "{" | 99% | Thấp | Production, JSON objects |
| XML + Extraction | 98% | Trung bình | Khi cần Claude suy nghĩ trước |
| Prefill + Stop seq | 99% | Trung bình | JSON nhỏ, đơn giản |
| Robust parsing + Pydantic | 99.9% | Cao | Production critical |
Khuyến nghị cho production: Kết hợp Prefill "{" + Robust parsing + Pydantic validation. Ba lớp bảo vệ này đảm bảo hệ thống của bạn không bao giờ crash vì JSON malformed.
Kết hợp JSON output với Prompt Caching để giảm latency khi schema phức tạp được reuse nhiều lần.
Bai viet co huu ich khong?
Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.





