Khắc phục lỗi Anthropic 400: các vai trò (roles) phải luân phiên giữa user và assistant

beginner🧠 AI Tools2026-06-11| Python/Node.js, Anthropic SDK, các model Claude 3/3.5

Error Message

anthropic.BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages: roles must alternate between "user" and "assistant", but found multiple "user" roles in a row'}}
#anthropic#claude#messages#conversation-history#api

Tại sao Anthropic API lại rất nghiêm ngặt

Claude yêu cầu một nhịp điệu phản hồi qua lại hoàn hảo. Không giống như một số LLM khác cho phép bạn xếp chồng các tin nhắn, Anthropic Messages API xử lý cuộc hội thoại giống như một trận đấu quần vợt. Bạn gửi một tin nhắn, Claude trả lời, sau đó bạn gửi một tin nhắn khác. Nếu bạn phá vỡ mô hình user → assistant → user này, API sẽ từ chối yêu cầu ngay lập tức.

Bạn thường sẽ gặp lỗi 400 này theo một trong ba cách sau:

  • Người dùng gửi hai tin nhắn liên tiếp (double-posting) trước khi AI kịp phản hồi.
  • Bạn cố gắng đưa "system" prompt vào bên trong mảng messages.
  • Lịch sử cuộc hội thoại bắt đầu bằng tin nhắn của "assistant" thay vì "user".

Các bước khắc phục

1. Di chuyển System Message ra khỏi mảng

Nếu bạn chuyển từ hệ sinh thái OpenAI sang, đây là một lỗi phổ biến. Trong API của Anthropic, system prompt là một tham số ở cấp cao nhất. Nó không bao giờ được là một đối tượng nằm trong danh sách lịch sử tin nhắn của bạn.

# SAI: Điều này sẽ gây ra lỗi 400
client.messages.create(
    model="claude-3-5-sonnet-20240620",
    messages=[
        {"role": "system", "content": "Bạn là một trợ lý hữu ích"},
        {"role": "user", "content": "Xin chào!"}
    ]
)

# ĐÚNG: Sử dụng tham số system riêng biệt
client.messages.create(
    model="claude-3-5-sonnet-20240620",
    system="Bạn là một trợ lý hữu ích",
    messages=[
        {"role": "user", "content": "Xin chào!"}
    ]
)

2. Gộp các tin nhắn liên tiếp của cùng một vai trò

Trong các ứng dụng chat thực tế, người dùng thường gửi nhiều tin nhắn trước khi AI có thể phản hồi. Bạn không thể chỉ thêm chúng vào một danh sách. Thay vào đó, bạn phải kết hợp chúng thành một đối tượng tin nhắn duy nhất trước khi gửi tới API.

Sử dụng trình hỗ trợ Python này để làm sạch lịch sử của bạn bằng cách gộp các vai trò trùng lặp:

def merge_consecutive_messages(messages):
    if not messages:
        return []
    
    merged = []
    for msg in messages:
        # Kiểm tra xem vai trò hiện tại có khớp với vai trò cuối cùng đã thêm không
        if merged and merged[-1]["role"] == msg["role"]:
            prev_content = merged[-1]["content"]
            curr_content = msg["content"]
            
            # Kết hợp các chuỗi bằng hai dòng mới
            if isinstance(prev_content, str) and isinstance(curr_content, str):
                merged[-1]["content"] = f"{prev_content}\n\n{curr_content}"
            else:
                # Gộp các khối nội dung phức tạp như hình ảnh và văn bản
                if isinstance(prev_content, str):
                    merged[-1]["content"] = [{"type": "text", "text": prev_content}]
                if isinstance(curr_content, str):
                    curr_content = [{"type": "text", "text": curr_content}]
                merged[-1]["content"].extend(curr_content)
        else:
            merged.append(msg)
    return merged

3. Luôn bắt đầu bằng tin nhắn "user"

Anthropic yêu cầu mọi cuộc hội thoại phải bắt đầu bằng vai trò user. Nếu cơ sở dữ liệu của bạn lấy ra một lịch sử bắt đầu bằng phản hồi assistant đã lưu trong cache, API sẽ thất bại. Luôn cắt (slice) hoặc thêm vào đầu danh sách của bạn để đảm bảo tin nhắn của người dùng dẫn đầu.

Xác minh

Trước khi gọi API, hãy in mảng messages của bạn. Nó sẽ trông giống như một chuỗi luân phiên sạch sẽ. Ví dụ: 100% các vai trò phải tuân theo thứ tự [user, assistant, user, assistant]. Nếu bạn thấy hai vai trò giống hệt nhau nằm cạnh nhau, logic gộp của bạn có thể đã thất bại.

Mẹo thực tế

  • Giới hạn UI (Throttling): Vô hiệu hóa nút "Gửi" trong khi trợ lý đang suy nghĩ để ngăn người dùng gửi tin nhắn liên tiếp.
  • Khối nội dung (Content Blocks): Khi gửi văn bản và hình ảnh cùng nhau, hãy sử dụng một vai trò "user" duy nhất với nhiều khối nội dung thay vì hai tin nhắn riêng biệt.
  • Gỡ lỗi: Ghi log JSON payload của yêu cầu. Việc phát hiện các vai trò trùng lặp trong log thô thường dễ dàng hơn so với trong mã ứng dụng phức tạp.

Related Error Notes