Đánh giá Đặc vụ bằng ADK

1. Khoảng cách về niềm tin

Khoảnh khắc truyền cảm hứng

Bạn đã tạo một nhân viên dịch vụ khách hàng. Ứng dụng này hoạt động trên máy của bạn. Nhưng hôm qua, Gemini đã nói với một khách hàng rằng chiếc Đồng hồ thông minh hết hàng vẫn còn hàng, hoặc tệ hơn là Gemini đã bịa ra một chính sách hoàn tiền. Bạn có ngủ ngon vào ban đêm khi biết rằng nhân viên hỗ trợ của bạn đang hoạt động không?

Để thu hẹp khoảng cách giữa một bản chứng minh khái niệm và một tác nhân AI sẵn sàng hoạt động, bạn cần có một khung đánh giá mạnh mẽ và tự động.

dịch vụ khách hàng

Chúng ta thực sự đang đánh giá điều gì?

Việc đánh giá tác nhân phức tạp hơn so với việc đánh giá LLM tiêu chuẩn. Bạn không chỉ chấm điểm Bài luận (Câu trả lời cuối cùng) mà còn chấm điểm Toán học (Logic/công cụ được dùng để đưa ra câu trả lời).

sơ đồ đánh giá

  1. Quỹ đạo (Quy trình): Nhân viên có sử dụng đúng công cụ vào đúng thời điểm không? Bạn có gọi check_inventory trước place_order không?
  2. Câu trả lời cuối cùng (Đầu ra): Câu trả lời có chính xác, lịch sự và dựa trên dữ liệu không?

Vòng đời phát triển

Trong lớp học lập trình này, chúng ta sẽ tìm hiểu vòng đời chuyên nghiệp của hoạt động kiểm thử tác nhân:

  1. Kiểm tra trực quan tại địa phương (Giao diện người dùng web ADK): Trò chuyện và xác minh logic theo cách thủ công (Bước 1).
  2. Kiểm thử đơn vị/hồi quy (ADK CLI): Chạy các trường hợp kiểm thử cụ thể trên máy để phát hiện nhanh các lỗi (Bước 3 và 4).
  3. Gỡ lỗi (Khắc phục sự cố): Phân tích các lỗi và sửa logic của câu lệnh (Bước 5).
  4. Tích hợp CI/CD (Pytest): Tự động hoá các quy trình kiểm thử trong quy trình dựng (Bước 6).

2. Thiết lập

Để hỗ trợ các tác nhân AI của chúng tôi, chúng tôi cần hai thứ: một Dự án trên Google Cloud để cung cấp nền tảng.

Bước 1: Bật Tài khoản thanh toán

  • Để nhận tài khoản thanh toán có khoản tín dụng 5 đô la, bạn cần phải có tài khoản này để triển khai. Đảm bảo bạn đã đăng nhập vào tài khoản gmail.

Bước 2: Mở Environment

👉 Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Google Cloud (Đây là biểu tượng có hình dạng thiết bị đầu cuối ở đầu ngăn Cloud Shell),

văn bản thay thế

👉 Nhấp vào nút "Mở trình chỉnh sửa" (nút này trông giống như một thư mục đang mở có bút chì). Thao tác này sẽ mở Trình chỉnh sửa mã Cloud Shell trong cửa sổ. Bạn sẽ thấy một trình khám phá tệp ở bên trái. văn bản thay thế

👉Mở cửa sổ dòng lệnh trong IDE trên đám mây, văn bản thay thế

👉💻 Trong thiết bị đầu cuối, hãy xác minh rằng bạn đã được xác thực và dự án được đặt thành mã dự án của bạn bằng lệnh sau:

gcloud auth list

👉💻 Sao chép dự án khởi động từ GitHub:

git clone https://github.com/cuppibla/adk_eval_starter

👉💻 Chạy tập lệnh thiết lập trong thư mục dự án.

⚠️ Lưu ý về mã dự án: Tập lệnh sẽ đề xuất một mã dự án mặc định được tạo ngẫu nhiên. Bạn có thể nhấn phím Enter để chấp nhận giá trị mặc định này.

Tuy nhiên, nếu muốn tạo một dự án mới cụ thể, bạn có thể nhập mã dự án mong muốn khi tập lệnh nhắc bạn.

cd ~/adk_eval_starter
./init.sh

Tập lệnh sẽ tự động xử lý phần còn lại của quy trình thiết lập.

👉 Bước quan trọng sau khi hoàn tất: Sau khi tập lệnh hoàn tất, bạn phải đảm bảo Google Cloud Console đang xem dự án chính xác:

  1. Truy cập vào console.cloud.google.com.
  2. Nhấp vào trình đơn thả xuống bộ chọn dự án ở đầu trang.
  3. Nhấp vào thẻ "Tất cả" (vì dự án mới có thể chưa xuất hiện trong phần "Gần đây").
  4. Chọn Mã dự án mà bạn vừa định cấu hình ở bước init.sh.

03-05-project-all.png

👉💻 Đặt mã dự án cần thiết:

gcloud config set project $(cat ~/project_id.txt) --quiet

Thiết lập quyền

👉💻 Bật các API bắt buộc bằng lệnh sau. Việc này có thể mất vài phút.

gcloud services enable \
    cloudresourcemanager.googleapis.com \
    servicenetworking.googleapis.com \
    run.googleapis.com \
    cloudbuild.googleapis.com \
    artifactregistry.googleapis.com \
    aiplatform.googleapis.com \
    compute.googleapis.com

👉💻 Cấp các quyền cần thiết bằng cách chạy các lệnh sau trong thiết bị đầu cuối:

. ~/adk_eval_starter/set_env.sh

Xin lưu ý rằng một tệp .env sẽ được tạo cho bạn. Thẻ này cho biết thông tin dự án của bạn.

3. Tạo tập dữ liệu vàng (adk web)

golden

Chúng tôi cần có khoá đáp án thì mới có thể chấm điểm cho trợ lý ảo. Trong ADK, chúng tôi gọi đây là Tập dữ liệu quan trọng. Tập dữ liệu này chứa những lượt tương tác "hoàn hảo" đóng vai trò là sự thật cơ bản để đánh giá.

Tập dữ liệu vàng là gì?

Tập dữ liệu vàng là ảnh chụp nhanh về tác nhân của bạn đang hoạt động chính xác. Đây không chỉ là danh sách các cặp câu hỏi và câu trả lời. Thẻ này ghi lại:

  • Câu hỏi của người dùng ("Tôi muốn được hoàn tiền")
  • Quỹ đạo (Trình tự chính xác của các lệnh gọi công cụ: check_order -> verify_eligibility -> refund_transaction).
  • Câu trả lời cuối cùng (Câu trả lời bằng văn bản "hoàn hảo").

Chúng tôi sử dụng thông tin này để phát hiện Hồi quy. Nếu bạn cập nhật câu lệnh và nhân viên hỗ trợ đột ngột ngừng kiểm tra điều kiện trước khi hoàn tiền, thì thử nghiệm Tập dữ liệu vàng sẽ thất bại vì quỹ đạo không còn khớp nữa.

Mở giao diện người dùng web

Giao diện người dùng web ADK cung cấp một cách thức tương tác để tạo các tập dữ liệu mẫu này bằng cách ghi lại các lượt tương tác thực với tác nhân của bạn.

👉 Trong thiết bị đầu cuối, hãy chạy:

cd ~/adk_eval_starter
uv run adk web

👉 Mở bản xem trước Giao diện người dùng web (thường ở http://127.0.0.1:8000).

👉 Trong giao diện người dùng trò chuyện, hãy nhập

Hi, I'm customer CUST001. Can you check my orders? I need a refund for order ORD-102. It arrived damaged.

adk eval result

Bạn sẽ thấy phản hồi như sau:

I've processed your refund for order ORD-102 due to the items arriving damaged. A full refund of $35.0 has been processed, and the status of order ORD-102 is now updated to "refunded".

Is there anything else I can assist you with today, CUST001? 🛍️

Ghi lại các lượt tương tác hiệu quả

Chuyển đến thẻ Phiên. Tại đây, bạn có thể xem nhật ký trò chuyện của nhân viên hỗ trợ bằng cách nhấp vào phiên trò chuyện.

  1. Tương tác với trợ lý ảo để tạo một luồng trò chuyện lý tưởng, chẳng hạn như kiểm tra nhật ký mua hàng hoặc yêu cầu hoàn tiền.
  2. Xem lại cuộc trò chuyện để đảm bảo cuộc trò chuyện thể hiện hành vi dự kiến.

dấu vết eval

4. Xuất Tập dữ liệu quan trọng

Xác minh bằng Chế độ xem dấu vết

Trước khi xuất, bạn phải xác minh rằng nhân viên hỗ trợ không chỉ nhận được câu trả lời đúng một cách tình cờ. Bạn cần kiểm tra logic nội bộ.

  1. Nhấp vào thẻ Trace (Dấu vết) trong Giao diện người dùng web.
  2. Các dấu vết được tự động nhóm theo thông báo của người dùng. Di chuột lên một hàng dấu vết để làm nổi bật thông báo tương ứng trong cuộc trò chuyện.
  3. Kiểm tra các hàng màu xanh dương: Đây là những hàng cho biết các sự kiện được tạo từ lượt tương tác. Nhấp vào một hàng màu xanh dương để mở bảng điều khiển kiểm tra.
  4. Kiểm tra các thẻ sau để xác thực logic:
    • Biểu đồ: Hình ảnh minh hoạ các lệnh gọi công cụ và luồng logic. Đường đi có chính xác không?
    • Yêu cầu/Phản hồi: Xem xét chính xác nội dung đã được gửi đến mô hình và nội dung nhận được.
    • Xác minh: Nếu nhân viên dự đoán được số tiền hoàn lại mà không cần gọi công cụ cơ sở dữ liệu, thì đó là "ảo tưởng may mắn". eval verify

Thêm phiên vào EvalSet

Khi bạn hài lòng với cuộc trò chuyện và dấu vết: 👉 Nhấp vào thẻ Eval, sau đó nhấp vào nút Create Evaluation Set rồi nhập tên đánh giá là:

evalset1

tập hợp đánh giá

👉 Trong tập hợp đánh giá này, hãy nhấp vào biểu tượng Add current session to evalset1. Trong cửa sổ bật lên, hãy nhập tên phiên là:

eval1

eval create

Chạy Eval trong ADK Web

👉 Trong giao diện người dùng web ADK, hãy nhấp vào Run Evaluation, trong cửa sổ bật lên, hãy điều chỉnh các chỉ số rồi nhấp vào Start:

run eval

Xác minh tập dữ liệu trong kho lưu trữ

Bạn sẽ thấy thông báo xác nhận rằng một tệp tập dữ liệu (ví dụ: evalset1.evalset.json) đã được lưu vào kho lưu trữ của bạn. Tệp này chứa dấu vết thô, được tạo tự động của cuộc trò chuyện.

eval set save

5. Tệp đánh giá

tệp eval

Mặc dù giao diện người dùng trên web tạo ra một tệp .evalset.json phức tạp, nhưng chúng ta thường muốn tạo một tệp kiểm thử gọn gàng và có cấu trúc hơn cho quy trình kiểm thử tự động.

ADK Eval sử dụng 2 thành phần chính:

  1. Tệp kiểm thử: Có thể là Tập dữ liệu chuẩn được tạo tự động (ví dụ: customer_service_agent/evalset1.evalset.json) hoặc một tập hợp được tuyển chọn theo cách thủ công (ví dụ: customer_service_agent/eval.test.json).
  2. Tệp cấu hình (ví dụ: customer_service_agent/test_config.json): Xác định các chỉ số và ngưỡng để vượt qua.

Thiết lập tệp cấu hình kiểm thử

👉 Mở customer_service_agent/test_config.json trong trình chỉnh sửa.

Nhập mã sau:

{
  "criteria": {
    "tool_trajectory_avg_score": 0.8,
    "response_match_score": 0.5
  }
}

Giải mã các chỉ số

  1. tool_trajectory_avg_score (Quy trình) Chỉ số này đo lường xem nhân viên hỗ trợ có sử dụng công cụ đúng cách hay không.
  • 0.8: Chúng tôi yêu cầu độ trùng khớp là 80%.
  1. response_match_score (Đầu ra) Thử nghiệm này sử dụng ROUGE-1 (mức độ trùng lặp từ) để so sánh câu trả lời với câu trả lời tham chiếu chính xác.
  • Ưu điểm: Nhanh chóng, xác định được, miễn phí.
  • Nhược điểm: Thất bại nếu tác nhân diễn đạt cùng một ý tưởng theo cách khác (ví dụ: "Đã hoàn tiền" so với "Đã trả lại tiền").

Chỉ số nâng cao (khi bạn cần có thêm sức mạnh)

6. Chạy quy trình đánh giá cho tập dữ liệu vàng (adk eval)

vòng lặp bên trong

Bước này thể hiện "Vòng lặp bên trong" của quá trình phát triển. Bạn là nhà phát triển đang thực hiện các thay đổi và muốn nhanh chóng xác minh kết quả.

Chạy Tập dữ liệu quan trọng

hãy chạy tập dữ liệu mà bạn đã tạo ở Bước 1. Điều này giúp đảm bảo đường cơ sở của bạn vững chắc.

👉 Trong thiết bị đầu cuối, hãy chạy:

cd ~/adk_eval_starter
uv run adk eval customer_service_agent customer_service_agent/evalset1.evalset.json --config_file_path=customer_service_agent/test_config.json --print_detailed_results

Điều gì đang xảy ra?

ADK hiện là:

  1. Đang tải nhân viên hỗ trợ từ customer_service_agent.
  2. Đang chạy các truy vấn đầu vào từ evalset1.evalset.json.
  3. So sánh quỹ đạo và phản hồi thực tế của tác nhân với quỹ đạo và phản hồi dự kiến.
  4. Chấm điểm kết quả dựa trên các tiêu chí trong test_config.json.

Phân tích kết quả

Xem kết quả đầu ra của thiết bị đầu cuối. Bạn sẽ thấy bản tóm tắt về các kiểm thử đã vượt qua và không vượt qua.

Eval Run Summary
evalset1:
  Tests passed: 1
  Tests failed: 0
********************************************************************
Eval Set Id: evalset1
Eval Id: eval1
Overall Eval Status: PASSED
---------------------------------------------------------------------
Metric: tool_trajectory_avg_score, Status: PASSED, Score: 1.0, Threshold: 0.8
---------------------------------------------------------------------
Metric: response_match_score, Status: PASSED, Score: 0.5581395348837208, Threshold: 0.5
---------------------------------------------------------------------
Invocation Details:
+----+---------------------------+---------------------------+--------------------------+---------------------------+---------------------------+-----------------------------+------------------------+
|    | prompt                    | expected_response         | actual_response          | expected_tool_calls       | actual_tool_calls         | tool_trajectory_avg_score   | response_match_score   |
+====+===========================+===========================+==========================+===========================+===========================+=============================+========================+
|  0 | Hi, I'm customer CUST001. | Great news! Your refund   | Great news, CUST001! 🎉   | id='adk-051409fe-c230-43f | id='adk-4e9aa570-1cc6-4c3 | Status: PASSED, Score:      | Status: PASSED, Score: |
|    | Can you check my orders?  | for order **ORD-102** has | I've successfully        | 4-a7f1- 5747280fd878'     | c-aa3e- 91dbe113dd4b'     | 1.0                         | 0.5581395348837208     |
|    | I need a refund for order | been successfully         | processed a full refund  | args={'customer_id':      | args={'customer_id':      |                             |                        |
|    | ORD-102. It arrived       | processed due to the item | of $35.0 for your order  | 'CUST001'} name='get_purc | 'CUST001'} name='get_purc |                             |                        |
|    | damaged.                  | arriving damaged. You     | ORD-102 because it       | hase_history'             | hase_history'             |                             |                        |
|    |                           | should see a full refund  | arrived damaged. The     | partial_args=None         | partial_args=None         |                             |                        |
|    |                           | of $35.0 back to your     | status of that order has | will_continue=None id= 'a | will_continue=None        |                             |                        |
|    |                           | original payment method   | been updated to          | dk-8a194cb8-5a82-47ce-a3a | id='adk- dad1b376-9bcc-48 |                             |                        |
|    |                           | shortly. The status of    | "refunded."  Is there    | 7- 3d24551f8c90'          | bb-996f-a30f6ef5b70b'     |                             |                        |
|    |                           | this order has been       | anything else I can      | args={'reason':           | args={'reason':           |                             |                        |
|    |                           | updated to "refunded".    | assist you with today?   | 'damaged', 'order_id':    | 'damaged', 'order_id':    |                             |                        |
|    |                           | Here's your updated       |                          | 'ORD-102'}                | 'ORD-102'}                |                             |                        |
|    |                           | purchase history for      |                          | name='issue_refund'       | name='issue_refund'       |                             |                        |
|    |                           | CUST001: *   **ORD-101**: |                          | partial_args=None         | partial_args=None         |                             |                        |
|    |                           | Wireless Headphones,      |                          | will_continue=None        | will_continue=None        |                             |                        |
|    |                           | delivered on 2023-10-15   |                          |                           |                           |                             |                        |
|    |                           | (Total: $120) *           |                          |                           |                           |                             |                        |
|    |                           | **ORD-102**: USB-C Cable, |                          |                           |                           |                             |                        |
|    |                           | Phone Case, refunded on   |                          |                           |                           |                             |                        |
|    |                           | 2023-11-01 (Total: $35)   |                          |                           |                           |                             |                        |
|    |                           | Is there anything else I  |                          |                           |                           |                             |                        |
|    |                           | can help you with today?  |                          |                           |                           |                             |                        |
|    |                           | 😊                         |                          |                           |                           |                             |                        |
+----+---------------------------+---------------------------+--------------------------+---------------------------+---------------------------+-----------------------------+------------------------+

Lưu ý: Vì bạn vừa tạo thông tin này từ chính tác nhân, nên thông tin này sẽ vượt qua 100%. Nếu không thành công, tức là tác nhân của bạn không xác định được (ngẫu nhiên).

7. Tạo bài kiểm tra tuỳ chỉnh của riêng bạn

Mặc dù các tập dữ liệu được tạo tự động rất hữu ích, nhưng đôi khi bạn cần tạo các trường hợp biên theo cách thủ công (ví dụ: các cuộc tấn công đối nghịch hoặc xử lý lỗi cụ thể). Hãy xem cách eval.test.json cho phép bạn xác định "Tính chính xác".

Hãy tạo một bộ kiểm thử toàn diện.

Khung kiểm thử

Khi viết một trường hợp kiểm thử trong ADK, hãy làm theo Công thức gồm 3 phần này:

  • Thiết lập (session_input): Người dùng là ai? (ví dụ: user_id, state). Thao tác này sẽ cô lập quy trình kiểm thử.
  • Câu lệnh (user_content): Điều gì kích hoạt câu lệnh?

Với Các câu khẳng định (Kỳ vọng):

  • Quỹ đạo (tool_uses): Có tính toán chính xác không? (Logic)
  • Câu trả lời (final_response): Câu trả lời có chính xác không? (Chất lượng)
  • Trung cấp (intermediate_responses): Các tác nhân phụ có nói đúng không? (Điều phối)

Viết Bộ kiểm thử

👉 Mở customer_service_agent/eval.test.json trong trình chỉnh sửa.

Nhập mã sau:

{
  "eval_set_id": "customer_service_eval",
  "name": "Customer Service Agent Evaluation",
  "description": "Evaluation suite for the customer service agent covering product info, purchase history, and refunds.",
  "eval_cases": [
    {
      "eval_id": "product_info_check",
      "session_input": {
        "app_name": "customer_service_agent",
        "user_id": "eval_user_1",
        "state": {}
      },
      "conversation": [
        {
          "invocation_id": "turn_1_product_info",
          "user_content": {
            "role": "user",
            "parts": [
              {
                "text": "Do you have wireless headphones in stock?"
              }
            ]
          },
          "final_response": {
            "role": "model",
            "parts": [
              {
                "text": "Yes, we have wireless headphones in stock! They are priced at $120.00 and feature noise-canceling with a 20-hour battery life. 🎧"
              }
            ]
          },
          "intermediate_data": {
            "tool_uses": [
              {
                "name": "lookup_product_info",
                "args": {
                  "product_name": "wireless headphones"
                }
              }
            ],
            "intermediate_responses": []
          }
        }
      ]
    },
    {
      "eval_id": "purchase_history_check",
      "session_input": {
        "app_name": "customer_service_agent",
        "user_id": "eval_user_2",
        "state": {}
      },
      "conversation": [
        {
          "invocation_id": "turn_1_purchase_history",
          "user_content": {
            "role": "user",
            "parts": [
              {
                "text": "What did I buy recently? My customer ID is CUST001."
              }
            ]
          },
          "final_response": {
            "role": "model",
            "parts": [
              {
                "text": "Here's your recent purchase history for Customer ID CUST001:\n\n*   **Order ORD-101** (October 15, 2023): Wireless Headphones, Status: delivered, Total: $120\n*   **Order ORD-102** (November 1, 2023): USB-C Cable, Phone Case, Status: refunded, Total: $35\n\nLet me know if you have any other questions or need further assistance! 🛍️"
              }
            ]
          },
          "intermediate_data": {
            "tool_uses": [
              {
                "name": "get_purchase_history",
                "args": {
                  "customer_id": "CUST001"
                }
              }
            ],
            "intermediate_responses": []
          }
        }
      ]
    },
    {
      "eval_id": "refund_request",
      "session_input": {
        "app_name": "customer_service_agent",
        "user_id": "eval_user_3",
        "state": {}
      },
      "conversation": [
        {
          "invocation_id": "turn_1_refund",
          "user_content": {
            "role": "user",
            "parts": [
              {
                "text": "I want a refund for order ORD-102 because it was damaged."
              }
            ]
          },
          "final_response": {
            "role": "model",
            "parts": [
              {
                "text": "Your refund for order **ORD-102** due to \"damaged\" has been successfully processed!  Refund amount: **$35.0**. Your order status has been updated to **refunded**. \nIs there anything else I can help you with today? 🛍️"
              }
            ]
          },
          "intermediate_data": {
            "tool_uses": [
              {
                "name": "issue_refund",
                "args": {
                  "order_id": "ORD-102",
                  "reason": "damaged"
                }
              }
            ],
            "intermediate_responses": []
          }
        }
      ]
    }
  ]
}

Phân tích các loại kiểm thử

Chúng tôi đã tạo ra 3 loại thử nghiệm riêng biệt tại đây. Hãy cùng tìm hiểu xem mỗi chỉ số đánh giá điều gì và tại sao.

  1. Bài kiểm thử một công cụ (product_info_check)
  • Mục tiêu: Xác minh khả năng truy xuất thông tin cơ bản.
  • Key Assertion (Xác nhận chính): Chúng tôi kiểm tra intermediate_data.tool_uses. Chúng tôi khẳng định rằng lookup_product_info được gọi. Chúng ta khẳng định đối số product_name chính xác là "tai nghe không dây".
  • Lý do: Nếu mô hình đưa ra một mức giá ảo mà không gọi công cụ, thì kiểm thử này sẽ thất bại. Điều này giúp đảm bảo việc tiếp đất.
  1. Thử nghiệm trích xuất bối cảnh (purchase_history_check)
  • Mục tiêu: Xác minh rằng trợ lý có thể trích xuất các thực thể (CUST001) từ câu lệnh của người dùng và chuyển các thực thể đó đến công cụ.
  • Key Assertion (Xác nhận khoá): Chúng tôi kiểm tra để đảm bảo rằng get_purchase_history được gọi bằng customer_id: "CUST001".
  • Lý do: Một chế độ lỗi thường gặp là tác nhân gọi đúng công cụ nhưng có mã nhận dạng rỗng. Điều này giúp đảm bảo độ chính xác của tham số.
  1. Bài kiểm tra hành động/quỹ đạo (refund_request)
  • Mục tiêu: Xác minh một thao tác ghi quan trọng.
  • Tuyên bố chính: Quỹ đạo. Trong một trường hợp phức tạp hơn, danh sách này sẽ chứa nhiều bước: [verify_order, calculate_refund, issue_refund]. ADK kiểm tra danh sách này Theo thứ tự.
  • Lý do: Đối với những hành động chuyển tiền hoặc thay đổi dữ liệu, trình tự quan trọng không kém kết quả. Bạn không muốn hoàn tiền trước khi xác minh.

8. Chạy quy trình đánh giá cho các kiểm thử tuỳ chỉnh (adk eval)

vòng lặp bên trong

👉 Trong thiết bị đầu cuối, hãy chạy:

cd ~/adk_eval_starter
uv run adk eval customer_service_agent customer_service_agent/eval.test.json --config_file_path=customer_service_agent/test_config.json --print_detailed_results

Tìm hiểu về đầu ra

Bạn sẽ thấy kết quả PASS (ĐẠT) như sau:

Eval Run Summary
customer_service_eval:
  Tests passed: 3
  Tests failed: 0
********************************************************************
Eval Set Id: customer_service_eval
Eval Id: purchase_history_check
Overall Eval Status: PASSED
---------------------------------------------------------------------
Metric: tool_trajectory_avg_score, Status: PASSED, Score: 1.0, Threshold: 0.8
---------------------------------------------------------------------
Metric: response_match_score, Status: PASSED, Score: 0.5473684210526315, Threshold: 0.5
---------------------------------------------------------------------
Invocation Details:
+----+--------------------------+---------------------------+---------------------------+---------------------------+---------------------------+-----------------------------+------------------------+
|    | prompt                   | expected_response         | actual_response           | expected_tool_calls       | actual_tool_calls         | tool_trajectory_avg_score   | response_match_score   |
+====+==========================+===========================+===========================+===========================+===========================+=============================+========================+
|  0 | What did I buy recently? | Here's your recent        | Looks like your recent    | id=None                   | id='adk-8960eb53-2933-459 | Status: PASSED, Score:      | Status: PASSED, Score: |
|    | My customer ID is        | purchase history for      | orders include: *         | args={'customer_id':      | f-b306- 71e3c069e77e'     | 1.0                         | 0.5473684210526315     |
|    | CUST001.                 | Customer ID CUST001:  *   | **ORD-101 (2023-10-15):** | 'CUST001'} name='get_purc | args={'customer_id':      |                             |                        |
|    |                          | **Order ORD-101**         | Wireless Headphones for   | hase_history'             | 'CUST001'} name='get_purc |                             |                        |
|    |                          | (October 15, 2023):       | $120.00 - Status:         | partial_args=None         | hase_history'             |                             |                        |
|    |                          | Wireless Headphones,      | Delivered 🎧 *   **ORD-102 | will_continue=None        | partial_args=None         |                             |                        |
|    |                          | Status: delivered, Total: | (2023-11-01):** USB-C     |                           | will_continue=None        |                             |                        |
|    |                          | $120 *   **Order          | Cable, Phone Case for     |                           |                           |                             |                        |
|    |                          | ORD-102** (November 1,    | $35.00 - Status: Refunded |                           |                           |                             |                        |
|    |                          | 2023): USB-C Cable, Phone | 📱  Is there anything else |                           |                           |                             |                        |
|    |                          | Case, Status: refunded,   | I can help you with       |                           |                           |                             |                        |
|    |                          | Total: $35  Let me know   | regarding these orders?   |                           |                           |                             |                        |
|    |                          | if you have any other     |                           |                           |                           |                             |                        |
|    |                          | questions or need further |                           |                           |                           |                             |                        |
|    |                          | assistance! 🛍️            |                           |                           |                           |                             |                        |
+----+--------------------------+---------------------------+---------------------------+---------------------------+---------------------------+-----------------------------+------------------------+



********************************************************************
Eval Set Id: customer_service_eval
Eval Id: product_info_check
Overall Eval Status: PASSED
---------------------------------------------------------------------
Metric: tool_trajectory_avg_score, Status: PASSED, Score: 1.0, Threshold: 0.8
---------------------------------------------------------------------
Metric: response_match_score, Status: PASSED, Score: 0.6829268292682927, Threshold: 0.5
---------------------------------------------------------------------
Invocation Details:
+----+----------------------+---------------------------+---------------------------+---------------------------+---------------------------+-----------------------------+------------------------+
|    | prompt               | expected_response         | actual_response           | expected_tool_calls       | actual_tool_calls         | tool_trajectory_avg_score   | response_match_score   |
+====+======================+===========================+===========================+===========================+===========================+=============================+========================+
|  0 | Do you have wireless | Yes, we have wireless     | Yes, we do! 🎧 We have     | id=None                   | id='adk-4571d660-a92b-412 | Status: PASSED, Score:      | Status: PASSED, Score: |
|    | headphones in stock? | headphones in stock! They | noise-canceling wireless  | args={'product_name':     | a-a79e- 5c54f8b8af2d'     | 1.0                         | 0.6829268292682927     |
|    |                      | are priced at $120.00 and | headphones with a 20-hour | 'wireless headphones'} na | args={'product_name':     |                             |                        |
|    |                      | feature noise-canceling   | battery life available    | me='lookup_product_info'  | 'wireless headphones'} na |                             |                        |
|    |                      | with a 20-hour battery    | for $120.                 | partial_args=None         | me='lookup_product_info'  |                             |                        |
|    |                      | life. 🎧                   |                           | will_continue=None        | partial_args=None         |                             |                        |
|    |                      |                           |                           |                           | will_continue=None        |                             |                        |
+----+----------------------+---------------------------+---------------------------+---------------------------+---------------------------+-----------------------------+------------------------+



********************************************************************
Eval Set Id: customer_service_eval
Eval Id: refund_request
Overall Eval Status: PASSED
---------------------------------------------------------------------
Metric: tool_trajectory_avg_score, Status: PASSED, Score: 1.0, Threshold: 0.8
---------------------------------------------------------------------
Metric: response_match_score, Status: PASSED, Score: 0.6216216216216216, Threshold: 0.5
---------------------------------------------------------------------
Invocation Details:
+----+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+-----------------------------+------------------------+
|    | prompt                    | expected_response         | actual_response           | expected_tool_calls       | actual_tool_calls         | tool_trajectory_avg_score   | response_match_score   |
+====+===========================+===========================+===========================+===========================+===========================+=============================+========================+
|  0 | I want a refund for order | Your refund for order     | Your refund for order     | id=None args={'order_id': | id='adk-fb8ff1cc- cf87-41 | Status: PASSED, Score:      | Status: PASSED, Score: |
|    | ORD-102 because it was    | **ORD-102** due to        | **ORD-102** has been      | 'ORD-102', 'reason':      | f2-9b11-d4571b14287f'     | 1.0                         | 0.6216216216216216     |
|    | damaged.                  | "damaged" has been        | successfully processed!   | 'damaged'}                | args={'order_id':         |                             |                        |
|    |                           | successfully processed!   | You should see a full     | name='issue_refund'       | 'ORD-102', 'reason':      |                             |                        |
|    |                           | Refund amount: **$35.0**. | refund of $35.0 appear in | partial_args=None         | 'damaged'}                |                             |                        |
|    |                           | Your order status has     | your account shortly. We  | will_continue=None        | name='issue_refund'       |                             |                        |
|    |                           | been updated to           | apologize for the         |                           | partial_args=None         |                             |                        |
|    |                           | **refunded**.  Is there   | inconvenience! Is there   |                           | will_continue=None        |                             |                        |
|    |                           | anything else I can help  | anything else I can       |                           |                           |                             |                        |
|    |                           | you with today? 🛍️        | assist you with today? 😊  |                           |                           |                             |                        |
+----+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+-----------------------------+------------------------+

Điều này có nghĩa là trợ lý ảo đã sử dụng đúng công cụ và đưa ra câu trả lời tương đối giống với những gì bạn mong đợi.

9. (Không bắt buộc: Chỉ đọc) – Khắc phục sự cố và gỡ lỗi

Các kiểm thử sẽ không thành công. Đó là công việc của họ. Nhưng làm cách nào để khắc phục những vấn đề đó? Hãy phân tích các trường hợp lỗi thường gặp và cách gỡ lỗi.

Tình huống A: Lỗi "Quỹ đạo"

Lỗi:

Result: FAILED
Reason: Criteria 'tool_trajectory_avg_score' failed. Score 0.0 < Threshold 1.0
Details:
EXPECTED: tool: lookup_order, then tool: issue_refund
ACTUAL:   tool: issue_refund

Chẩn đoán: Nhân viên hỗ trợ đã bỏ qua bước xác minh (lookup_order). Đây là một lỗi logic.

Cách khắc phục sự cố:

  • Đừng đoán: Quay lại Giao diện người dùng web ADK (adk web).
  • Tái tạo: Nhập chính xác câu lệnh của lần kiểm thử không thành công vào cuộc trò chuyện.
  • Trace (Dấu vết): Mở chế độ xem Dấu vết. Xem thẻ "Biểu đồ".
  • Sửa câu lệnh: Thông thường, bạn cần cập nhật Câu lệnh hệ thống. Thay đổi: "Bạn là một trợ lý hữu ích." Đến: "Bạn là một nhân viên hỗ trợ hữu ích. QUAN TRỌNG: Bạn PHẢI gọi lookup_order để xác minh thông tin chi tiết trước khi gọi issue_refund."
  • Điều chỉnh bài kiểm thử: Nếu logic nghiệp vụ thay đổi (ví dụ: không cần xác minh nữa), thì bài kiểm thử đó là sai. Cập nhật eval.test.json để phù hợp với thực tế mới.

Tình huống B: Lỗi "ROUGE"

Lỗi:

Result: FAILED
Reason: Criteria 'response_match_score' failed. Score 0.45 < Threshold 0.8
Expected: "The refund has been processed successfully."
Actual:   "I've gone ahead and returned the money to your card."

Chẩn đoán: Nhân viên đã làm đúng nhưng dùng từ khác. ROUGE (từ trùng lặp) đã phạt chỉ số này.

Cách khắc phục:

  • Có gì sai không? Nếu ý nghĩa chính xác, đừng thay đổi câu lệnh.
  • Điều chỉnh ngưỡng: Giảm ngưỡng trong test_config.json (ví dụ: từ 0.8 xuống 0.5).
  • Nâng cấp chỉ số: Chuyển sang final_response_match_v2 trong cấu hình của bạn. Tính năng này sử dụng một LLM để đọc cả hai câu và đánh giá xem chúng có cùng nghĩa hay không.

10. CI/CD với Pytest (pytest)

pytest

Lệnh CLI dành cho người dùng. pytest là dành cho máy móc. Để đảm bảo độ tin cậy của quy trình sản xuất, chúng tôi gói các quy trình đánh giá trong một bộ thử nghiệm Python. Điều này cho phép quy trình CI/CD (GitHub Actions, Jenkins) chặn việc triển khai nếu tác nhân bị giảm hiệu suất.

Tệp này có nội dung gì?

Tệp Python này đóng vai trò là cầu nối giữa trình chạy CI/CD và trình đánh giá ADK. Bạn cần:

  • Tải Agent: Nhập mã agent một cách linh động.
  • Đặt lại trạng thái: Đảm bảo bộ nhớ của tác nhân không bị ảnh hưởng để các kiểm thử không bị ảnh hưởng lẫn nhau.
  • Chạy quy trình đánh giá: Gọi AgentEvaluator.evaluate() theo phương thức lập trình.
  • Xác nhận thành công: Nếu điểm đánh giá thấp, hãy không tạo bản dựng.

Mã kiểm thử tích hợp

👉 Mở customer_service_agent/test_agent_eval.py. Tập lệnh này dùng AgentEvaluator.evaluate để chạy các kiểm thử được xác định trong eval.test.json.

👉 Mở customer_service_agent/test_agent_eval.py trong trình chỉnh sửa.

Nhập mã sau:

from google.adk.evaluation.agent_evaluator import AgentEvaluator
import pytest
import importlib
import sys
import os

@pytest.mark.asyncio
async def test_with_single_test_file():
    """Test the agent's basic ability via a session file."""
    # Load the agent module robustly
    module_name = "customer_service_agent.agent"
    try:
        agent_module = importlib.import_module(module_name)
        # Reset the mock data to ensure a fresh state for the test
        if hasattr(agent_module, 'reset_mock_data'):
            agent_module.reset_mock_data()
    except ImportError:
        # Fallback if running from a different context
        sys.path.append(os.getcwd())
        agent_module = importlib.import_module(module_name)
        if hasattr(agent_module, 'reset_mock_data'):
            agent_module.reset_mock_data()
    
    # Use absolute path to the eval file to be robust to where pytest is run
    script_dir = os.path.dirname(os.path.abspath(__file__))
    eval_file = os.path.join(script_dir, "eval.test.json")
    
    await AgentEvaluator.evaluate(
        agent_module=module_name,
        eval_dataset_file_path_or_dir=eval_file,
        num_runs=1,
    )

Chạy Pytest

👉 Trong thiết bị đầu cuối, hãy chạy:

cd ~/adk_eval_starter
uv pip install pytest
uv run pytest customer_service_agent/test_agent_eval.py

Bạn sẽ thấy kết quả như sau:

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=============== 1 passed, 15 warnings in 12.84s ===============

11. Kết luận

Xin chúc mừng! Bạn đã đánh giá thành công nhân viên dịch vụ khách hàng bằng ADK Eval.

Kiến thức bạn học được

Trong lớp học lập trình này, bạn đã tìm hiểu cách:

  • Tạo một Tập dữ liệu vàng để thiết lập giá trị thực cho tác nhân của bạn.
  • Tìm hiểu Cấu hình đánh giá để xác định tiêu chí thành công.
  • Chạy quy trình Đánh giá tự động để phát hiện sớm các lỗi hồi quy.

Bằng cách kết hợp ADK Eval vào quy trình phát triển, bạn có thể tự tin tạo các tác nhân, vì biết rằng mọi thay đổi về hành vi sẽ được các bài kiểm thử tự động phát hiện.