Skip to content

Commit a29b25b

Browse files
committed
Introduce LangChain4j Agentic Workflow Implementation
Signed-off-by: Ricardo Zanini <ricardozanini@gmail.com>
1 parent 0608eca commit a29b25b

File tree

16 files changed

+662
-14
lines changed

16 files changed

+662
-14
lines changed

fluent/agentic-langchain4j/pom.xml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>io.serverlessworkflow</groupId>
8+
<artifactId>serverlessworkflow-fluent</artifactId>
9+
<version>8.0.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>serverlessworkflow-fluent-agentic-langchain4j</artifactId>
13+
<name>Serverless Workflow :: Fluent :: Agentic LangChain4j</name>
14+
<description>Agentic Workflow DSL Implementation for langchain4j-agentic</description>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>io.serverlessworkflow</groupId>
19+
<artifactId>serverlessworkflow-experimental-types</artifactId>
20+
</dependency>
21+
<dependency>
22+
<groupId>io.serverlessworkflow</groupId>
23+
<artifactId>serverlessworkflow-fluent-agentic</artifactId>
24+
</dependency>
25+
<dependency>
26+
<groupId>dev.langchain4j</groupId>
27+
<artifactId>langchain4j-agentic</artifactId>
28+
</dependency>
29+
30+
<dependency>
31+
<groupId>org.slf4j</groupId>
32+
<artifactId>slf4j-simple</artifactId>
33+
<scope>test</scope>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.junit.jupiter</groupId>
37+
<artifactId>junit-jupiter-api</artifactId>
38+
<scope>test</scope>
39+
</dependency>
40+
<dependency>
41+
<groupId>org.mockito</groupId>
42+
<artifactId>mockito-core</artifactId>
43+
<scope>test</scope>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.assertj</groupId>
47+
<artifactId>assertj-core</artifactId>
48+
<scope>test</scope>
49+
</dependency>
50+
<dependency>
51+
<groupId>dev.langchain4j</groupId>
52+
<artifactId>langchain4j-ollama</artifactId>
53+
<scope>test</scope>
54+
<version>${version.dev.langchain4j}</version>
55+
</dependency>
56+
<dependency>
57+
<groupId>io.serverlessworkflow</groupId>
58+
<artifactId>serverlessworkflow-fluent-agentic</artifactId>
59+
<type>test-jar</type>
60+
<scope>test</scope>
61+
</dependency>
62+
</dependencies>
63+
64+
65+
66+
67+
68+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.fluent.agentic.langchain4j;
17+
18+
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19+
import io.serverlessworkflow.api.types.Workflow;
20+
import io.serverlessworkflow.fluent.agentic.AgentWorkflowBuilder;
21+
import java.util.function.Consumer;
22+
import java.util.function.Function;
23+
24+
public abstract class AbstractAgentService<T, S> implements WorkflowDefinitionBuilder {
25+
26+
private static final Function<Cognisphere, Object> DEFAULT_OUTPUT_FUNCTION = cognisphere -> null;
27+
private static final Consumer<Cognisphere> DEFAULT_INIT_FUNCTION = cognisphere -> {};
28+
29+
protected final AgentWorkflowBuilder workflowBuilder;
30+
protected final Class<T> agentServiceClass;
31+
32+
protected AbstractAgentService(Class<T> agentServiceClass) {
33+
this("", agentServiceClass);
34+
}
35+
36+
protected AbstractAgentService(String name, Class<T> agentServiceClass) {
37+
this.workflowBuilder =
38+
AgentWorkflowBuilder.workflow(name)
39+
.outputAs(DEFAULT_OUTPUT_FUNCTION)
40+
.input(i -> i.from(DEFAULT_INIT_FUNCTION));
41+
this.agentServiceClass = agentServiceClass;
42+
}
43+
44+
@SuppressWarnings("unchecked")
45+
public S beforeCall(Consumer<Cognisphere> beforeCall) {
46+
// TODO: Our runner must know that our input can be a cognisphere object and extract it from the
47+
// context, so that we can accept the consumer.
48+
// TODO: For now, we can add the consumer to inputFrom
49+
this.workflowBuilder.input(i -> i.from(beforeCall));
50+
return (S) this;
51+
}
52+
53+
@SuppressWarnings("unchecked")
54+
public S outputName(String outputName) {
55+
// TODO: This can be solved using a combination with our output object
56+
this.workflowBuilder.document(d -> d.name(outputName));
57+
return (S) this;
58+
}
59+
60+
@SuppressWarnings("unchecked")
61+
public S output(Function<Cognisphere, Object> output) {
62+
this.workflowBuilder.outputAs(output);
63+
return (S) this;
64+
}
65+
66+
@Override
67+
public Workflow getDefinition() {
68+
return this.workflowBuilder.build();
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.fluent.agentic.langchain4j;
17+
18+
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19+
import dev.langchain4j.agentic.internal.AgentExecutor;
20+
import dev.langchain4j.agentic.workflow.ConditionalAgentService;
21+
import java.util.Arrays;
22+
import java.util.List;
23+
import java.util.function.Predicate;
24+
25+
public class ConditionalAgentServiceImpl<T>
26+
extends AbstractAgentService<T, ConditionalAgentService<T>>
27+
implements ConditionalAgentService<T> {
28+
29+
private ConditionalAgentServiceImpl(Class<T> agentServiceClass) {
30+
super(agentServiceClass);
31+
}
32+
33+
public static <T> ConditionalAgentService<T> builder(Class<T> agentServiceClass) {
34+
return new ConditionalAgentServiceImpl<>(agentServiceClass);
35+
}
36+
37+
@Override
38+
public T build() {
39+
return null;
40+
}
41+
42+
@Override
43+
public ConditionalAgentService<T> subAgents(Object... agents) {
44+
this.workflowBuilder.tasks(t -> t.sequence(agents));
45+
return this;
46+
}
47+
48+
@Override
49+
public ConditionalAgentService<T> subAgents(List<AgentExecutor> agentExecutors) {
50+
return this.subAgents(agentExecutors.toArray());
51+
}
52+
53+
@Override
54+
public ConditionalAgentService<T> subAgents(Predicate<Cognisphere> condition, Object... agents) {
55+
this.workflowBuilder.tasks(
56+
t -> Arrays.stream(agents).forEach(agent -> t.when(condition).agent(agent)));
57+
return this;
58+
}
59+
60+
@Override
61+
public ConditionalAgentService<T> subAgents(
62+
Predicate<Cognisphere> condition, List<AgentExecutor> agentExecutors) {
63+
return this.subAgents(condition, agentExecutors.toArray());
64+
}
65+
66+
@Override
67+
public ConditionalAgentService<T> subAgent(
68+
Predicate<Cognisphere> condition, AgentExecutor agentExecutor) {
69+
this.workflowBuilder.tasks(t -> t.when(condition).agent(agentExecutor));
70+
return this;
71+
}
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.fluent.agentic.langchain4j;
17+
18+
import dev.langchain4j.agentic.UntypedAgent;
19+
import dev.langchain4j.agentic.workflow.ConditionalAgentService;
20+
import dev.langchain4j.agentic.workflow.LoopAgentService;
21+
import dev.langchain4j.agentic.workflow.ParallelAgentService;
22+
import dev.langchain4j.agentic.workflow.SequentialAgentService;
23+
import dev.langchain4j.agentic.workflow.WorkflowAgentsBuilder;
24+
25+
public class LC4JWorkflowBuilder implements WorkflowAgentsBuilder {
26+
27+
@Override
28+
public SequentialAgentService<UntypedAgent> sequenceBuilder() {
29+
return SequentialAgentServiceImpl.builder(UntypedAgent.class);
30+
}
31+
32+
@Override
33+
public <T> SequentialAgentService<T> sequenceBuilder(Class<T> agentServiceClass) {
34+
return SequentialAgentServiceImpl.builder(agentServiceClass);
35+
}
36+
37+
@Override
38+
public ParallelAgentService<UntypedAgent> parallelBuilder() {
39+
return ParallelAgentServiceImpl.builder(UntypedAgent.class);
40+
}
41+
42+
@Override
43+
public <T> ParallelAgentService<T> parallelBuilder(Class<T> agentServiceClass) {
44+
return ParallelAgentServiceImpl.builder(agentServiceClass);
45+
}
46+
47+
@Override
48+
public LoopAgentService<UntypedAgent> loopBuilder() {
49+
return LoopAgentServiceImpl.builder(UntypedAgent.class);
50+
}
51+
52+
@Override
53+
public <T> LoopAgentService<T> loopBuilder(Class<T> agentServiceClass) {
54+
return LoopAgentServiceImpl.builder(agentServiceClass);
55+
}
56+
57+
@Override
58+
public ConditionalAgentService<UntypedAgent> conditionalBuilder() {
59+
return ConditionalAgentServiceImpl.builder(UntypedAgent.class);
60+
}
61+
62+
@Override
63+
public <T> ConditionalAgentService<T> conditionalBuilder(Class<T> agentServiceClass) {
64+
return ConditionalAgentServiceImpl.builder(agentServiceClass);
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.fluent.agentic.langchain4j;
17+
18+
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19+
import dev.langchain4j.agentic.internal.AgentExecutor;
20+
import dev.langchain4j.agentic.workflow.LoopAgentService;
21+
import io.serverlessworkflow.fluent.agentic.LoopAgentsBuilder;
22+
import java.util.List;
23+
import java.util.function.Predicate;
24+
25+
public class LoopAgentServiceImpl<T> extends AbstractAgentService<T, LoopAgentService<T>>
26+
implements LoopAgentService<T> {
27+
28+
private final LoopAgentsBuilder loopAgentsBuilder = new LoopAgentsBuilder();
29+
30+
private LoopAgentServiceImpl(Class<T> agentServiceClass) {
31+
super(agentServiceClass);
32+
}
33+
34+
public static <T> LoopAgentService<T> builder(Class<T> agentServiceClass) {
35+
return new LoopAgentServiceImpl<>(agentServiceClass);
36+
}
37+
38+
@Override
39+
public LoopAgentService<T> maxIterations(int maxIterations) {
40+
this.loopAgentsBuilder.maxIterations(maxIterations);
41+
return this;
42+
}
43+
44+
@Override
45+
public LoopAgentService<T> exitCondition(Predicate<Cognisphere> exitCondition) {
46+
this.loopAgentsBuilder.exitCondition(exitCondition);
47+
return this;
48+
}
49+
50+
@Override
51+
public T build() {
52+
return null;
53+
}
54+
55+
@Override
56+
public LoopAgentService<T> subAgents(Object... agents) {
57+
this.loopAgentsBuilder.subAgents(agents);
58+
this.workflowBuilder.tasks(t -> t.loop(this.loopAgentsBuilder));
59+
return this;
60+
}
61+
62+
@Override
63+
public LoopAgentService<T> subAgents(List<AgentExecutor> agentExecutors) {
64+
this.loopAgentsBuilder.subAgents(agentExecutors.toArray());
65+
this.workflowBuilder.tasks(t -> t.loop(this.loopAgentsBuilder));
66+
return this;
67+
}
68+
}

0 commit comments

Comments
 (0)