Bỏ qua đến nội dung chính

Multi-Turn conversations

📖 Nội dung bài học

Tóm tắt

Mã nguồn chúng ta đã viết cho đến nay mô phỏng một trao đổi rất đơn giản với Claude. Nhưng chuyện gì sẽ xảy ra khi bạn muốn tiếp tục một cuộc hội thoại? Khi bạn đặt một câu hỏi tiếp nối như "Thêm 3 nữa thì sao?" sau khi hỏi "1+1 bằng mấy?", bạn sẽ mong đợi Claude hiểu rằng bạn đang hỏi về việc cộng thêm 3 vào kết quả 2 trước đó.

Tuy nhiên, có một điều quan trọng bạn cần hiểu về API Bedrock và bản thân Claude.

Không lưu trữ tin nhắn (No Message Storage)

Bedrock và Claude không lưu trữ bất kỳ tin nhắn nào. Không có tin nhắn nào bạn gửi đi được lưu lại, và các phản hồi bạn nhận được cũng vậy. Mỗi lần gọi API là hoàn toàn độc lập.

Để có một cuộc hội thoại với nhiều tin nhắn mà vẫn duy trì được ngữ cảnh (context), bạn cần:

  • Tự duy trì một danh sách tất cả các tin nhắn trong mã nguồn của mình.
  • Cung cấp toàn bộ danh sách tin nhắn đó trong mỗi yêu cầu tiếp theo.

Tại sao ngữ cảnh (context) lại quan trọng

Hãy xem điều gì xảy ra nếu không có ngữ cảnh phù hợp. Nếu bạn chỉ gửi "Thêm 3 nữa thì sao?" như một tin nhắn độc lập, Claude sẽ không biết bạn đang đề cập đến điều gì. Nó sẽ cố gắng hết sức để phản hồi, nhưng câu trả lời sẽ không có ý nghĩa vì thiếu ngữ cảnh của cuộc trò chuyện trước đó.

Khi bạn chỉ gửi câu hỏi tiếp nối, Claude chỉ thấy tin nhắn bị cô lập đó và cố gắng trả lời mà không biết về trao đổi "1+1 bằng mấy?" trước đó.

Xây dựng ngữ cảnh hội thoại

Để duy trì ngữ cảnh, bạn cần bao gồm toàn bộ lịch sử hội thoại trong mỗi request. Cách thức hoạt động như sau:

Danh sách tin nhắn của bạn nên chứa tất cả các trao đổi trước đó - bao gồm cả tin nhắn của người dùng (user) và phản hồi của trợ lý (assistant). Khi bạn gửi đầy đủ ngữ cảnh này, Claude có thể hiểu rằng "Thêm 3 nữa thì sao?" là ám chỉ việc cộng thêm 3 vào kết quả 2 trước đó.

Các hàm bổ trợ để quản lý tin nhắn

Để việc quản lý hội thoại dễ dàng hơn, bạn có thể tạo các hàm bổ trợ (helper functions):

def add_user_message(messages, text):
    user_message = {
        "role": "user",
        "content": [
            {"text": text}
        ]
    }
    messages.append(user_message)

def add_assistant_message(messages, text):
    assistant_message = {
        "role": "assistant", 
        "content": [
            {"text": text}
        ]
    }
    messages.append(assistant_message)

def chat(messages):
    response = client.converse(
        modelId=model_id,
        messages=messages
    )
    return response["output"]["message"]["content"][0]["text"]

Triển khai hội thoại đa lượt (Multi-Turn Conversations)

Dưới đây là cách xây dựng một cuộc hội thoại theo từng bước:


messages = []

add_user_message(messages, "What's 1+1?")

answer = chat(messages)

add_assistant_message(messages, answer)

add_user_message(messages, "And 3 more added to that?")

answer = chat(messages)
print(answer)

Cách tiếp cận này đảm bảo Claude có đầy đủ ngữ cảnh và có thể phản hồi phù hợp: "Bắt đầu với kết quả của 1+1 = 2, nếu chúng ta cộng thêm 3 nữa, chúng ta được: 2 + 3 = 5"

Sự luân phiên vai trò tin nhắn (Message Role Alternation)

Khi xây dựng danh sách tin nhắn, hãy luôn đảm bảo rằng các vai trò tin nhắn được luân phiên đúng cách:

Cuộc hội thoại của bạn nên tuân theo mô hình: user → assistant → user → assistant. Không bao giờ để hai tin nhắn user liên tiếp hoặc hai tin nhắn assistant liên tiếp. Mô hình luân phiên này là bắt buộc bởi API và phản ánh luồng hội thoại tự nhiên.

Mặc dù việc quản lý tin nhắn thủ công này ban đầu có vẻ tẻ nhạt, bạn sẽ nhanh chóng làm quen với nó. Mô hình này là nền tảng để xây dựng bất kỳ ứng dụng nào cần duy trì ngữ cảnh hội thoại với Claude.

🔁 Bài học liên quan

📚 Nguồn & ghi nhận

Bài học có hữu ích không?

Góp ý / Báo lỗiPhát hiện sai sót hoặc có ý tưởng cải thiện?