Skip to content

Commit 601fa63

Browse files
committed
add better docs about Langchain4g/ServerlessWorkflow
Signed-off-by: Dmitrii Tikhomirov <[email protected]>
1 parent 01f64f8 commit 601fa63

File tree

3 files changed

+169
-95
lines changed

3 files changed

+169
-95
lines changed

experimental/fluent/agentic/src/main/java/io/serverlessworkflow/fluent/agentic/dsl/AgenticDSL.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public static AgentTaskConfigurer loop(Predicate<AgenticScope> exitCondition, Ob
122122
}
123123

124124
public static AgentTaskConfigurer loop(
125-
Predicate<AgenticScope> exitCondition, int maxIterations, Object... agents) {
125+
int maxIterations, Predicate<AgenticScope> exitCondition, Object... agents) {
126126
return list ->
127127
list.loop(
128128
l -> l.subAgents(agents).exitCondition(exitCondition).maxIterations(maxIterations));

experimental/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/LC4JEquivalenceIT.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static io.serverlessworkflow.fluent.agentic.AgentWorkflowBuilder.workflow;
1919
import static io.serverlessworkflow.fluent.agentic.dsl.AgenticDSL.conditional;
2020
import static io.serverlessworkflow.fluent.agentic.dsl.AgenticDSL.doTasks;
21+
import static io.serverlessworkflow.fluent.agentic.dsl.AgenticDSL.loop;
2122
import static org.assertj.core.api.Assertions.assertThat;
2223
import static org.junit.jupiter.api.Assertions.assertEquals;
2324

@@ -45,10 +46,7 @@ public void sequentialWorkflow() {
4546
var audienceEditor = AgentsUtils.newAudienceEditor();
4647
var styleEditor = AgentsUtils.newStyleEditor();
4748

48-
Workflow wf =
49-
workflow("seqFlow")
50-
.sequence("process", creativeWriter, audienceEditor, styleEditor)
51-
.build();
49+
Workflow wf = workflow("seqFlow").sequence(creativeWriter, audienceEditor, styleEditor).build();
5250

5351
List<TaskItem> items = wf.getDo();
5452
assertThat(items).hasSize(3);
@@ -118,7 +116,7 @@ public void loopWorkflowWithMaxIterations() {
118116

119117
Predicate<AgenticScope> until = s -> s.readState("score", 0).doubleValue() >= 0.8;
120118

121-
Workflow wf = workflow("retryFlow").loop(until, scorer, 5, editor).build();
119+
Workflow wf = workflow("retryFlow").tasks(loop(5, until, scorer, editor)).build();
122120

123121
List<TaskItem> items = wf.getDo();
124122
assertThat(items).hasSize(1);

experimental/fluent/agentic/src/test/java/io/serverlessworkflow/fluent/agentic/README.md

Lines changed: 165 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
# Sequential workflow
44
### Common part:
5+
<details><summary>Click to expand</summary>
6+
57
```java
68
public interface AudienceEditor {
79

@@ -65,33 +67,53 @@ Map<String, Object> input = Map.of(
6567
"audience", "young adults"
6668
);
6769
```
68-
69-
### LangChain4j
70-
```java
71-
UntypedAgent novelCreator = AgenticServices
72-
.sequenceBuilder()
73-
.subAgents(creativeWriter, audienceEditor, styleEditor)
74-
.outputName("story")
75-
.build();
70+
</details>
71+
72+
<table style="table-layout:fixed; width:100%;">
73+
<tr>
74+
<th style="width:50%; text-align:left;">LangChain4j</th>
75+
<th style="text-align:left;">Serverless Workflow</th>
76+
</tr>
77+
<tr>
78+
<td style="vertical-align:top;">
79+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
80+
<code class="language-java" style="background:none;white-space:pre;">UntypedAgent novelCreator = AgenticServices
81+
.sequenceBuilder()
82+
.subAgents(creativeWriter, audienceEditor, styleEditor)
83+
.outputName("story")
84+
.build();
7685

7786
String story = (String) novelCreator.invoke(input);
78-
```
7987

80-
### Serverless Workflow
88+
</code>
89+
</pre>
90+
</td>
8191

82-
```java
83-
Workflow wf = workflow("seqFlow").sequence("process", creativeWriter, audienceEditor, styleEditor).build();
92+
<td style="vertical-align:top;">
93+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
94+
<code class="language-java" style="background:none;white-space:pre;">Workflow wf = workflow("seqFlow")
95+
.sequence(creativeWriter, audienceEditor, styleEditor)
96+
.build();
97+
&nbsp;
98+
&nbsp;
8499

85100
try (WorkflowApplication app = WorkflowApplication.builder().build()) {
86101
String result = app.workflowDefinition(wf).instance(input).start().get().asText().orElseThrow();
87102
} catch (Exception e) {
88103
throw new RuntimeException("Workflow execution failed", e);
89104
}
90-
```
105+
106+
</code>
107+
</pre>
108+
</td>
109+
</tr>
110+
</table>
91111

92112

93113
### Loop workflow
94114
### Common part:
115+
<details><summary>Click to expand</summary>
116+
95117
```java
96118
interface StyleEditor {
97119

@@ -136,38 +158,58 @@ StyleScorer styleScorer = AgenticServices
136158

137159
```
138160

139-
### LangChain4j
140-
```java
161+
</details>
162+
163+
<table style="table-layout:fixed; width:100%;">
164+
<tr>
165+
<th style="width:50%; text-align:left;">LangChain4j</th>
166+
<th style="text-align:left;">Serverless Workflow</th>
167+
</tr>
168+
<tr>
169+
<td style="vertical-align:top;">
170+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
171+
<code class="language-java" style="background:none;white-space:pre;">
172+
&nbsp;
173+
&nbsp;
141174
StyledWriter styledWriter = AgenticServices
142-
.sequenceBuilder(StyledWriter.class)
143-
.subAgents(creativeWriter, styleReviewLoop)
144-
.outputName("story")
145-
.build();
175+
.sequenceBuilder(StyledWriter.class)
176+
.subAgents(creativeWriter, styleReviewLoop)
177+
.outputName("story")
178+
.build();
146179

147180
String story = styledWriter.writeStoryWithStyle("dragons and wizards", "comedy");
148-
```
149-
150-
### Serverless Workflow
151-
```java
152-
Predicate<AgenticScope> until = s -> s.readState("score", 0).doubleValue() >= 0.8;
153181

154-
Workflow wf = workflow("retryFlow").loop(until, scorer, 5, editor).build();
182+
</code>
183+
</pre>
184+
</td>
155185

186+
<td style="vertical-align:top;">
187+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
188+
<code class="language-java" style="background:none;white-space:pre;">Map&lt;String, Object> input = Map.of("story", "dragons and wizards","style", "comedy");
189+
Predicate<AgenticScope> until = s -> s.readState("score", 0).doubleValue() >= 0.8;
156190

157-
Map<String, Object> input =
158-
Map.of(
159-
"story", "dragons and wizards",
160-
"style", "comedy");
161-
191+
Workflow wf = workflow("retryFlow")
192+
.loop(until, scorer, editor)
193+
.build();
194+
&nbsp;
195+
&nbsp;
196+
&nbsp;
162197
try (WorkflowApplication app = WorkflowApplication.builder().build()) {
163-
String result = app.workflowDefinition(wf).instance(input).start().get().asText().orElseThrow();
198+
String result = app.workflowDefinition(wf).instance(input).start().get().asText().orElseThrow();
164199
} catch (Exception e) {
165-
throw new RuntimeException("Workflow execution failed", e);
200+
throw new RuntimeException("Workflow execution failed", e);
166201
}
167-
```
202+
203+
</code>
204+
</pre>
205+
</td>
206+
</tr>
207+
</table>
168208

169209
### Parallel workflow
170210
### Common part:
211+
<details><summary>Click to expand</summary>
212+
171213
```java
172214
public interface FoodExpert {
173215

@@ -206,65 +248,81 @@ MovieExpert movieExpert = AgenticServices
206248
.outputName("movies")
207249
.build();
208250
```
209-
210-
### LangChain4j
211-
```java
251+
</details>
252+
253+
254+
<table style="table-layout:fixed; width:100%;">
255+
<tr>
256+
<th style="width:50%; text-align:left;">LangChain4j</th>
257+
<th style="text-align:left;">Serverless Workflow</th>
258+
</tr>
259+
<tr>
260+
<td style="vertical-align:top;">
261+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
262+
<code class="language-java" style="background:none;white-space:pre;">
212263
EveningPlannerAgent eveningPlannerAgent = AgenticServices
213-
.parallelBuilder(EveningPlannerAgent.class)
214-
.subAgents(foodExpert, movieExpert)
215-
.executor(Executors.newFixedThreadPool(2))
216-
.outputName("plans")
217-
.output(agenticScope -> {
218-
List<String> movies = agenticScope.readState("movies", List.of());
219-
List<String> meals = agenticScope.readState("meals", List.of());
220-
221-
List<EveningPlan> moviesAndMeals = new ArrayList<>();
222-
for (int i = 0; i < movies.size(); i++) {
223-
if (i >= meals.size()) {
224-
break;
225-
}
226-
moviesAndMeals.add(new EveningPlan(movies.get(i), meals.get(i)));
227-
}
228-
return moviesAndMeals;
229-
})
230-
.build();
264+
.parallelBuilder(EveningPlannerAgent.class)
265+
.subAgents(foodExpert, movieExpert)
266+
.executor(Executors.newFixedThreadPool(2))
267+
.outputName("plans")
268+
.output(agenticScope -> {
269+
List<String> movies = agenticScope.readState("movies", List.of());
270+
List<String> meals = agenticScope.readState("meals", List.of());
271+
List<EveningPlan> moviesAndMeals = new ArrayList<>();
272+
for (int i = 0; i < movies.size(); i++) {
273+
if (i >= meals.size()) {
274+
break;
275+
}
276+
moviesAndMeals.add(new EveningPlan(movies.get(i), meals.get(i)));
277+
}
278+
return moviesAndMeals;
279+
})
280+
.build();
231281

232282
List<EveningPlan> plans = eveningPlannerAgent.plan("romantic");
233-
```
234283

235-
### Serverless Workflow
236-
```java
237-
Workflow wf = workflow("forkFlow").parallel("fanout", foodExpert, movieExpert).build();
284+
</code>
285+
</pre>
286+
</td>
287+
288+
<td style="vertical-align:top;">
289+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
290+
<code class="language-java" style="background:none;white-space:pre;">
291+
Workflow wf = workflow("forkFlow")
292+
.parallel(foodExpert, movieExpert)
293+
.build();
294+
&nbsp;
295+
&nbsp;
296+
&nbsp;
297+
&nbsp;
298+
&nbsp;
299+
&nbsp;
300+
&nbsp;
301+
&nbsp;
302+
&nbsp;
303+
&nbsp;
304+
&nbsp;
305+
&nbsp;
306+
&nbsp;
307+
Map&lt;String, Object> input = Map.of("mood", "I am hungry and bored");
238308

239-
Map<String, Object> input = Map.of("mood", "I am hungry and bored");
240-
241-
Map<String, Object> result;
242309
try (WorkflowApplication app = WorkflowApplication.builder().build()) {
243-
result = app.workflowDefinition(wf).instance(input).start().get().asMap().orElseThrow();
310+
Map<String, Object> result = app.workflowDefinition(wf).instance(input).start().get().asMap().orElseThrow();
244311
} catch (Exception e) {
245-
throw new RuntimeException("Workflow execution failed", e);
312+
throw new RuntimeException("Workflow execution failed", e);
246313
}
247-
```
248-
249-
### Error handling
250-
### Common part:
251-
```java
252-
253-
```
254-
255-
### LangChain4j
256-
```java
257-
258-
```
259314

260-
### Serverless Workflow
315+
</code>
316+
</pre>
317+
</td>
318+
</tr>
319+
</table>
261320

262-
```java
263-
264-
```
265321

266322
### Human-in-the-loop
267323
### Common part:
324+
<details><summary>Click to expand</summary>
325+
268326
```java
269327
public record HumanInTheLoop(Consumer<String> requestWriter, Supplier<String> responseReader) {
270328

@@ -302,28 +360,46 @@ HumanInTheLoop humanInTheLoop = AgenticServices
302360
.responseReader(() -> System.console().readLine())
303361
.build();
304362
```
305-
306-
### LangChain4j
307-
```java
363+
</details>
364+
365+
<table style="table-layout:fixed; width:100%;">
366+
<tr>
367+
<th style="width:50%; text-align:left;">LangChain4j</th>
368+
<th style="text-align:left;">Serverless Workflow</th>
369+
</tr>
370+
<tr>
371+
<td style="vertical-align:top;">
372+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
373+
<code class="language-java" style="background:none;white-space:pre;">
308374
SupervisorAgent horoscopeAgent = AgenticServices
309375
.supervisorBuilder()
310376
.chatModel(PLANNER_MODEL)
311377
.subAgents(astrologyAgent, humanInTheLoop)
312378
.build();
313379

314380
horoscopeAgent.invoke("My name is Mario. What is my horoscope?")
315-
```
316381

317-
### Serverless Workflow
382+
</code>
383+
</pre>
384+
</td>
318385

319-
```java
320-
Workflow wf = workflow("seqFlow").sequence("process", astrologyAgent, humanInTheLoop).build();
386+
<td style="vertical-align:top;">
387+
<pre style="background:none; margin:0; padding:0; font-family:monospace; line-height:1.4;">
388+
<code class="language-java" style="background:none;white-space:pre;">
389+
Workflow wf = workflow("seqFlow")
390+
.sequence(astrologyAgent, humanInTheLoop)
391+
.build();
321392

322393
Map<String, Object> input = Map.of("request", "My name is Mario. What is my horoscope?");
323394

324395
try (WorkflowApplication app = WorkflowApplication.builder().build()) {
325-
String result = app.workflowDefinition(wf).instance(input).start().get().asMap().orElseThrow();
396+
String result = app.workflowDefinition(wf).instance(input).start().get().asMap().orElseThrow();
326397
} catch (Exception e) {
327-
throw new RuntimeException("Workflow execution failed", e);
398+
throw new RuntimeException("Workflow execution failed", e);
328399
}
329-
```
400+
401+
</code>
402+
</pre>
403+
</td>
404+
</tr>
405+
</table>

0 commit comments

Comments
 (0)