1- فجوة الثقة
لحظة الإلهام
لقد أنشأت وكيل خدمة عملاء. يعمل هذا التطبيق على جهازك. لكنّها أبلغت أحد العملاء أمس بأنّ "الساعة الذكية" غير المتوفّرة في المخزون متاحة، أو الأسوأ من ذلك، أنّها قدّمت معلومات غير صحيحة عن سياسة ردّ الأموال. كيف تنام في الليل وأنت تعلم أنّ موظف الدعم يتحدث مع العملاء؟
لتقليل الفجوة بين نموذج أوّلي وعميل ذكاء اصطناعي جاهز للاستخدام، من الضروري توفير إطار تقييم قوي ومبرمَج.

ما الذي نقيّمه في الواقع؟
يُعدّ تقييم الوكيل أكثر تعقيدًا من تقييم نماذج اللغات الكبيرة العادية. أنت لا تقيّم المقالة (الردّ النهائي) فقط، بل تقيّم الرياضيات (المنطق/الأدوات المستخدَمة للوصول إلى الردّ).

- المسار (العملية): هل استخدم الوكيل الأداة المناسبة في الوقت المناسب؟ هل اتصلتُ بـ
check_inventoryقبلplace_order؟ - الرد النهائي (الناتج): هل الإجابة صحيحة ومهذبة ومستندة إلى البيانات؟
مراحل التطوير
في هذا الدرس التطبيقي حول الترميز، سنتعرّف على دورة حياة اختبار الوكيل الاحترافية:
- الفحص المرئي المحلي (واجهة مستخدم الويب في "حزمة تطوير التطبيقات"): الدردشة يدويًا والتحقّق من المنطق (الخطوة 1)
- اختبار الوحدة/اختبار الانحدار (واجهة سطر الأوامر في حزمة تطوير التطبيقات): تنفيذ حالات اختبار معيّنة على الجهاز لاكتشاف الأخطاء بسرعة (الخطوتان 3 و4)
- تصحيح الأخطاء (تحديد المشاكل وحلّها): تحليل حالات الفشل وإصلاح منطق الطلب (الخطوة 5)
- دمج CI/CD (Pytest): أتمتة الاختبارات في مسار الإنشاء (الخطوة 6)
2. إعداد
لتشغيل وكلاء الذكاء الاصطناعي، نحتاج إلى أمرين: مشروع على Google Cloud لتوفير الأساس.
الخطوة 1: تفعيل حساب الفوترة
- للمطالبة بحساب الفوترة الذي يتضمّن رصيدًا بقيمة 5 دولار أمريكي، ستحتاج إليه عند نشر تطبيقك. تأكَّد من تسجيل الدخول إلى حسابك على Gmail.
الخطوة 2: فتح "البيئة"
👉 انقر على "تفعيل Cloud Shell" في أعلى "وحدة تحكّم Google Cloud" (رمز شكل الوحدة الطرفية في أعلى لوحة Cloud Shell).

👉 انقر على الزر "فتح المحرّر" (يبدو كملف مفتوح مع قلم رصاص). سيؤدي ذلك إلى فتح "محرِّر Cloud Shell" في النافذة. سيظهر لك مستكشف الملفات على الجانب الأيمن. 
👉افتح المحطة الطرفية في بيئة التطوير المتكاملة المستندة إلى السحابة الإلكترونية، 
👉💻 في نافذة الأوامر، تأكَّد من أنّك قد أثبتّ هويتك وأنّ المشروع مضبوط على رقم تعريف مشروعك باستخدام الأمر التالي:
gcloud auth list
👉💻 استنسِخ مشروع bootstrap من GitHub:
git clone https://github.com/cuppibla/adk_eval_starter
👉💻 شغِّل نص الإعداد البرمجي من دليل المشروع.
⚠️ ملاحظة حول معرّف المشروع: سيقترح النص البرمجي معرّف مشروع تلقائيًا تم إنشاؤه عشوائيًا. يمكنك الضغط على Enter لقبول هذا الإعداد التلقائي.
ومع ذلك، إذا كنت تفضّل إنشاء مشروع جديد محدّد، يمكنك كتابة رقم تعريف المشروع المطلوب عندما يطلب منك النص البرمجي ذلك.
cd ~/adk_eval_starter
./init.sh
سيتولّى النص البرمجي بقية عملية الإعداد تلقائيًا.
👉 خطوة مهمة بعد الإكمال: بعد انتهاء البرنامج النصي، عليك التأكّد من أنّ Google Cloud Console يعرض المشروع الصحيح:
- انتقِل إلى console.cloud.google.com.
- انقر على القائمة المنسدلة الخاصة بأداة اختيار المشاريع في أعلى الصفحة.
- انقر على علامة التبويب "الكل" (لأنّ المشروع الجديد قد لا يظهر في "الأحدث" بعد).
- اختَر رقم تعريف المشروع الذي أعددته للتو في الخطوة
init.sh.

👉💻 اضبط رقم تعريف المشروع المطلوب:
gcloud config set project $(cat ~/project_id.txt) --quiet
إعداد الإذن
👉💻 فعِّل واجهات برمجة التطبيقات المطلوبة باستخدام الأمر التالي. قد يستغرق هذا بضع دقائق.
gcloud services enable \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
aiplatform.googleapis.com \
compute.googleapis.com
👉💻 امنح الأذونات اللازمة من خلال تنفيذ الأوامر التالية في الوحدة الطرفية:
. ~/adk_eval_starter/set_env.sh
لاحظ أنّه تم إنشاء ملف .env لك. تعرض هذه الصفحة معلومات مشروعك.
3- إنشاء مجموعة البيانات الذهبية (الويب adk)

قبل أن نتمكّن من تقييم الوكيل، نحتاج إلى مفتاح إجابة. في "أداة تطوير الإعلانات"، نسمّي ذلك مجموعة البيانات الذهبية. تحتوي مجموعة البيانات هذه على تفاعلات "مثالية" تُستخدَم كمرجع أساسي للتقييم.
ما هي مجموعة البيانات الذهبية؟
مجموعة البيانات الذهبية هي لقطة لوكيلك وهو يؤدي مهامه بشكل صحيح. وهي ليست مجرد قائمة بأزواج من الأسئلة والأجوبة. تسجّل هذه الأداة ما يلي:
- طلب المستخدم ("أريد استرداد الأموال")
- المسار (التسلسل الدقيق لعمليات استدعاء الأدوات:
check_order->verify_eligibility->refund_transaction) - الردّ النهائي (الردّ النصي "المثالي")
نستخدم هذا الإجراء لرصد التحسينات التي تم التراجع عنها. إذا عدّلت طلبك وتوقّف الوكيل فجأة عن التحقّق من الأهلية قبل ردّ الأموال، سيفشل اختبار "مجموعة البيانات الذهبية" لأنّ المسار لم يعُد مطابقًا.
فتح واجهة مستخدم الويب
توفّر واجهة مستخدم الويب الخاصة بـ "حزمة تطوير التطبيقات" طريقة تفاعلية لإنشاء مجموعات البيانات الذهبية هذه من خلال تسجيل التفاعلات الفعلية مع وكيلك.
👉 في الوحدة الطرفية، نفِّذ ما يلي:
cd ~/adk_eval_starter
uv run adk web
👉 افتح معاينة واجهة مستخدم الويب (عادةً ما تكون متاحة على http://127.0.0.1:8000).
👉 في واجهة مستخدم المحادثة، اكتب
Hi, I'm customer CUST001. Can you check my orders? I need a refund for order ORD-102. It arrived damaged.

سيظهر لك ردّ مثل:
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? 🛍️
تسجيل التفاعلات الذهبية
انتقِل إلى علامة التبويب الجلسات. يمكنك هنا الاطّلاع على سجلّ محادثات وكيلك من خلال النقر على الجلسة.
- التفاعل مع الوكيل لإنشاء مسار محادثة مثالي، مثل الاطّلاع على سجلّ الشراء أو طلب استرداد الأموال
- راجِع المحادثة للتأكّد من أنّها تمثّل السلوك المتوقّع.

4. تصدير مجموعة البيانات الذهبية
إجراء عملية التحقّق باستخدام "عرض سجلّ التتبُّع"
قبل التصدير، يجب التأكّد من أنّ الوكيل لم يحصل على الإجابة الصحيحة بمحض الصدفة. عليك فحص المنطق الداخلي.
- انقر على علامة التبويب التتبُّع في واجهة مستخدم الويب.
- يتم تجميع عمليات التتبُّع تلقائيًا حسب رسالة المستخدِم. مرِّر مؤشر الماوس فوق صف تتبُّع لتمييز الرسالة المقابلة في المحادثة.
- فحص الصفوف الزرقاء: تشير هذه الصفوف إلى الأحداث التي تم إنشاؤها من التفاعل. انقر على أحد الصفوف الزرقاء لفتح لوحة الفحص.
- راجِع علامات التبويب التالية للتحقّق من صحة المنطق:
- الرسم البياني: تمثيل مرئي لعمليات استدعاء الأدوات وسير المنطق هل اتّخذ المسار الصحيح؟
- الطلب/الردّ: يمكنك مراجعة ما تم إرساله إلى النموذج وما تم تلقّيه منه.
- التحقّق: إذا خمّن الموظف مبلغ ردّ الأموال بدون استخدام أداة قاعدة البيانات، يُعرف ذلك باسم "الهلوسة المحظوظة".

Add Session to EvalSet
بعد الاقتناع بالمحادثة والتتبُّع: 👉 انقر على علامة التبويب Eval، ثم على الزر Create Evaluation Set، ثم أدخِل اسم التقييم الذي تريد أن يكون:
evalset1

👉 في مجموعة التقييم هذه، انقر على Add current session to evalset1، وفي النافذة المنبثقة، أدخِل اسم الجلسة على النحو التالي:
eval1

تشغيل Eval في ADK Web
👉 في واجهة مستخدم الويب الخاصة بـ "حزمة تطوير التطبيقات"، انقر على Run Evaluation، وفي النافذة المنبثقة، عدِّل المقاييس، ثم انقر على Start:

التحقّق من صحة مجموعة البيانات في المستودع
ستظهر لك رسالة تأكيد بأنّه تم إنشاء ملف مجموعة بيانات (مثل تم حفظ evalset1.evalset.json) في مستودعك. يحتوي هذا الملف على سجلّ المحادثة الأوّلي الذي تم إنشاؤه تلقائيًا.

5- ملفات التقييم

مع أنّ واجهة مستخدم الويب تنشئ ملف .evalset.json معقّدًا، غالبًا ما نريد إنشاء ملف اختبار أكثر وضوحًا وتنظيمًا لإجراء الاختبارات المبرمَجة.
تستخدم أداة ADK Eval مكوّنَين رئيسيَّين:
- ملفات الاختبار: يمكن أن تكون مجموعة البيانات الذهبية التي يتم إنشاؤها تلقائيًا (مثل
customer_service_agent/evalset1.evalset.json) أو مجموعة منسّقة يدويًا (مثلcustomer_service_agent/eval.test.json). - ملفات الإعداد (مثل
customer_service_agent/test_config.json): حدِّد المقاييس والحدود الدنيا لاجتياز الاختبار.
إعداد ملف إعدادات الاختبار
👉 افتح customer_service_agent/test_config.json في المحرّر.
أدخِل الرمز التالي:
{
"criteria": {
"tool_trajectory_avg_score": 0.8,
"response_match_score": 0.5
}
}
تفسير المقاييس
tool_trajectory_avg_score(العملية) يقيس هذا المقياس ما إذا كان الموظف قد استخدم الأدوات بشكل صحيح.
- 0.8: نطلب مطابقة بنسبة% 80.
response_match_score(الناتج) تستخدم هذه السمة ROUGE-1 (تداخل الكلمات) لمقارنة الإجابة بالمرجع الذهبي.
- المزايا: سريع، ومحدّد، ومجاني.
- العيوب: يتعذّر تنفيذها إذا عبّر الوكيل عن الفكرة نفسها بطريقة مختلفة (مثلاً "تم ردّ الأموال" مقابل "تم إرجاع الأموال").
المقاييس المتقدّمة (عندما تحتاج إلى المزيد من الإمكانات)
6. تنفيذ التقييم لمجموعة البيانات الذهبية (adk eval)

تمثّل هذه الخطوة "الحلقة الداخلية" للتطوير. أنت مطوّر تجري تغييرات وتريد التحقّق من النتائج بسرعة.
تشغيل مجموعة البيانات الذهبية
لننفّذ مجموعة البيانات التي أنشأتها في الخطوة 1. يضمن ذلك أن يكون خط الأساس متينًا.
👉 في الوحدة الطرفية، نفِّذ ما يلي:
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
ما هي المشكلة؟
أصبحت حزمة تطوير التطبيقات (ADK) الآن:
- جارٍ تحميل وكيلك من
customer_service_agent. - جارٍ تنفيذ طلبات الإدخال من
evalset1.evalset.json. - مقارنة المسار الفعلي للوكيل وردوده بالمسار والردود المتوقّعة
- تسجيل النتائج استنادًا إلى المعايير الواردة في
test_config.json
تحليل النتائج
شاهِد ناتج المحطة الطرفية. سيظهر لك ملخّص للاختبارات التي تم اجتيازها وتلك التي لم يتم اجتيازها.
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? | | | | | |
| | | 😊 | | | | | |
+----+---------------------------+---------------------------+--------------------------+---------------------------+---------------------------+-----------------------------+------------------------+
ملاحظة: بما أنّك أنشأت هذا الرمز المميز من البرنامج نفسه، من المفترض أن يحقق نسبة نجاح تبلغ %100. إذا تعذّر ذلك، يكون الوكيل غير حتمي (عشوائي).
7. إنشاء اختبار مخصّص
على الرغم من أنّ مجموعات البيانات التي يتم إنشاؤها تلقائيًا رائعة، إلا أنّك تحتاج أحيانًا إلى إنشاء حالات استخدام متطرفة يدويًا (مثل الهجمات الخصومية أو معالجة الأخطاء المحدّدة). لنلقِ نظرة على كيفية السماح لك eval.test.json بتحديد "الصحة".
لننشئ مجموعة اختبار شاملة.
إطار الاختبار
عند كتابة حالة اختبار في ADK، اتّبِع هذه الصيغة المكوّنة من 3 أجزاء:
- مرحلة الإعداد (
session_input): من هو المستخدم؟ (مثال:user_id،state). يؤدي ذلك إلى عزل الاختبار. - الطلب (
user_content): ما هو عامل التشغيل؟
مع التأكيدات (التوقّعات):
- المسار (
tool_uses): هل تم إجراء العملية الحسابية بشكل صحيح؟ (المنطق) - الردّ (
final_response): هل ذكرت الإجابة الصحيحة؟ (الجودة) - المستوى المتوسط (
intermediate_responses): هل تحدث الوكلاء الفرعيون بشكل صحيح؟ (التنظيم)
كتابة مجموعة الاختبارات
👉 افتح customer_service_agent/eval.test.json في المحرّر.
أدخِل الرمز التالي:
{
"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": []
}
}
]
}
]
}
تفكيك أنواع الاختبارات
لقد أنشأنا ثلاثة أنواع مختلفة من الاختبارات هنا. دعنا نوضّح ما يقيّمه كلّ مقياس وسبب ذلك.
- اختبار الأداة الفردية (
product_info_check)
- الهدف: التحقّق من إمكانية استرداد المعلومات الأساسية.
- البيان الأساسي: نتحقّق من
intermediate_data.tool_uses. نؤكّد أنّه تم استدعاءlookup_product_info. نؤكّد أنّ وسيطة البحثproduct_nameهي "سماعات رأس لاسلكية" بالضبط. - السبب: إذا قدّم النموذج سعرًا من دون استدعاء الأداة، سيفشل هذا الاختبار. يضمن ذلك أن تكون الإجابة مستندة إلى معلومات واقعية.
- اختبار استخراج السياق (
purchase_history_check)
- الهدف: التحقّق من قدرة الوكيل على استخراج الكيانات (CUST001) من طلب المستخدم وتمريرها إلى الأداة.
- تأكيد المفتاح: نتحقّق من أنّه تم استدعاء
get_purchase_historyباستخدامcustomer_id: "CUST001". - السبب: أحد أوضاع الإخفاق الشائعة هو أن يستدعي الوكيل الأداة الصحيحة ولكن برقم تعريف فارغ. يضمن ذلك دقة المَعلمات.
- اختبار الإجراء/المسار (
refund_request)
- الهدف: التحقّق من عملية كتابة مهمة.
- الفرضية الأساسية: المسار في سيناريو أكثر تعقيدًا، ستتضمّن هذه القائمة خطوات متعدّدة:
[verify_order, calculate_refund, issue_refund]. يتحقّق ADK من هذه القائمة بالترتيب. - السبب: بالنسبة إلى الإجراءات التي تنقل الأموال أو تغيّر البيانات، يكون التسلسل مهمًا مثل النتيجة. لا تريد ردّ الأموال قبل إثبات الملكية.
8. تشغيل التقييم للاختبارات المخصّصة ( adk eval)

👉 في الوحدة الطرفية، نفِّذ ما يلي:
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
فهم الناتج
يجب أن تظهر لك نتيجة PASS على النحو التالي:
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? 😊 | | | | |
+----+---------------------------+---------------------------+---------------------------+---------------------------+---------------------------+-----------------------------+------------------------+
وهذا يعني أنّ الوكيل استخدم الأدوات الصحيحة وقدّم ردًا مشابهًا لتوقّعاتك إلى حدّ كبير.
9- (اختياري: للقراءة فقط) - تحديد المشاكل وحلّها وتصحيح الأخطاء
ستفشل الاختبارات. هذه هي وظيفتهم. ولكن كيف يمكن إصلاحها؟ لنحلّل سيناريوهات الأعطال الشائعة وكيفية تصحيحها.
السيناريو (أ): تعذُّر عرض "المسار"
الخطأ:
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
التشخيص: تخطّى الموظف خطوة إثبات الملكية (lookup_order). هذا خطأ منطقي.
كيفية تحديد المشاكل وحلّها:
- عدم التخمين: ارجع إلى واجهة مستخدم الويب الخاصة بـ "حزمة تطوير التطبيقات" (adk web).
- إعادة الإنتاج: اكتب الطلب نفسه الذي أدخلته في الاختبار الفاشل في المحادثة.
- سجلّ التتبُّع: لفتح عرض "سجلّ التتبُّع" انتقِل إلى علامة التبويب "الرسم البياني".
- إصلاح الطلب: عليك عادةً تعديل طلب النظام. تغيير: "أنت وكيل مفيد". إلى: "أنت وكيل مفيد. مهم: يجب الاتصال بـ lookup_order للتحقّق من التفاصيل قبل الاتصال بـ issue_refund."
- تعديل الاختبار: إذا تغيّرت منطق النشاط التجاري (على سبيل المثال، لم يعُد من الضروري إثبات الملكية)، يكون الاختبار غير صحيح. عدِّل ملف eval.test.json ليتطابق مع الواقع الجديد.
السيناريو (ب): فشل "ROUGE"
الخطأ:
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."
التشخيص: نفّذ الوكيل الإجراء الصحيح، ولكن باستخدام كلمات مختلفة. تمت معاقبة ROUGE (تداخل الكلمات).
كيفية حلّ المشكلة:
- هل هذا خطأ؟ إذا كان المعنى صحيحًا، لا تغيِّر الطلب.
- ضبط الحدّ: خفِّض الحدّ في
test_config.json(مثلاً، من0.8إلى0.5). - ترقية المقياس: انتقِل إلى
final_response_match_v2في ملف الإعداد. يستخدم هذا النظام نموذج لغة كبيرًا لقراءة الجملتَين وتحديد ما إذا كانتا تحملان المعنى نفسه.
10. التكامل المستمر/التسليم المستمر باستخدام Pytest (pytest)

أوامر واجهة سطر الأوامر مخصّصة للمستخدمين. pytest مخصّص للآلات. لضمان موثوقية الإنتاج، نضمّن تقييماتنا في مجموعة اختبارات Python. يسمح ذلك لعملية CI/CD (مثل GitHub Actions وJenkins) بحظر عملية نشر إذا انخفض أداء البرنامج.
ما الذي يتضمّنه هذا الملف؟
يعمل ملف Python هذا كجسر بين أداة تنفيذ CI/CD وأداة تقييم ADK. يجب أن تتضمّن ما يلي:
- تحميل برنامجك الآلي: استورِد رمز البرنامج الآلي بشكل ديناميكي.
- إعادة ضبط الحالة: تأكَّد من أنّ ذاكرة البرنامج الوكيل فارغة حتى لا تتداخل الاختبارات مع بعضها البعض.
- تشغيل التقييم: يمكنك طلب
AgentEvaluator.evaluate()آليًا. - Assert Success: إذا كانت نتيجة التقييم منخفضة، سيتم إيقاف الإصدار.
رمز اختبار الدمج
👉 افتح customer_service_agent/test_agent_eval.py. يستخدم هذا النص البرمجي AgentEvaluator.evaluate لتشغيل الاختبارات المحدّدة في eval.test.json.
👉 افتح customer_service_agent/test_agent_eval.py في المحرّر.
أدخِل الرمز التالي:
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,
)
Run Pytest
👉 في الوحدة الطرفية، نفِّذ ما يلي:
cd ~/adk_eval_starter
uv pip install pytest
uv run pytest customer_service_agent/test_agent_eval.py
ستظهر لك نتيجة مشابهة لما يلي:
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=============== 1 passed, 15 warnings in 12.84s ===============
11. الخاتمة
تهانينا! لقد قيّمت موظّف خدمة العملاء بنجاح باستخدام أداة ADK Eval.
ما تعلّمته
في هذا الدرس العملي، تعلّمت كيفية:
- ✅ إنشاء مجموعة بيانات ذهبية لتحديد قاعدة أساسية للوكيل
- ✅ التعرّف على إعدادات التقييم لتحديد معايير النجاح
- ✅ تنفيذ التقييمات الآلية لرصد المشاكل في وقت مبكر
من خلال دمج ADK Eval في سير عمل التطوير، يمكنك إنشاء وكلاء بثقة، مع العلم أنّ أي تغيير في السلوك سيتم رصده من خلال اختباراتك الآلية.