Skip to content

Commit 0549d73

Browse files
committed
Introduce LangChain4j Agentic Workflow Implementation
1 parent 8d85aea commit 0549d73

File tree

30 files changed

+1203
-73
lines changed

30 files changed

+1203
-73
lines changed

experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModel.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,15 @@
1616
package io.serverlessworkflow.impl.expressions.agentic;
1717

1818
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19-
import dev.langchain4j.agentic.cognisphere.ResultWithCognisphere;
2019
import io.serverlessworkflow.impl.WorkflowModel;
2120
import io.serverlessworkflow.impl.expressions.func.JavaModel;
2221
import java.util.Collection;
23-
import java.util.Collections;
2422
import java.util.Optional;
2523

2624
class AgenticModel extends JavaModel {
2725

28-
private final Cognisphere cognisphere;
29-
30-
AgenticModel(Object object, Cognisphere cognisphere) {
31-
super(object);
32-
this.cognisphere = cognisphere;
26+
AgenticModel(Cognisphere cognisphere) {
27+
super(cognisphere);
3328
}
3429

3530
@Override
@@ -39,17 +34,13 @@ public void setObject(Object obj) {
3934

4035
@Override
4136
public Collection<WorkflowModel> asCollection() {
42-
return object instanceof Collection value
43-
? new AgenticModelCollection(value, cognisphere)
44-
: Collections.emptyList();
37+
throw new UnsupportedOperationException("Not supported yet.");
4538
}
4639

4740
@Override
4841
public <T> Optional<T> as(Class<T> clazz) {
4942
if (Cognisphere.class.isAssignableFrom(clazz)) {
50-
return Optional.of(clazz.cast(cognisphere));
51-
} else if (ResultWithCognisphere.class.isAssignableFrom(clazz)) {
52-
return Optional.of(clazz.cast(new ResultWithCognisphere<>(cognisphere, object)));
43+
return Optional.of(clazz.cast(object));
5344
} else {
5445
return super.as(clazz);
5546
}

experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelCollection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class AgenticModelCollection extends JavaModelCollection {
3737

3838
@Override
3939
protected WorkflowModel nextItem(Object obj) {
40-
return new AgenticModel(obj, cognisphere);
40+
return new AgenticModel((Cognisphere) obj);
4141
}
4242

4343
@Override

experimental/agentic/src/main/java/io/serverlessworkflow/impl/expressions/agentic/AgenticModelFactory.java

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,17 @@
1616
package io.serverlessworkflow.impl.expressions.agentic;
1717

1818
import dev.langchain4j.agentic.cognisphere.Cognisphere;
19-
import dev.langchain4j.agentic.cognisphere.CognisphereRegistry;
2019
import io.cloudevents.CloudEvent;
2120
import io.cloudevents.CloudEventData;
2221
import io.serverlessworkflow.impl.WorkflowModel;
2322
import io.serverlessworkflow.impl.WorkflowModelCollection;
2423
import io.serverlessworkflow.impl.WorkflowModelFactory;
24+
import io.serverlessworkflow.impl.expressions.func.JavaModel;
2525
import java.time.OffsetDateTime;
2626
import java.util.Map;
2727

2828
class AgenticModelFactory implements WorkflowModelFactory {
2929

30-
private Cognisphere cognisphere = CognisphereRegistry.createEphemeralCognisphere();
31-
32-
private final AgenticModel TrueModel = new AgenticModel(Boolean.TRUE, cognisphere);
33-
private final AgenticModel FalseModel = new AgenticModel(Boolean.FALSE, cognisphere);
34-
private final AgenticModel NullModel = new AgenticModel(null, cognisphere);
35-
36-
public void setCognishere(Cognisphere cognisphere) {
37-
this.cognisphere = cognisphere;
38-
}
39-
4030
@Override
4131
public WorkflowModel fromAny(WorkflowModel prev, Object obj) {
4232
((AgenticModel) prev).setObject(obj);
@@ -45,57 +35,59 @@ public WorkflowModel fromAny(WorkflowModel prev, Object obj) {
4535

4636
@Override
4737
public WorkflowModel combine(Map<String, WorkflowModel> workflowVariables) {
48-
return new AgenticModel(workflowVariables, cognisphere);
38+
throw new UnsupportedOperationException();
4939
}
5040

5141
@Override
5242
public WorkflowModelCollection createCollection() {
53-
return new AgenticModelCollection(cognisphere);
43+
throw new UnsupportedOperationException();
5444
}
5545

5646
@Override
5747
public WorkflowModel from(boolean value) {
58-
return value ? TrueModel : FalseModel;
48+
return new JavaModel(value);
5949
}
6050

6151
@Override
6252
public WorkflowModel from(Number value) {
63-
return new AgenticModel(value, cognisphere);
53+
return new JavaModel(value);
6454
}
6555

6656
@Override
6757
public WorkflowModel from(String value) {
68-
return new AgenticModel(value, cognisphere);
58+
return new JavaModel(value);
6959
}
7060

7161
@Override
7262
public WorkflowModel from(CloudEvent ce) {
73-
return new AgenticModel(ce, cognisphere);
63+
return new JavaModel(ce);
7464
}
7565

7666
@Override
7767
public WorkflowModel from(CloudEventData ce) {
78-
return new AgenticModel(ce, cognisphere);
68+
return new JavaModel(ce);
7969
}
8070

8171
@Override
8272
public WorkflowModel from(OffsetDateTime value) {
83-
return new AgenticModel(value, cognisphere);
73+
return new JavaModel(value);
8474
}
8575

8676
@Override
8777
public WorkflowModel from(Map<String, Object> map) {
88-
cognisphere.writeStates(map);
89-
return new AgenticModel(map, cognisphere);
78+
return new JavaModel(map);
9079
}
9180

9281
@Override
9382
public WorkflowModel fromNull() {
94-
return NullModel;
83+
return new JavaModel(null);
9584
}
9685

9786
@Override
9887
public WorkflowModel fromOther(Object value) {
99-
return new AgenticModel(value, cognisphere);
88+
if (value instanceof Cognisphere) {
89+
return new AgenticModel((Cognisphere) value);
90+
}
91+
return new JavaModel(value);
10092
}
10193
}

experimental/lambda/src/main/java/io/serverlessworkflow/impl/expressions/func/JavaModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class JavaModel implements WorkflowModel {
2828

2929
protected Object object;
3030

31-
protected JavaModel(Object object) {
31+
public JavaModel(Object object) {
3232
this.object = asJavaObject(object);
3333
}
3434

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-agentic</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,85 @@
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.cognisphere.DefaultCognisphere;
20+
import dev.langchain4j.agentic.internal.AgentSpecification;
21+
import dev.langchain4j.agentic.internal.CognisphereOwner;
22+
import io.serverlessworkflow.api.types.Workflow;
23+
import io.serverlessworkflow.fluent.agentic.AgentWorkflowBuilder;
24+
import io.serverlessworkflow.impl.WorkflowApplication;
25+
import java.lang.reflect.Proxy;
26+
import java.util.function.Consumer;
27+
import java.util.function.Function;
28+
29+
public abstract class AbstractAgentService<T, S> implements WorkflowDefinitionBuilder {
30+
31+
// Workflow OutputAs
32+
private static final Function<Cognisphere, Object> DEFAULT_OUTPUT_FUNCTION = cognisphere -> null;
33+
34+
protected final WorkflowApplication.Builder workflowExecBuilder;
35+
protected final AgentWorkflowBuilder workflowBuilder;
36+
protected final Class<T> agentServiceClass;
37+
38+
protected AbstractAgentService(Class<T> agentServiceClass) {
39+
this.workflowBuilder =
40+
AgentWorkflowBuilder.workflow()
41+
.outputAs(DEFAULT_OUTPUT_FUNCTION);
42+
this.agentServiceClass = agentServiceClass;
43+
this.workflowExecBuilder = WorkflowApplication.builder();
44+
}
45+
46+
@SuppressWarnings("unchecked")
47+
public T build() {
48+
return (T)
49+
Proxy.newProxyInstance(
50+
this.agentServiceClass.getClassLoader(),
51+
new Class<?>[] {agentServiceClass, AgentSpecification.class, CognisphereOwner.class},
52+
new WorkflowInvocationHandler(this.workflowBuilder.build(), this.workflowExecBuilder, this.agentServiceClass));
53+
}
54+
55+
@SuppressWarnings("unchecked")
56+
public S beforeCall(Consumer<Cognisphere> beforeCall) {
57+
this.workflowBuilder.inputFrom(
58+
cog -> {
59+
beforeCall.accept(cog);
60+
return cog;
61+
},
62+
Cognisphere.class);
63+
return (S) this;
64+
}
65+
66+
@SuppressWarnings("unchecked")
67+
public S outputName(String outputName) {
68+
Function<DefaultCognisphere, Object> outputFunction = cog -> cog.readState(outputName);
69+
this.workflowBuilder.outputAs(outputFunction, DefaultCognisphere.class);
70+
this.workflowBuilder.document(
71+
d -> d.metadata(m -> m.metadata(META_KEY_OUTPUTNAME, outputName)));
72+
return (S) this;
73+
}
74+
75+
@SuppressWarnings("unchecked")
76+
public S output(Function<Cognisphere, Object> output) {
77+
this.workflowBuilder.outputAs(output, Cognisphere.class);
78+
return (S) this;
79+
}
80+
81+
@Override
82+
public Workflow getDefinition() {
83+
return this.workflowBuilder.build();
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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 ConditionalAgentService<T> subAgents(Object... agents) {
39+
this.workflowBuilder.tasks(t -> t.sequence(agents));
40+
return this;
41+
}
42+
43+
@Override
44+
public ConditionalAgentService<T> subAgents(List<AgentExecutor> agentExecutors) {
45+
return this.subAgents(agentExecutors.toArray());
46+
}
47+
48+
@Override
49+
public ConditionalAgentService<T> subAgents(Predicate<Cognisphere> condition, Object... agents) {
50+
this.workflowBuilder.tasks(
51+
t -> Arrays.stream(agents).forEach(agent -> t.when(condition).agent(agent)));
52+
return this;
53+
}
54+
55+
@Override
56+
public ConditionalAgentService<T> subAgents(
57+
Predicate<Cognisphere> condition, List<AgentExecutor> agentExecutors) {
58+
return this.subAgents(condition, agentExecutors.toArray());
59+
}
60+
61+
@Override
62+
public ConditionalAgentService<T> subAgent(
63+
Predicate<Cognisphere> condition, AgentExecutor agentExecutor) {
64+
this.workflowBuilder.tasks(t -> t.when(condition).agent(agentExecutor));
65+
return this;
66+
}
67+
}

0 commit comments

Comments
 (0)