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

Multi-Turn conversations with tools

📖 Nội dung bài học

Tóm tắt

Xây dựng các cuộc hội thoại nhiều lượt với tool use đòi hỏi phải xử lý các loại phản hồi khác nhau từ Claude. Khi Claude phản hồi, nó có thể cần dùng một tool, hoặc nó có thể cung cấp câu trả lời trực tiếp. Code của bạn cần xử lý cả hai tình huống một cách trơn tru.

Vấn đề với việc tích hợp tool đơn giản

Nếu bạn chỉ thêm kết quả tool vào mọi cuộc hội thoại, bạn sẽ gặp vấn đề. Khi Claude trả lời một câu hỏi đơn giản như "1+1 bằng bao nhiêu?", nó không cần bất kỳ tool nào. Nhưng nếu code của bạn luôn cố gắng xử lý kết quả tool, bạn sẽ thêm các tin nhắn trống vào lịch sử hội thoại của mình.

Giải pháp là kiểm tra stop_reason đi kèm với mọi phản hồi của Claude. Điều này cho bạn biết tại sao Claude dừng việc tạo - cho dù nó kết thúc một cách tự nhiên hay vì nó muốn dùng một tool.

Stop Reasons

Claude có thể dừng vì một số lý do:

  • "tool_use" - Model muốn gọi một tool
  • "end_turn" - Model đã hoàn thành việc tạo phản hồi
  • "max_tokens" - Đã đạt giới hạn output
  • "stop_sequence" - Gặp một stop sequence bạn đã cung cấp

Cải thiện hàm Chat

Đầu tiên, cập nhật hàm chat của bạn để trả về nhiều thông tin hơn. Thay vì chỉ trả về text và các phần riêng biệt, hãy trả về một dictionary với mọi thứ bạn cần:

def chat(messages, tools=None, system=None, **kwargs):
    # ... existing code ...
    
    return {
        "parts": parts,
        "stop_reason": response["stopReason"],
        "text": "\n".join([p["text"] for p in parts if "text" in p])
    }

Cách tiếp cận này trích xuất tất cả nội dung text từ các phần phản hồi, điều này mạnh mẽ hơn so với việc giả định phần đầu tiên luôn là text.

Xây dựng một vòng lặp hội thoại

Tạo một hàm xử lý luồng hội thoại đầy đủ:

def run_conversation(messages):
    while True:
        result = chat(messages, tools=[get_current_datetime_schema])
        
        add_assistant_message(messages, result["parts"])
        print(result["text"])
        
        if result["stop_reason"] != "tool_use":
            break
            
        tool_result_parts = run_tools(result["parts"])
        add_user_message(messages, tool_result_parts)
    
    return messages

Vòng lặp này tiếp tục cho đến khi Claude dừng vì một lý do khác ngoài tool use. Mỗi lần lặp:

  1. Gửi các tin nhắn hiện tại đến Claude
  2. Thêm phản hồi của Claude vào lịch sử tin nhắn
  3. Kiểm tra xem Claude có muốn dùng một tool không
  4. Nếu có, chạy các tool và thêm kết quả trở lại cuộc hội thoại
  5. Nếu không, thoát khỏi vòng lặp

tool_use

iterate

end_turn / other

User message

Send messages → Bedrock Converse

Claude response + stop_reason

stop_reason == tool_use?

run_tools — append results

Final answer cho user

Kiểm tra việc triển khai

Cách tiếp cận này xử lý cả các câu hỏi cần tool và các câu hỏi đơn giản:


messages = []
add_user_message(messages, "What time is it?")
run_conversation(messages)

messages = []
add_user_message(messages, "What is 1+1?")
run_conversation(messages)

Đối với các câu hỏi về thời gian, Claude sẽ dùng tool datetime. Đối với các câu hỏi toán học, nó trả lời trực tiếp mà không cần bất kỳ tool calls nào. Vòng lặp hội thoại tự động điều chỉnh dựa trên stop reason của Claude.

Mô hình này mở rộng tốt khi bạn thêm nhiều tool - cùng một vòng lặp xử lý bất kỳ sự kết hợp nào của tool use và phản hồi trực tiếp, làm cho AI hội thoại của bạn trở nên mạnh mẽ và tự nhiên hơn.

🔁 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?