1. مرحبًا بكم، مطوّرو وكلاء الذكاء الاصطناعي!
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية إنشاء وكلاء مستندين إلى الذكاء الاصطناعي في Java باستخدام حزمة تطوير الوكلاء (ADK) للغة Java. سننتقل إلى ما هو أبعد من طلبات البيانات البسيطة من واجهة برمجة التطبيقات الخاصة بالنماذج اللغوية الكبيرة (LLM) لإنشاء وكلاء ذكاء اصطناعي مستقلين يمكنهم الاستدلال والتخطيط واستخدام الأدوات والعمل معًا لحل المشاكل المعقّدة.
ستبدأ بتحصيل رصيد Google Cloud، وإعداد بيئة Google Cloud، ثم إنشاء أول وكيل بسيط، وإضافة المزيد من الإمكانات المتقدّمة تدريجيًا، مثل الأدوات المخصّصة والبحث على الويب وتنسيق عمل عدة وكلاء.
أهداف الدورة التعليمية
- كيفية إنشاء وكيل أساسي مستند إلى الذكاء الاصطناعي ومصمّم خصيصًا لشخصية معيّنة
- كيفية تزويد الوكلاء بأدوات مخصّصة ومضمّنة (مثل "بحث Google")
- كيفية إضافة أدواتك الخاصة التي تم تنفيذها في Java
- كيفية تنسيق عدة وكلاء في مهام سير عمل قوية متسلسلة ومتوازية ومتكررة
المتطلبات
- متصفّح ويب سنستخدمه في وضع التصفّح المتخفي.
- حساب Gmail شخصي
- مشروع جديد على Google Cloud مرتبط بحسابك الشخصي على Gmail
- حساب فوترة تم إنشاؤه باستخدام رصيد Google Cloud الذي تم تحصيله
- أداة سطر الأوامر git لاستخراج رمز المصدر
- Java 17 والإصدارات الأحدث وApache Maven
- محرّر نصوص أو بيئة تطوير متكاملة (IDE)، مثل IntelliJ IDEA أو VS Code
يمكنك استخدام محرّر VS Code المضمّن في Cloud Shell، وذلك في Google Cloud Console.
2. الإعداد: بيئتك
المطالبة برصيد Google Cloud مقابل ورشة العمل
بالنسبة إلى ورشة العمل التي يقودها مدرّب، ستتلقّى رابطًا إلى الموقع الإلكتروني حيث يمكنك المطالبة بأرصدة Google Cloud لاستخدامها في ورشة العمل.
- استخدام حساب Google شخصي: من المهم استخدام حساب Google شخصي (مثل عنوان gmail.com) لأنّ عناوين البريد الإلكتروني الخاصة بالشركات أو المؤسسات التعليمية لن تعمل.
- استخدام Google Chrome في وضع التصفّح المتخفي: يُنصح بذلك لإنشاء جلسة جديدة ومنع حدوث تعارضات مع حسابات Google الأخرى.
- استخدام رابط الحدث الخاص: يجب استخدام رابط خاص بالحدث، ويبدو على النحو التالي: https://trygcp.dev/event/xxx متبوعًا برمز الحدث (هنا "xxx" في هذا المثال).
- قبول بنود الخدمة: بعد تسجيل الدخول، ستظهر لك بنود خدمة Google Cloud Platform، ويجب قبولها للمتابعة.
- إنشاء مشروع جديد: يجب إنشاء مشروع جديد فارغ من Google Cloud Console.
- ربط حساب فوترة: اربط المشروع الذي تم إنشاؤه حديثًا بحساب فوترة.
- تأكيد الرصيد: يوضّح الفيديو التالي كيفية تأكيد تطبيق الرصيد على المشروع من خلال الاطّلاع على قسم "الأرصدة" في صفحة الفوترة.
يمكنك مشاهدة هذا الفيديو الذي يشرح كيفية تحصيل قيمة الرصيد واستخدامه.
إنشاء مفتاح واجهة برمجة التطبيقات وضبطه
للمصادقة على وكلاء الذكاء الاصطناعي في "حزمة تطوير التطبيقات" (ADK) باستخدام Gemini API في هذا الدرس التطبيقي حول الترميز، عليك استخدام مفتاح واجهة برمجة تطبيقات مرتبط بمشروعك على Google Cloud.
- إنشاء مفتاح واجهة برمجة تطبيقات:
- انتقِل إلى Google AI Studio وانقر على الرابط "الحصول على مفتاح API" في أسفل اللوحة الجانبية اليمنى.
- اختَر المشاريع، ثم انقر على زر استيراد المشاريع.
- ابحث عن مشروع Google Cloud الذي تريد استيراده واختَره، ثم انقر على الزر استيراد.
- بعد استيراد المشروع، انتقِل إلى صفحة مفاتيح واجهة برمجة التطبيقات من قائمة "لوحة البيانات"، ثم أنشئ مفتاح واجهة برمجة تطبيقات في المشروع الذي استوردته للتو.
- دوِّن مفتاح واجهة برمجة التطبيقات.
- ضبط متغيّر البيئة: يحتاج البرنامج إلى الوصول إلى هذا المفتاح. الطريقة العادية هي ضبط متغيّر بيئة باسم
GOOGLE_API_KEY
.
- نظام التشغيل macOS أو Linux: افتح الوحدة الطرفية ونفِّذ الأمر التالي، مع استبدال
"your-api-key"
بالمفتاح الذي نسخته للتو. لإجراء ذلك بشكل دائم، أضِف هذا السطر إلى ملف بدء التشغيل الخاص بالصدفة (على سبيل المثال،~/.bash_profile
,~/.zshrc
).
export GOOGLE_API_KEY="your-api-key"
- في نظام التشغيل Windows (موجّه الأوامر): افتح موجّه أوامر جديدًا ونفِّذ ما يلي:
setx GOOGLE_API_KEY "your-api-key"
- عليك إعادة تشغيل موجه الأوامر لكي ينعكس هذا التغيير.
- نظام التشغيل Windows (PowerShell): افتح وحدة تحكّم PowerShell وشغِّل:
$env:GOOGLE_API_KEY="your-api-key"
- لإجراء هذا التغيير بشكل دائم في PowerShell، عليك إضافته إلى نص ملفك الشخصي.
3- الخطوات الأولى: وكيلك الأول
أفضل طريقة لبدء مشروع جديد هي استخدام نموذج ADK for Java على GitHub. يوفر بنية المشروع وجميع التبعيات اللازمة.
إذا كان لديك حساب على Github، يمكنك إجراء ما يلي: Use this template
> Create a new repository
، ثم استخراج الرمز برمجيًا محليًا باستخدام الأمر git clone
.
في ما يلي لقطة شاشة تعرض القائمة أعلى يسار الصفحة لاستخدام النموذج.
الأسلوب الآخر هو استنساخ المستودع مباشرةً باستخدام:
git clone https://github.com/glaforge/adk-java-maven-template.git
بعد ذلك، أدخِل cd
في adk-java-maven-template
.
للتأكّد من أنّك مستعد لبدء كتابة رمز أول وكيل يعمل بالذكاء الاصطناعي في Java، تأكَّد من إمكانية تجميع الرمز في هذا المشروع باستخدام:
mvn compile
Code Step: A Friendly Science Teacher Agent
الوحدة الأساسية في حزمة تطوير التطبيقات (ADK) هي الفئة LlmAgent
. يمكن تشبيهها بالذكاء الاصطناعي الذي يتمتع بشخصية وهدف محدّدين، ويستند إلى نموذج لغوي كبير. سنضيف لاحقًا المزيد من الإمكانات من خلال الأدوات، وسنجعلها أكثر فعالية من خلال التعاون بشكل وثيق مع وكلاء آخرين مشابهين.
لننشئ فئة Java جديدة في حزمة com.example.agent
ونسمّيها ScienceTeacher
.
هذه هي الخطوة الأولى في إنشاء وكيل. سنحدّد وكيلًا بسيطًا بشخصية معلّم علوم.
// src/main/java/com/example/agent/ScienceTeacher.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class ScienceTeacher {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("science-teacher")
.description("A friendly science teacher")
.instruction("""
You are a science teacher for teenagers.
You explain science concepts in a simple, concise and direct way.
""")
.model("gemini-2.5-flash")
.build()
);
}
}
يتم إعداد وكيل الذكاء الاصطناعي من خلال الطريقة LlmAgent.builder()
. المَعلمات name()
وdescription()
وmodel()
إلزامية، ولإضفاء طابع شخصي محدّد وسلوك مناسب على وكيلك، عليك دائمًا تقديم إرشادات مفصّلة باستخدام طريقة instruction()
.
اخترنا هنا استخدام نموذج Gemini 2.5 Flash، ولكن يمكنك أيضًا تجربة Gemini 2.5 Pro للمهام الأكثر تعقيدًا.
يتم تضمين هذا الوكيل في الطريقة AdkWebServer.start()
. هذه هي واجهة المحادثة المعروفة باسم واجهة مستخدم مطوّري حزمة تطوير التطبيقات. تتيح لك هذه الميزة التحدّث مع الوكيل من خلال واجهة دردشة عادية. بالإضافة إلى ذلك، يكون من المفيد جدًا فهم ما يحدث في الخلفية، مثل جميع الأحداث التي تمر عبر النظام والطلبات والردود التي يتم إرسالها إلى النموذج اللغوي الكبير.
لترجمة هذا البرنامج وتشغيله محليًا، شغِّل الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.ScienceTeacher
بعد ذلك، انتقِل إلى المتصفّح على http://localhost:8080. من المفترض أن تظهر لك واجهة المستخدم كما هو موضّح في لقطة الشاشة أدناه. يمكنك طرح أسئلة متعلقة بالعلوم على وكيلك.
4. تزويد الوكلاء بالأدوات
لماذا يحتاج العملاء إلى أدوات؟ تتميّز النماذج اللغوية الكبيرة بقدراتها العالية، ولكنّ معلوماتها ثابتة ولا يمكنها التفاعل مع العالم الخارجي. الأدوات هي الجسر. تسمح هذه الأدوات للوكيل بالوصول إلى المعلومات في الوقت الفعلي (مثل أسعار الأسهم أو الأخبار) أو طلب بيانات من واجهات برمجة التطبيقات الخاصة أو تنفيذ أي إجراء يمكنك ترميزه بلغة Java.
خطوة الرمز البرمجي: إنشاء أداة مخصّصة (StockTicker
)
هنا، نقدّم للوكيل أداة للبحث عن أسعار الأسهم. يستنتج الوكيل أنّه عندما يطلب المستخدم سعرًا، يجب أن يستدعي طريقة Java.
// src/main/java/com/example/agent/StockTicker.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
import com.google.adk.web.AdkWebServer;
import java.util.Map;
public class StockTicker {
public static void main(String[] args) {
AdkWebServer.start(
LlmAgent.builder()
.name("stock_agent")
.instruction("""
You are a stock exchange ticker expert.
When asked about the stock price of a company,
use the `lookup_stock_ticker` tool to find the information.
""")
.model("gemini-2.5-flash")
.tools(FunctionTool.create(StockTicker.class, "lookupStockTicker"))
.build()
);
}
@Schema(
name = "lookup_stock_ticker",
description = "Lookup stock price for a given company or ticker"
)
public static Map<String, String> lookupStockTicker(
@Schema(name = "company_name_or_stock_ticker", description = "The company name or stock ticker")
String ticker) {
// ... (logic to return a stock price)
}
}
لجعل الوكلاء أكثر ذكاءً ومنحهم القدرة على التفاعل مع العالم (أو مع الرموز البرمجية وواجهات برمجة التطبيقات والخدمات وما إلى ذلك)، يمكنك ضبط الوكيل لاستخدام الأدوات، وخاصةً أدوات الرموز البرمجية المخصّصة، من خلال طريقة tools()
، مع تمرير FunctionTool.create(...)
إليها.
يتطلّب FunctionTool
اسم فئة واسم طريقة يشيران إلى طريقتك الثابتة. ويمكن أيضًا تمرير مثيل لفئة واسم طريقة مثيل لهذا العنصر.
من المهم تحديد name
وdescription
لكلّ من الطريقة ومعلَماتها من خلال التعليق التوضيحي @Schema
، لأنّ النموذج اللغوي الكبير الأساسي سيستخدم هذه المعلومات لتحديد وقت وكيفية استدعاء طريقة معيّنة.
من المهم أيضًا تقديم تعليمات واضحة للنموذج اللغوي الكبير حول كيفية استخدام الأداة ومتى يجب استخدامها. قد يتمكّن النموذج من معرفة ذلك بنفسه، ولكن إذا قدّمت تفسيرات واضحة في طريقة instruction()
، ستكون هناك فرص أكبر لاستدعاء الدالة بشكل صحيح.
يجب أن تعرض هذه الطريقة Map
. عادةً، تكون الفكرة هي عرض خريطة تتضمّن مفتاحًا يمثّل النتيجة، مثل stock_price
، وربط قيمة سعر السهم بها. في النهاية، يمكنك إضافة زوج مفتاح / قيمة إضافي يشير إلى نجاح العملية. وفي حال حدوث خطأ، يجب إرجاع خريطة بمفتاح يُسمى، على سبيل المثال، error
، وربط رسالة الخطأ بالقيمة المرتبطة. يساعد ذلك النموذج اللغوي الكبير في معرفة ما إذا كانت المكالمة قد نجحت أو تعذّر إجراؤها لسبب ما.
- عند النجاح، يتم عرض:
{"stock_price": 123}
- في حال حدوث خطأ، يتم عرض:
{"error": "Impossible to retrieve stock price for XYZ"}
بعد ذلك، شغِّل هذه الفئة باستخدام الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.StockTicker
5- إمكانات "بحث Google" للحصول على معلومات محدّثة
تتضمّن حزمة تطوير التطبيقات (ADK) للغة Java مجموعة من الأدوات الفعّالة، بما في ذلك GoogleSearchTool
. باستخدام هذه الأداة، يمكن أن يطلب الوكيل استخدام "بحث Google" للعثور على معلومات ذات صلة لتحقيق هدفه.
في الواقع، إنّ معرفة النموذج اللغوي الكبير ثابتة في الوقت الحالي، إذ تم تدريبه حتى تاريخ معيّن (يُعرف باسم "تاريخ الإيقاف") باستخدام بيانات حديثة أيضًا مثل وقت جمع المعلومات. هذا يعني أنّ النماذج اللغوية الكبيرة قد لا تكون على دراية بالأحداث الأخيرة، أو قد تكون معرفتها محدودة وسطحية، وقد تساعدها محركات البحث في تذكّر المعلومات أو معرفة المزيد عن الموضوع.
لنلقِ نظرة على هذا البرنامج البسيط للبحث عن الأخبار:
// src/main/java/com/example/agent/LatestNews.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class LatestNews {
public static void main(String[] args) {
AdkWebServer.start(LlmAgent.builder()
.name("news-search-agent")
.description("A news search agent")
.instruction("""
You are a news search agent.
Use the `google_search` tool
when asked to search for recent events and information.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.build());
}
}
لاحظ كيف مرّرنا مثيلاً لأداة البحث باستخدام: tools(new GoogleSearchTool())
. وهذا ما يمنح الوكيل القدرة على التعرّف على أحدث المعلومات المتوفّرة على الويب. بالإضافة إلى ذلك، حدّد الطلب تاريخ اليوم، لأنّ ذلك قد يساعد النموذج اللغوي الكبير في فهم ما إذا كانت الأسئلة تتعلّق بمعلومات سابقة وما إذا كان من المطلوب البحث عن معلومات أحدث.
بعد ذلك، شغِّل هذه الفئة باستخدام الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.LatestNews
يمكنك تعديل الطلب للحصول على نتائج مختلفة من حيث الأسلوب أو الإيجاز أو التركيز أو غير ذلك.
خطوة الرمز البرمجي: استخدام "أداة البحث"
بدلاً من تمرير GoogleSearchTool
إلى وكيل مباشرةً كأداة، يمكنك إنشاء وكيل بحث مخصّص يضم وظيفة البحث وعرض هذا الوكيل كأداة لوكيل أعلى مستوى.
هذا مفهوم متقدّم يتيح لك تفويض سلوكيات معقّدة (مثل البحث و تلخيص النتائج) إلى وكيل فرعي متخصص. غالبًا ما يكون هذا النهج مفيدًا لسير العمل الأكثر تعقيدًا، لأنّه لا يمكن استخدام الأدوات المضمّنة مع الأدوات المخصّصة المستندة إلى الرموز البرمجية.
// src/main/java/com/example/agent/SearchAgentAsTool.java
package com.example.agent;
import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.AgentTool;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class SearchAgentAsTool {
public static void main(String[] args) {
// 1. Define the specialized Search Agent
LlmAgent searchAgent = LlmAgent.builder()
.name("news-search-agent-tool")
.description("Searches for recent events and provides a concise summary.")
.instruction("""
You are a concise information retrieval specialist.
Use the `google_search` tool to find information.
Always provide the answer as a short,
direct summary, without commentary.
Today is \
""" + LocalDate.now())
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool()) // This agent uses the Google Search Tool
.build();
// 2. Wrap the Search Agent as a Tool
AgentTool searchTool = AgentTool.create(searchAgent);
// 3. Define the Main Agent that uses the Search Agent Tool
AdkWebServer.start(LlmAgent.builder()
.name("main-researcher")
.description("Main agent for answering complex, up-to-date questions.")
.instruction("""
You are a sophisticated research assistant.
When the user asks a question that requires up-to-date or external information,
you MUST use the `news-search-agent-tool` to get the facts before answering.
After the tool returns the result, synthesize the final answer for the user.
""")
.model("gemini-2.5-flash")
.tools(searchTool) // This agent uses the Search Agent as a tool
.build()
);
}
}
AgentTool.create(searchAgent)
هو المفهوم الأساسي هنا. تسجّل هذه الدالة searchAgent
بأكملها (مع منطقها الداخلي وطلبها وأدواتها) كأداة واحدة قابلة للاستدعاء من أجل mainAgent
. ويعزّز ذلك إمكانية التعديل وإعادة الاستخدام.
نفِّذ هذه الفئة باستخدام الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SearchAgentAsTool
بالنسبة إلى الأسئلة العادية، سيردّ الوكيل من قاعدة المعرفة الخاصة به، ولكن عند السؤال عن الأحداث الأخيرة، سيُحيل البحث إلى وكيل البحث المتخصّص باستخدام أداة "بحث Google".
6. إتقان عمليات سير العمل المعقّدة
بالنسبة إلى المشاكل المعقّدة، لا يكفي وجود وكيل واحد. عندما يتم تزويد نماذج اللغات الكبيرة بهدف يتألف من عدد كبير جدًا من المهام الفرعية، أو يتضمّن طلبًا كبيرًا يقدّم الكثير من التفاصيل، أو يتيح الوصول إلى عدد كبير من الوظائف، فإنّ هذه النماذج تواجه صعوبات، وينخفض أداؤها ودقتها.
يكمن الحلّ في تقسيم المهام وتوزيعها من خلال تنسيق عدّة وكلاء متخصصين. لحسن الحظ، تتضمّن "مجموعة أدوات تطوير التطبيقات" وكلاء مدمجين متخصصين مختلفين:
- وكيل عادي مع
subAgent()
لتفويض المهام إليه SequentialAgent
، لتنفيذ المهام بالتسلسل،ParallelAgent
، لتنفيذ الوكلاء بالتوازي،-
LoopAgent
، عادةً ما يتم ذلك من خلال عملية تحسين عدة مرات حسب الحاجة.
يمكنك الاطّلاع على الجدول أدناه لمعرفة حالات الاستخدام الرئيسية ومزايا وعيوب كل سير عمل. لكن تذكَّر أنّ القوة الحقيقية ستأتي في الواقع من الجمع بين عدة منها.
Workflow | فئة ADK | Use Case | الإيجابيات | السلبيات |
الوكلاء الفرعيون |
| مهام مرنة يحدّدها المستخدم ولا تكون الخطوة التالية فيها معروفة دائمًا | مرونة عالية، وتفاعلية، ومناسبة لبرامج الروبوت التي يتفاعل معها المستخدمون | أقل قابلية للتوقّع، ويعتمد على استدلال النموذج اللغوي الكبير للتحكّم في التدفق |
تسلسلية |
| العمليات الثابتة والمتعددة الخطوات التي يكون فيها الترتيب مهمًا | يمكن توقّع أدائه وموثوقيته، ويسهل تصحيح الأخطاء فيه، ويضمن ترتيب العمليات. | غير مرن، ويمكن أن يكون أبطأ إذا كان من الممكن تنفيذ المهام بالتوازي. |
التوازي |
| جمع البيانات من مصادر متعددة أو تنفيذ مهام مستقلة | عالية الكفاءة، وتقلّل بشكل كبير من وقت الاستجابة للمهام المرتبطة بالإدخال/الإخراج. | يتم تنفيذ جميع المهام بدون أي اختصار. غير مناسب للمهام التي تعتمد على مهام أخرى |
التكرار |
| التحسين التكراري أو التصحيح الذاتي أو العمليات التي تتكرر إلى أن يتم استيفاء شرط معيّن | فعّالة في حلّ المشاكل المعقّدة، وتتيح للموظفين تحسين عملهم. | يمكن أن يؤدي إلى تكرار لا نهائي إذا لم يتم تصميمه بعناية (استخدِم دائمًا maxIterations!). |
7. عمليات سير العمل المستندة إلى الذكاء الاصطناعي الوكيل: التفويض باستخدام الوكلاء الفرعيين
يمكن لوكيل مشرف تفويض مهام معيّنة إلى وكلاء فرعيين. على سبيل المثال، تخيَّل وكيلًا لموقع إلكتروني للتجارة الإلكترونية يفوّض الأسئلة المتعلقة بالطلبات إلى وكيل آخر ("ما هي حالة طلبي؟") والأسئلة المتعلقة بخدمة ما بعد البيع إلى وكيل آخر ("لا أعرف كيفية تشغيله!"). هذه هي حالة الاستخدام التي سنناقشها.
// src/main/java/com/example/agent/SupportAgent.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;
public class SupportAgent {
public static void main(String[] args) {
LlmAgent topicSearchAgent = LlmAgent.builder()
.name("order-agent")
.description("Order agent")
.instruction("""
Your role is to help our customers
with all the questions they may have about their orders.
Always respond that the order has been received, prepared,
and is now out for delivery.
""")
.model("gemini-2.5-flash")
.build();
LlmAgent socialMediaAgent = LlmAgent.builder()
.name("after-sale-agent")
.description("After sale agent")
.instruction("""
You are an after sale agent,
helping customers with the product they received.
When a customer has a problem,
suggest the person to switch the product off and on again.
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(LlmAgent.builder()
.name("support-agent")
.description("Customer support agent")
.instruction("""
Your role is help our customers.
Call the `order-agent` for all questions related to order status.
Call the `after-sale-agent` for inquiries about the received product.
""")
.model("gemini-2.5-flash")
.subAgents(socialMediaAgent, topicSearchAgent)
.build()
);
}
}
السطر الأساسي هنا هو المكان الذي يتم فيه استدعاء الطريقة subAgents()
، مع تمرير الوكيلَين الفرعيَين اللذين سيتم التعامل مع دورهما المحدّد بشكل منفصل عن بعضهما البعض.
نفِّذ المثال أعلاه باستخدام الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.SupportAgent
يتشابه مفهوم تفويض المهام إلى وكلاء فرعيين مع الإدارة الفعّالة للبشر، حيث يعتمد المدير الجيد (الوكيل المشرف) على موظفين متخصصين (الوكلاء الفرعيون) للتعامل مع مهام محددة لديهم خبرة أكبر فيها. لا يحتاج المشرف إلى معرفة تفاصيل كل عملية، بل يوجّه طلب العميل (مثل الاستفسار عن طلب أو مشكلة فنية) بذكاء إلى "عضو الفريق" الأكثر تأهيلاً، ما يضمن تقديم ردّ أكثر كفاءة وأعلى جودة مما يمكن أن يقدّمه موظف عام بمفرده. علاوةً على ذلك، يمكن لهذه الوكلاء الفرعيين التركيز بشكل كامل على مهامهم الفردية بدون الحاجة إلى فهم العملية المعقّدة الشاملة بأكملها.
8. عمليات سير العمل المستندة إلى الوكلاء: خط التجميع
عندما يكون ترتيب العمليات الحسابية مهمًا، استخدِم SequentialAgent
. وهي تشبه خط التجميع، حيث يتم تنفيذ الوكلاء الفرعيين بترتيب ثابت يمكن أن تعتمد فيه كل خطوة على الخطوة السابقة.
لنفترض أنّ شاعرًا إنجليزيًا يتعاون مع مترجم من الإنجليزية إلى الفرنسية لإنشاء قصائد باللغة الإنجليزية أولاً ثم ترجمتها إلى الفرنسية:
// src/main/java/com/example/agent/PoetAndTranslator.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.web.AdkWebServer;
public class PoetAndTranslator {
public static void main(String[] args) {
LlmAgent poet = LlmAgent.builder()
.name("poet-agent")
.description("Poet writing poems")
.model("gemini-2.5-flash")
.instruction("""
You are a talented poet,
who writes short and beautiful poems.
""")
.outputKey("poem")
.build();
LlmAgent translator = LlmAgent.builder()
.name("translator-agent")
.description("English to French translator")
.model("gemini-2.5-flash")
.instruction("""
As an expert English-French translator,
your role is to translate the following poem into French,
ensuring the poem still rhymes even after translation:
{poem}
""")
.outputKey("translated-poem")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("poet-and-translator")
.subAgents(poet, translator)
.build());
}
}
نفِّذ المثال للحصول على قصيدة باللغة الإنجليزية، ثم ترجمتها إلى الفرنسية، باستخدام الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.PoetAndTranslator
يضمن هذا التقسيم المنهجي للمهام المعقّدة إلى مهام فرعية أصغر ومرتّبة عملية أكثر تحديدًا وموثوقية، ما يزيد بشكل كبير من احتمالية تحقيق نتيجة ناجحة مقارنةً بالاعتماد على وكيل واحد ذي غرض عام.
إنّ تقسيم مهمة ما بشكل فعّال إلى سلسلة من المهام الفرعية (عند الإمكان وعندما يكون ذلك منطقيًا) أمر بالغ الأهمية لتحقيق نتائج أكثر تحديدًا ونجاحًا، لأنّه يتيح إحراز تقدّم منظّم وإدارة التبعيات بين الخطوات.
9- عمليات سير العمل المستندة إلى الوكلاء: العمل بالتوازي
عندما تكون المهام مستقلة، يوفّر ParallelAgent
تحسّنًا كبيرًا في الكفاءة من خلال تنفيذها في الوقت نفسه. في المثال التالي، سنجمع بين SequentialAgent
وParallelAgent
: يتم تنفيذ المهام المتوازية أولاً، ثم يلخّص وكيل نهائي نتائج المهام المتوازية.
لننشئ برنامجًا للتحقّق من الشركات، وستكون مهمته البحث عن معلومات حول:
- الملف التعريفي للشركة (الرئيس التنفيذي والمقر الرئيسي والشعار وما إلى ذلك)
- آخر الأخبار حول الشركة
- تعرض هذه السمة تفاصيل حول البيانات المالية للشركة.
// src/main/java/com/example/agent/CompanyDetective.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.ParallelAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;
public class CompanyDetective {
public static void main(String[] args) {
var companyProfiler = LlmAgent.builder()
.name("company-profiler")
.description("Provides a general overview of a company.")
.instruction("""
Your role is to provide a brief overview of the given company.
Include its mission, headquarters, and current CEO.
Use the Google Search Tool to find this information.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("profile")
.build();
var newsFinder = LlmAgent.builder()
.name("news-finder")
.description("Finds the latest news about a company.")
.instruction("""
Your role is to find the top 3-4 recent news headlines for the given company.
Use the Google Search Tool.
Present the results as a simple bulleted list.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("news")
.build();
var financialAnalyst = LlmAgent.builder()
.name("financial-analyst")
.description("Analyzes the financial performance of a company.")
.instruction("""
Your role is to provide a snapshot of the given company's recent financial performance.
Focus on stock trends or recent earnings reports.
Use the Google Search Tool.
""")
.model("gemini-2.5-flash")
.tools(new GoogleSearchTool())
.outputKey("financials")
.build();
var marketResearcher = ParallelAgent.builder()
.name("market-researcher")
.description("Performs comprehensive market research on a company.")
.subAgents(
companyProfiler,
newsFinder,
financialAnalyst
)
.build();
var reportCompiler = LlmAgent.builder()
.name("report-compiler")
.description("Compiles a final market research report.")
.instruction("""
Your role is to synthesize the provided information into a coherent market research report.
Combine the company profile, latest news, and financial analysis into a single, well-formatted report.
## Company Profile
{profile}
## Latest News
{news}
## Financial Snapshot
{financials}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("company-detective")
.description("Collects various information about a company.")
.subAgents(
marketResearcher,
reportCompiler
).build());
}
}
كالعادة، يمكنك تشغيل البرنامج باستخدام الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CompanyDetective
يقدّم هذا الوكيل مزيجًا قويًا من سير العمل، حيث يتم استخدام الوكلاء المتوازيين والمتسلسلين بشكل جيد وبطريقة فعّالة بفضل التوازي في البحث عن المعلومات وتجميعها.
10. عمليات سير العمل المستندة إلى الذكاء الاصطناعي الوكيل: التحسين التكراري
بالنسبة إلى المهام التي تتطلّب دورة "إنشاء → مراجعة → تحسين"، استخدِم LoopAgent
. تعمل هذه الميزة على تحسين الأداء بشكل متكرّر إلى أن يتم تحقيق هدف معيّن. على غرار SequentialAgent
، سيتصل LoopAgent
بالوكلاء الفرعيين بالتسلسل، ولكنّه سيعود إلى البداية. إنّ النموذج اللغوي الكبير المستخدَم داخليًا من قِبل الوكيل هو الذي سيقرّر ما إذا كان سيطلب إجراء مكالمة إلى أداة خاصة، وهي الأداة المدمجة exit_loop
، لإيقاف تنفيذ الحلقة.
يؤدي مثال أداة تحسين الرموز البرمجية أدناه، باستخدام LoopAgent
، إلى تنفيذ عملية تحسين الرموز البرمجية تلقائيًا: إنشاء الرموز ومراجعتها وتصحيحها. ويحاكي هذا التطور البشري. ينشئ مساعد كتابة الرموز البرمجية أولاً الرمز المطلوب، ويحفظه في حالة المساعد ضمن المفتاح generated_code
. بعد ذلك، يراجع مدقق الرمز البرمجي الرمز الذي تم إنشاؤه، ويقدّم ملاحظات (ضمن المفتاح feedback
)، أو يستدعي أداة حلقة الخروج لإنهاء التكرار مبكرًا.
لنلقِ نظرة على الرمز:
// src/main/java/com/example/agent/CodeRefiner.java
package com.example.agent;
import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.LoopAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.ExitLoopTool;
import com.google.adk.web.AdkWebServer;
public class CodeRefiner {
public static void main(String[] args) {
var codeGenerator = LlmAgent.builder()
.name("code-generator")
.description("Writes and refines code based on a request and feedback.")
.instruction("""
Your role is to write a Python function based on the user's request.
In the first turn, write the initial version of the code.
In subsequent turns, you will receive feedback on your code.
Your task is to refine the code based on this feedback.
Previous feedback (if any):
{feedback?}
""")
.model("gemini-2.5-flash")
.outputKey("generated_code")
.build();
var codeReviewer = LlmAgent.builder()
.name("code-reviewer")
.description("Reviews code and decides if it's complete or needs more work.")
.instruction("""
Your role is to act as a senior code reviewer.
Analyze the provided Python code for correctness, style, and potential bugs.
Code to review:
{generated_code}
If the code is perfect and meets the user's request,
you MUST call the `exit_loop` tool.
Otherwise, provide constructive feedback for the `code-generator to improve the code.
""")
.model("gemini-2.5-flash")
.outputKey("feedback")
.tools(ExitLoopTool.INSTANCE)
.build();
var codeRefinerLoop = LoopAgent.builder()
.name("code-refiner-loop")
.description("Iteratively generates and reviews code until it is correct.")
.subAgents(
codeGenerator,
codeReviewer
)
.maxIterations(3) // Safety net to prevent infinite loops
.build();
var finalPresenter = LlmAgent.builder()
.name("final-presenter")
.description("Presents the final, accepted code to the user.")
.instruction("""
The code has been successfully generated and reviewed.
Present the final version of the code to the user in a clear format.
Final Code:
{generated_code}
""")
.model("gemini-2.5-flash")
.build();
AdkWebServer.start(SequentialAgent.builder()
.name("code-refiner-assistant")
.description("Manages the full code generation and refinement process.")
.subAgents(
codeRefinerLoop,
finalPresenter)
.build());
}
}
شغِّل هذا الوكيل باستخدام الأمر التالي:
mvn compile exec:java -Dexec.mainClass=com.example.agent.CodeRefiner
تُعدّ حلقات الملاحظات/التحسين، التي يتم تنفيذها باستخدام LoopAgent
، ضرورية لحلّ المشاكل التي تتطلّب تحسينًا متكررًا وتصحيحًا ذاتيًا، ما يحاكي العمليات المعرفية البشرية بشكل كبير. يُعدّ نمط التصميم هذا مفيدًا بشكل خاص للمهام التي نادرًا ما تكون فيها النتائج الأولية مثالية، مثل إنشاء الرموز البرمجية أو الكتابة الإبداعية أو تكرار التصميم أو تحليل البيانات المعقّد. من خلال تكرار عملية إخراج المحتوى عبر وكيل مراجعة متخصص يقدّم ملاحظات منظَّمة، يمكن لوكيل الإنشاء تحسين عمله باستمرار إلى أن يتم استيفاء معيار اكتمال محدّد مسبقًا، ما يؤدي إلى نتائج نهائية ذات جودة أعلى وموثوقية أكبر بشكل واضح مقارنةً بنهج المرور الفردي.
11. تهانينا!
لقد نجحت في إنشاء مجموعة متنوعة من وكلاء الذكاء الاصطناعي واستكشافها، بدءًا من الوكلاء البسيطين الذين يجرون محادثات إلى الأنظمة المعقّدة التي تضم عدة وكلاء. لقد تعرّفت على المفاهيم الأساسية لحزمة تطوير التطبيقات (ADK) للغة Java، وهي: تحديد الوكلاء باستخدام التعليمات، وتزويدهم بالأدوات، وتنظيمهم في سير عمل فعّالة.
ما هي الخطوات التالية؟
- استكشِف مستودع GitHub الرسمي لحزمة تطوير التطبيقات (ADK) للغة Java.
- يمكنك الاطّلاع على مزيد من المعلومات عن إطار العمل في مستنداته.
- يمكنك الاطّلاع على مختلف مهام سير العمل المستندة إلى الوكلاء في سلسلة المدونات هذه، وعلى الأدوات المختلفة المتاحة.
- يمكنك التعرّف أكثر على الأدوات المضمّنة الأخرى وعمليات معاودة الاتصال المتقدّمة.
- التعامل مع السياق والحالة والنتائج للحصول على تفاعلات أكثر ثراءً ومتعددة الوسائط
- تنفيذ وتطبيق المكوّنات الإضافية التي تتكامل مع دورة حياة الوكلاء
- جرِّب إنشاء وكيلك الخاص الذي يحلّ مشكلة واقعية.