1. 1. قبل البدء

مرحبًا في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية إنشاء تطبيقات الذكاء الاصطناعي الوكيل في Java باستخدام إطار عمل LangChain4j الرائج ووحدة Google GenAI الجديدة.
يشير الذكاء الاصطناعي الوكيل إلى الأنظمة التي لا تكتفي فيها النماذج اللغوية الكبيرة بالرد على الطلبات، بل تكون مزوّدة بأدوات وذاكرة وإمكانات تخطيط لإنجاز أهداف معقّدة ومتعددة الخطوات بشكل مستقل.
ستبدأ بإعدادات بسيطة، ثم تنتقل إلى إنشاء وكلاء باستخدام أدوات محلية ومخرجات منظَّمة، وأخيرًا ستستكشف أنماطًا متقدّمة لتنظيم الوكلاء المتعدّدين، وستختتم الدورة التدريبية بنظام وكيل لتخطيط الإجراءات المستند إلى الأهداف (GOAP).
الإجراءات التي ستنفذّها
- اضبط إعدادات
GoogleGenAiChatModelالجديد للربط بـ Gemini. - فعِّل تسجيل الطلبات/الردود لتسهيل عملية تصحيح الأخطاء.
- امنح Gemini الإذن بالوصول إلى رمز Java المحلي باستخدام الأدوات.
- فرض تنسيق الناتج المنظَّم (كائنات Java العادية) من Gemini
- تحديد الوكلاء ذوي الأغراض الفردية وإنشاؤهم باستخدام تعليق توضيحي
@Agent - تنظيم مهام سير العمل التسلسلية والمتوازية المتعددة الوكلاء
- إنشاء نظام تخطيط إجراءات موجّهة نحو الهدف (GOAP) يخطّط بشكل ديناميكي لتنفيذ الوكيل
المتطلبات
- حزمة تطوير Java (JDK) 17 أو إصدار أحدث
- يجب تثبيت الإصدار 3.5 أو إصدار أحدث من Maven.
- مفتاح Gemini API من Google AI Studio
2. 2. الإعداد: المشروع ومفتاح واجهة برمجة التطبيقات
للبدء، علينا إنشاء مشروع Maven جديد وإعداد مفتاح Gemini API.
إنشاء مشروع Maven
أنشئ دليلاً جديدًا لمشروعك وأضِف إليه ملف pom.xml.
أضِف التبعيات التالية إلى pom.xml. يُرجى العِلم أنّنا نستخدم أحدث إصدار 1.16.1-beta26 من وحدتَي LangChain4j Google GenAI وAgentic:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>gemini-agents-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<langchain4j.version>1.16.1-beta26</langchain4j.version>
</properties>
<dependencies>
<!-- LangChain4j Google GenAI Integration -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-google-genai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- LangChain4j Agentic Framework Core -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- LangChain4j Agentic Patterns (needed for GOAP) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic-patterns</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- SLF4J Logger for logging requests/responses -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.12</version>
</dependency>
</dependencies>
</project>
الحصول على مفتاح Gemini API
- انتقِل إلى Google AI Studio.
- انقر على الحصول على مفتاح واجهة برمجة التطبيقات.
- أنشئ مفتاحًا جديدًا (أو اختَر مفتاحًا حاليًا).
- اضبطه كمتغيّر بيئة في نافذة الأوامر:
export GEMINI_API_KEY="your-api-key-here"
3- 3- ضبط إعدادات نموذج Gemini Chat
لننشئ الآن تطبيقًا بسيطًا يعرض عبارة "Hello World" وينشئ مثيلاً من GoogleGenAiChatModel ويرسل طلب اختبار.
يستخدم GoogleGenAiChatModel الجديد حزمة SDK الموحّدة من Google للذكاء الاصطناعي التوليدي، والتي تتيح الوصول الموحّد إلى نماذج Gemini.
أنشئ صفًا باسم HelloWorld.java في src/main/java/com/example/HelloWorld.java:
package com.example;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
public class HelloWorld {
public static void main(String[] args) {
// 1. Configure the Gemini model
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
// Enable logging for both requests and responses
.logRequestsAndResponses(true)
.build();
// 2. Invoke the model
String response = model.chat("Hello Gemini! Explain 'Agentic AI' in one sentence.");
// 3. Print response
System.out.println("\n--- Gemini Response ---");
System.out.println(response);
}
}
شغِّل هذه الفئة. بما أنّ logRequestsAndResponses(true) مفعَّل، ستظهر لك سجلّات SLF4J مفصّلة توضّح حمولة الطلب المحدّدة التي تم إرسالها إلى Google API، واستجابة JSON الأولية التي تم تلقّيها، يليها الناتج المطبوع:
--- Gemini Response ---
**Agentic AI** refers to autonomous artificial intelligence systems that can proactively plan, make decisions, use tools, and execute multi-step tasks to achieve specific goals with minimal human supervision.
4. 4. تحديد أدوات Java المحلية
تتسم النماذج اللغوية الكبيرة بقدراتها الفائقة، ولكنها محدودة بسبب بيانات التدريب التي تستند إليها. ويمكننا توسيع نطاق قدراتها من خلال تزويدها بالأدوات (المعروفة أيضًا باسم "استدعاء الدوال").
في LangChain4j، الأدوات هي فئات Java بسيطة يتم فيها إضافة تعليقات توضيحية إلى الطرق باستخدام @Tool.
لنكتب أداة بسيطة تحسب عدد الأيام بين تاريخين. إنشاء DateTools.java في src/main/java/com/example/DateTools.java:
package com.example;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class DateTools {
@Tool("Calculates the number of days between two dates")
public long daysBetween(
@P("The start date in ISO format (YYYY-MM-DD)") String startDate,
@P("The end date in ISO format (YYYY-MM-DD)") String endDate) {
LocalDate start = LocalDate.parse(startDate);
LocalDate end = LocalDate.parse(endDate);
return ChronoUnit.DAYS.between(start, end);
}
}
لاستخدام هذه الأداة، سنعرّف خدمة الذكاء الاصطناعي. في إطار عمل LangChain4j Agentic، يمكننا إنشاء هذه الخدمة باستخدام AgenticServices.agentBuilder().
إنشاء ToolDemo.java في src/main/java/com/example/ToolDemo.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import dev.langchain4j.service.V;
public class ToolDemo {
public interface DateAssistant {
@Agent
String ask(@V("prompt") String prompt);
}
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// Build the assistant and register our DateTools
DateAssistant assistant = AiServices.builder(DateAssistant.class)
.chatModel(model)
.tools(new DateTools())
.build();
String response = assistant.ask("How many days are there between 2026-01-01 and 2026-06-30?");
System.out.println("Response: " + response);
}
}
عند تشغيل هذا الرمز، سيحلّل Gemini الطلب، وسيدرك أنّه بحاجة إلى استدعاء daysBetween، وسينشئ طلبًا لاستخدام الأداة، وسينفّذ LangChain4j طريقة Java المحلية، وسيعيد النتيجة إلى Gemini، وسينسّق Gemini الردّ النهائي باللغة الطبيعية.
من المفترض أن تظهر لك نتيجة مشابهة لما يلي:
Response: There are 180 days between 2026-01-01 and 2026-06-30.
5- 5- تحديد الناتج المنظَّم
في كثير من الأحيان، تريد أن تعرض نماذج اللغات الكبيرة البيانات بتنسيق منظَّم معيّن (مثل JSON مطابق لمخطط) بدلاً من نص عادي.
تتعامل LangChain4j مع ذلك تلقائيًا عند تحديد POJO أو Java record كنوع القيمة التي تم إرجاعها للوكيل أو طريقة الخدمة.
لنحدّد فئة Java record تمثّل استخراج كتاب:
إنشاء Book.java في src/main/java/com/example/Book.java:
package com.example;
public record Book(String title, String author, int publicationYear) {}
الآن، أنشئ واجهة وكيل تعرض Book. إنشاء StructuredOutputDemo.java في src/main/java/com/example/StructuredOutputDemo.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public class StructuredOutputDemo {
public interface BookExtractor {
@UserMessage("Extract book details from: {{text}}")
Book extract(@V("text") String text);
}
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
BookExtractor extractor = AiServices.builder(BookExtractor.class)
.chatModel(model)
.build();
String text = "I just finished reading 'Project Hail Mary' by Andy Weir, published in 2021. It was amazing!";
Book book = extractor.extract(text);
System.out.println("Extracted POJO: " + book);
}
}
يتوافق Gemini 3.5 Flash مع إخراج مخطط JSON صارم. تنشئ LangChain4j مخطط JSON من سجلّ Book، وتطلب من Gemini ملء المخطط، ثم تزيل تسلسل استجابة JSON وتحوّلها إلى سجلّ Book.
من المفترض أن تظهر لك نتيجة مشابهة لما يلي:
Extracted POJO: Book[title=Project Hail Mary, author=Andy Weir, publicationYear=2021]
6. 6. إنشاء أول وكيل لك
في إطار عمل langchain4j-agentic، يتم تحديد الوكيل باستخدام التعليق التوضيحي @Agent على طريقة الواجهة. تقدّم هذه التعليقات التوضيحية اسمًا/وصفًا يمكن أن تستخدمه أنظمة التنسيق (مثل المخططين).
لننشئ وكيلًا بسيطًا يأخذ موضوعًا ويصوغ قصة قصيرة جدًا عنه.
إنشاء CreativeWriter.java في src/main/java/com/example/CreativeWriter.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface CreativeWriter {
@SystemMessage("You are a creative writer. Generate a draft of a story no more than 3 sentences long.")
@UserMessage("Write a story about {{topic}}.")
@Agent(description = "Generates a story based on the given topic", outputKey = "story")
String writeStory(@V("topic") String topic);
}
لنختبر هذا الوكيل بشكلٍ فردي. إنشاء AgentDemo.java في src/main/java/com/example/AgentDemo.java:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
public class AgentDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
CreativeWriter writer = AgenticServices.agentBuilder(CreativeWriter.class)
.chatModel(model)
.build();
String story = writer.writeStory("a lonely robot on Mars");
System.out.println("Generated Story:\n" + story);
}
}
من المفترض أن تظهر لك نتيجة مشابهة لما يلي:
Generated Story:
For eighty years, the rusty little rover trundled across the crimson dunes, diligently collecting soil samples for a home world that had long since gone dark. Each evening, it pointed its high-gain antenna toward the fading blue speck of Earth and beamed its lonely coordinates into the silent cosmos. Receiving only static in return, the robot tucked its camera arm close against the freezing Martian wind and sang a quiet lullaby to the empty stars.
من خلال إضافة التعليق التوضيحي @Agent، أصبح هذا الصف جاهزًا للمشاركة في سير عمل أكثر تعقيدًا، مثل التسلسل المتسلسل.
7. 7. تنظيم مهام سير العمل المتعددة الوكلاء: تسلسلية
أحد الأنماط الشائعة للوكلاء هو سير العمل التسلسلي، حيث يتم تنفيذ الوكلاء بترتيب محدّد مسبقًا، ويتم تمرير ناتج أحد الوكلاء كمدخل للوكيل التالي.
لنحدّد وكيلاً ثانيًا، StyleEditor، سيعدّل القصة التي كتبها CreativeWriter لتناسب أسلوبًا معيّنًا (مثل الأسلوب الكوميدي أو الدرامي).
إنشاء StyleEditor.java في src/main/java/com/example/StyleEditor.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface StyleEditor {
@SystemMessage("You are a professional editor. Analyze and rewrite the story to align with the style requested.")
@UserMessage("Rewrite this story: '{{story}}' into a {{style}} style.")
@Agent(description = "Edits a story to fit a specific style", outputKey = "edited_story")
String editStory(@V("story") String story, @V("style") String style);
}
لنربط الآن CreativeWriter وStyleEditor بالتسلسل باستخدام AgenticServices.sequenceBuilder().
سنستخدم UntypedAgent يمثّل التسلسل، ما يتيح لنا تمرير المدخلات وجمع المخرجات من خلال خريطة مشتركة.
إنشاء SequentialWorkflowDemo.java في src/main/java/com/example/SequentialWorkflowDemo.java:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.agentic.UntypedAgent;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import java.util.Map;
public class SequentialWorkflowDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// 1. Build the sub-agents
CreativeWriter writer = AgenticServices.agentBuilder(CreativeWriter.class)
.chatModel(model)
.outputKey("story") // Output goes into AgenticScope as "story"
.build();
StyleEditor editor = AgenticServices.agentBuilder(StyleEditor.class)
.chatModel(model)
.outputKey("edited_story") // Output goes into AgenticScope as "edited_story"
.build();
// 2. Build the sequence
UntypedAgent workflow = AgenticServices.sequenceBuilder()
.subAgents(writer, editor)
.outputKey("edited_story") // Final output of workflow
.build();
// 3. Run the workflow with inputs
Map<String, Object> inputs = Map.of(
"topic", "a cat learning to fly",
"style", "Shakespearean"
);
String result = (String) workflow.invoke(inputs);
System.out.println("Final Edited Story:\n" + result);
}
}
من المفترض أن تظهر لك نتيجة مشابهة لما يلي:
Final Edited Story:
For years had Barnaby with envy watched
The soaring sparrows with a green-eyed spite,
Convinced that heavy gravity was but
An idle law he deigned to tolerate.
But lo! Upon the rare and azure moon,
He scaled the summit of the ancient oak,
Closed fast his eyes, and leapt with blind belief.
While the dread squirrel shrieked in sheer dismay,
No downward plunge befell the daring beast;
For summer's zephyr bore his belly up,
And through the vault of night's celestial sphere,
He rowed his velvet paws among the stars.
التعرّف على AgenticScope
أثناء التنفيذ، تدير LangChain4j AgenticScope.
- تتم كتابة خريطة الإدخال
{"topic": "...", "style": "..."}في النطاق. - يتم تنفيذ
CreativeWriter، ويتطلّب ذلكtopicالذي تتم قراءته من النطاق، ويتم إخراجstoryالذي يتم حفظه مرة أخرى في النطاق. - يتم تنفيذ
StyleEditor، ويتطلّبstory(الذي ينتجه الكاتب) وstyle(من المدخلات الأولية)، ويُخرجedited_storyإلى النطاق. - يكتمل سير العمل ويعرض قيمة
edited_story.
8. 8. تنظيم مهام سير العمل المتعددة الوكلاء: التنفيذ المتوازي
في بعض السيناريوهات، يمكن للوكلاء الفرعيين العمل بشكل مستقل على الإدخال نفسه، ويمكن تنفيذ مهامهم بالتوازي.
على سبيل المثال، لننشئ مستشارًا للسفر يطلب من خبير في الأفلام وخبير في الطعام تقديم اقتراحات لمدينة معيّنة، ثم يجمع بين هذه الاقتراحات.
إنشاء MovieExpert.java في src/main/java/com/example/MovieExpert.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import java.util.List;
public interface MovieExpert {
@UserMessage("Suggest 2 movies filmed in {{city}}.")
@Agent(description = "Suggests movies filmed in a city")
List<String> findMovies(@V("city") String city);
}
إنشاء DiningExpert.java في src/main/java/com/example/DiningExpert.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import java.util.List;
public interface DiningExpert {
@UserMessage("Suggest 2 local dishes to try in {{city}}.")
@Agent(description = "Suggests local dishes to try in a city")
List<String> findDishes(@V("city") String city);
}
لننشئ الآن نظامًا متوازيًا يعتمد على الوكلاء. سنحدّد واجهة لمنسّق المستوى الأعلى: TravelAdvisorAgent.
إنشاء TravelAdvisorAgent.java في src/main/java/com/example/TravelAdvisorAgent.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.V;
import java.util.Map;
public interface TravelAdvisorAgent {
@Agent
Map<String, Object> planTrip(@V("city") String city);
}
أنشئ ParallelWorkflowDemo.java في src/main/java/com/example/ParallelWorkflowDemo.java لربطها معًا:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import java.util.List;
import java.util.Map;
public class ParallelWorkflowDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// 1. Build independent agents
MovieExpert movieExpert = AgenticServices.agentBuilder(MovieExpert.class)
.chatModel(model)
.outputKey("movies")
.build();
DiningExpert diningExpert = AgenticServices.agentBuilder(DiningExpert.class)
.chatModel(model)
.outputKey("dishes")
.build();
// 2. Build the Parallel agent
TravelAdvisorAgent travelAdvisor = AgenticServices.parallelBuilder(TravelAdvisorAgent.class)
.subAgents(movieExpert, diningExpert)
.output(scope -> {
// Combine the independent outputs in the AgenticScope
List<String> movies = scope.readState("movies", List.of());
List<String> dishes = scope.readState("dishes", List.of());
return Map.of("movies", movies, "dishes", dishes);
})
.build();
// 3. Invoke
Map<String, Object> plan = travelAdvisor.planTrip("Tokyo");
System.out.println("Tokyo Trip Plan:\n" + plan);
}
}
من المفترض أن تظهر لك نتيجة مشابهة لما يلي:
Tokyo Trip Plan:
{movies=[Lost in Translation, Tokyo Story], dishes=[Monjayaki, Edomae-zushi]}
In this parallel workflow, `movieExpert` and `diningExpert` execute concurrently. The `output(...)` configuration defines how to gather their respective results from the `AgenticScope` and merge them into the final result.
## 9. Build Goal-Oriented Agents (GOAP)
Duration: 07:00
Sequential and Parallel workflows are structured and predictable, but rigid. What if we want the system to figure out the path to the goal autonomously, but in a **deterministic, algorithmic way** rather than trusting an LLM to loop (like ReAct)?
This is where **Goal-Oriented Action Planning (GOAP)** shines.
By looking at the declared inputs and outputs of each agent, the `GoalOrientedPlanner` builds a dependency graph. When you invoke the system with a goal, it calculates the shortest path from the current state (available variables) to that goal.
Let's build a Horoscope & News combined writer. It requires 4 agents:
1. `PersonExtractor`: extracts person details from prompt.
2. `SignExtractor`: extracts zodiac sign from prompt.
3. `HoroscopeGenerator`: generates horoscope given person and sign.
4. `AmusingWriter`: writes a funny story combining a horoscope and a news story.
We will also define a `StoryFinder` that uses a mock search tool.
### 1. Define Model Classes
Create `Person.java` in `src/main/java/com/example/Person.java`:
```java
package com.example;
public record Person(String name) {
@Override public String toString() { return name; }
}
إنشاء Sign.java في src/main/java/com/example/Sign.java:
package com.example;
public record Sign(String signName) {
@Override public String toString() { return signName; }
}
2. تحديد الوكلاء الفرعيين
إنشاء HoroscopeGenerator.java في src/main/java/com/example/HoroscopeGenerator.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface HoroscopeGenerator {
@UserMessage("Generate a funny horoscope for {{person}} who is a {{sign}}.")
@Agent(description = "Generates horoscopes based on name and zodiac sign")
String horoscope(@V("person") Person person, @V("sign") Sign sign);
}
إنشاء PersonExtractor.java في src/main/java/com/example/PersonExtractor.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface PersonExtractor {
@UserMessage("Extract the person name from: {{prompt}}")
@Agent(description = "Extracts a person from user's prompt")
Person extractPerson(@V("prompt") String prompt);
}
إنشاء SignExtractor.java في src/main/java/com/example/SignExtractor.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface SignExtractor {
@UserMessage("Extract the zodiac sign from: {{prompt}}")
@Agent(description = "Extracts a zodiac sign from user's prompt")
Sign extractSign(@V("prompt") String prompt);
}
إنشاء AmusingWriter.java في src/main/java/com/example/AmusingWriter.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface AmusingWriter {
@UserMessage("Create an amusing writeup for {{person}} based on their horoscope: {{horoscope}} and current news story: {{story}}.")
@Agent(description = "Create an amusing writeup combining horoscope and news")
String write(@V("person") Person person, @V("horoscope") String horoscope, @V("story") String story);
}
3- تحديد الأداة للعثور على القصص
سننشئ فئة بسيطة لأداة البحث تعرض قصة وهمية. إنشاء MockSearchTool.java في src/main/java/com/example/MockSearchTool.java:
package com.example;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
public class MockSearchTool {
@Tool("Searches the web for news stories related to a zodiac sign")
public String searchNews(@P("The zodiac sign") String sign) {
return "Breaking news: A massive cheese festival was announced for " + sign + " natives today!";
}
}
أنشئ StoryFinder.java في وكيل src/main/java/com/example/StoryFinder.java يستخدم هذه الأداة:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface StoryFinder {
@UserMessage("Find a funny story for zodiac sign {{sign}} using search tool.")
@Agent(description = "Finds a news story on the internet about a zodiac sign")
String findStory(@V("sign") Sign sign);
}
4. إنشاء نظام يستند إلى الذكاء الاصطناعي الوكيل وتشغيله
إنشاء GoapDemo.java في src/main/java/com/example/GoapDemo.java:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.agentic.UntypedAgent;
import dev.langchain4j.agentic.patterns.goap.GoalOrientedPlanner;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import java.util.Map;
public class GoapDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// Instantiate sub-agents with output keys matching the inputs of other agents
HoroscopeGenerator horoscopeGen = AgenticServices.agentBuilder(HoroscopeGenerator.class)
.chatModel(model).outputKey("horoscope").build();
PersonExtractor personExt = AgenticServices.agentBuilder(PersonExtractor.class)
.chatModel(model).outputKey("person").build();
SignExtractor signExt = AgenticServices.agentBuilder(SignExtractor.class)
.chatModel(model).outputKey("sign").build();
StoryFinder storyFinder = AgenticServices.agentBuilder(StoryFinder.class)
.chatModel(model).tools(new MockSearchTool()).outputKey("story").build();
AmusingWriter writer = AgenticServices.agentBuilder(AmusingWriter.class)
.chatModel(model).outputKey("writeup").build();
// Build the GOAP Planner agentic system
UntypedAgent horoscopeNewsAgent = AgenticServices.plannerBuilder()
.subAgents(horoscopeGen, personExt, signExt, storyFinder, writer)
.outputKey("writeup") // The Goal we want to achieve
.planner(GoalOrientedPlanner::new) // Register the GOAP Planner
.build();
// Input provides only "prompt"
Map<String, Object> inputs = Map.of(
"prompt", "My name is Alice and my zodiac sign is Leo"
);
System.out.println("Invoking GOAP Agentic System...");
String result = (String) horoscopeNewsAgent.invoke(inputs);
System.out.println("\n--- Final Writeup ---");
System.out.println(result);
}
}
كيف حلّت "خطة عمل الحكومة" هذه المشكلة؟
عند استدعاء هذه الوظيفة:
- يرصد النظام أنّ الحالة الأولية تحتوي على
promptفقط. - الهدف المطلوب هو
writeup. - يتم إنشاء رسم بياني للمهام التابعة واحتساب المسار:
prompt->PersonExtractor->personprompt->SignExtractor->signperson+sign->HoroscopeGenerator->horoscopesign->StoryFinder->storyperson+horoscope+story->AmusingWriter->writeup
- ترتيب التنفيذ المحسوب هو:
[PersonExtractor, SignExtractor, HoroscopeGenerator, StoryFinder, AmusingWriter]. - ويتم تنفيذ كل وكيل فرعي بالترتيب وعرض النتيجة النهائية.
من المفترض أن تظهر لك نتيجة تعرض مسار التنفيذ والملخّص النهائي، على النحو التالي:
Invoking GOAP Agentic System...
[com.example.GoapDemo.main()] INFO dev.langchain4j.agentic.patterns.goap.GoalOrientedSearchGraph - Agents path sequence: [extractPerson, extractSign, findStory, horoscope, write]
--- Final Writeup ---
**The Cosmic Registry's Weekly Forecast & Special Event Guide for: Alice, the Leo Lioness**
Alice, the universe looked at your astrological chart this week and frankly, it's asking for your autograph. Your main-character energy is currently so potent that secondary characters are practically fading into the background.
But the biggest cosmic news of the week? The universe has finally recognized your royal status with the announcement of a **Massive Cheese Festival**...
9- 10. تَنظيم
لتنظيف الموارد، اتّبِع الخطوات التالية:
- احرص على حذف أي مفاتيح لواجهة برمجة التطبيقات من Google AI Studio إذا لم تعُد تستخدمها.
- ألغِ ضبط متغيّر البيئة في الوحدة الطرفية:
unset GEMINI_API_KEY
10. 11. تهانينا
تهانينا! لقد أنشأت بنجاح سلسلة من تطبيقات الذكاء الاصطناعي الوكيل باستخدام LangChain4j ووحدة Google GenAI الجديدة.
لتطوير مهاراتك، ننصحك بالاطّلاع على مستندات وحدة Google GenAI الرسمية في LangChain4j والتعرّف على مزيد من المعلومات حول إنشاء وكلاء باستخدام LangChain4j.
ما تعلّمته
- كيفية ضبط
GoogleGenAiChatModel - كيفية استخدام أدوات Java المحلية وتسجيل الطلبات والاستجابات
- كيفية إخراج بيانات POJO منظَّمة
- كيفية إنشاء وكلاء ذوي غرض واحد باستخدام
@Agent - كيفية تنظيم مهام سير العمل المتسلسلة والمتوازية والمستندة إلى الذكاء الاصطناعي الوكيل والموجّهة نحو تحقيق الأهداف