Skip to content

Introduce Agentic DSL #667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void testJavaFunction() throws InterruptedException, ExecutionException {
try (WorkflowApplication app = WorkflowApplication.builder().build()) {
final Workflow workflow =
FuncWorkflowBuilder.workflow("testJavaCall")
.tasks(tasks -> tasks.callFn(f -> f.fn(JavaFunctions::getName)))
.tasks(tasks -> tasks.callFn(f -> f.function(JavaFunctions::getName)))
.build();
assertThat(
app.workflowDefinition(workflow)
Expand Down Expand Up @@ -85,7 +85,7 @@ void testSwitch() throws InterruptedException, ExecutionException {
switchOdd.items(
item ->
item.when(CallTest::isOdd).then(FlowDirectiveEnum.END)))
.callFn(callJava -> callJava.fn(CallTest::zero)))
.callFn(callJava -> callJava.function(CallTest::zero)))
.build();

WorkflowDefinition definition = app.workflowDefinition(workflow);
Expand Down
73 changes: 73 additions & 0 deletions fluent/agentic/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<parent>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent</artifactId>
<version>8.0.0-SNAPSHOT</version>
</parent>

<name>Serverless Workflow :: Fluent :: Agentic</name>
<artifactId>serverlessworkflow-fluent-agentic</artifactId>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<version.dev.langchain4j>1.2.0-beta8-SNAPSHOT</version.dev.langchain4j>
</properties>

<dependencies>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-experimental-types</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-types</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent-spec</artifactId>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent-func</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic</artifactId>
<version>${version.dev.langchain4j}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<scope>test</scope>
<version>1.2.0-SNAPSHOT</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.fluent.agentic;

import static dev.langchain4j.agentic.internal.AgentExecutor.agentsToExecutors;

import dev.langchain4j.agentic.Cognisphere;
import dev.langchain4j.agentic.internal.AgentExecutor;
import dev.langchain4j.agentic.internal.AgentInstance;
import io.serverlessworkflow.impl.expressions.LoopPredicateIndex;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

public final class AgentAdapters {
private AgentAdapters() {}

public static List<AgentExecutor> toExecutors(Object... agents) {
return agentsToExecutors(Stream.of(agents).map(AgentInstance.class::cast).toList());
}

public static Function<Cognisphere, Object> toFunction(AgentExecutor exec) {
return exec::invoke;
}

public static LoopPredicateIndex<Object, Object> toWhile(Predicate<Cognisphere> exit) {
return (model, item, idx) -> !exit.test((Cognisphere) model);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.fluent.agentic;

import io.serverlessworkflow.fluent.spec.BaseDoTaskBuilder;

public class AgentDoTaskBuilder
extends BaseDoTaskBuilder<AgentDoTaskBuilder, AgentTaskItemListBuilder>
implements DelegatingAgentDoTaskFluent<AgentDoTaskBuilder> {

AgentDoTaskBuilder() {
super(new AgentTaskItemListBuilder());
}

@Override
public AgentDoTaskBuilder self() {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.fluent.agentic;

import java.util.UUID;
import java.util.function.Consumer;

public interface AgentDoTaskFluent<SELF extends AgentDoTaskFluent<SELF>> {

SELF agent(String name, Object agent);

default SELF agent(Object agent) {
return agent(UUID.randomUUID().toString(), agent);
}

SELF sequence(String name, Object... agents);

default SELF sequence(Object... agents) {
return sequence("seq-" + UUID.randomUUID(), agents);
}

SELF loop(String name, Consumer<LoopAgentsBuilder> builder);

default SELF loop(Consumer<LoopAgentsBuilder> builder) {
return loop("loop-" + UUID.randomUUID(), builder);
}

SELF parallel(String name, Object... agents);

default SELF parallel(Object... agents) {
return parallel("par-" + UUID.randomUUID(), agents);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.fluent.agentic;

import dev.langchain4j.agentic.internal.AgentExecutor;
import io.serverlessworkflow.api.types.Task;
import io.serverlessworkflow.api.types.TaskItem;
import io.serverlessworkflow.fluent.func.FuncTaskItemListBuilder;
import io.serverlessworkflow.fluent.spec.BaseTaskItemListBuilder;
import java.util.List;
import java.util.function.Consumer;

public class AgentTaskItemListBuilder extends BaseTaskItemListBuilder<AgentTaskItemListBuilder>
implements AgentDoTaskFluent<AgentTaskItemListBuilder> {

private final FuncTaskItemListBuilder funcDelegate;

AgentTaskItemListBuilder() {
super();
this.funcDelegate = new FuncTaskItemListBuilder(super.mutableList());
}

@Override
protected AgentTaskItemListBuilder newItemListBuilder() {
return new AgentTaskItemListBuilder();
}

@Override
public AgentTaskItemListBuilder agent(String name, Object agent) {
AgentAdapters.toExecutors(agent)
.forEach(
exec ->
this.funcDelegate.callFn(name, fn -> fn.function(AgentAdapters.toFunction(exec))));
return self();
}

@Override
public AgentTaskItemListBuilder sequence(String name, Object... agents) {
for (int i = 0; i < agents.length; i++) {
agent(name + "-" + i, agents[i]);
}
return self();
}

@Override
public AgentTaskItemListBuilder loop(String name, Consumer<LoopAgentsBuilder> consumer) {
final LoopAgentsBuilder builder = new LoopAgentsBuilder();
consumer.accept(builder);
this.addTaskItem(new TaskItem(name, new Task().withForTask(builder.build())));
return self();
}

@Override
public AgentTaskItemListBuilder parallel(String name, Object... agents) {
this.funcDelegate.forkFn(
name,
fork -> {
List<AgentExecutor> execs = AgentAdapters.toExecutors(agents);
for (int i = 0; i < execs.size(); i++) {
AgentExecutor ex = execs.get(i);
fork.branch("branch-" + i + "-" + name, AgentAdapters.toFunction(ex));
}
});
return self();
}

@Override
public AgentTaskItemListBuilder self() {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.fluent.agentic;

import static java.lang.constant.ConstantDescs.DEFAULT_NAME;

import io.serverlessworkflow.fluent.spec.BaseWorkflowBuilder;

public final class AgenticWorkflowBuilder
extends BaseWorkflowBuilder<
AgenticWorkflowBuilder, AgentDoTaskBuilder, AgentTaskItemListBuilder> {

AgenticWorkflowBuilder(final String name, final String namespace, final String version) {
super(name, namespace, version);
}

public static AgenticWorkflowBuilder workflow() {
return new AgenticWorkflowBuilder(DEFAULT_NAME, DEFAULT_NAMESPACE, DEFAULT_VERSION);
}

public static AgenticWorkflowBuilder workflow(String name) {
return new AgenticWorkflowBuilder(name, DEFAULT_NAMESPACE, DEFAULT_VERSION);
}

public static AgenticWorkflowBuilder workflow(String name, String ns) {
return new AgenticWorkflowBuilder(name, ns, DEFAULT_VERSION);
}

@Override
protected AgentDoTaskBuilder newDo() {
return new AgentDoTaskBuilder();
}

@Override
protected AgenticWorkflowBuilder self() {
return this;
}
}
Loading
Loading