From d9fae7eebde0e585fcbb7037825adda0cf84f825 Mon Sep 17 00:00:00 2001 From: extio-de Date: Thu, 10 Jul 2025 00:20:16 +0200 Subject: [PATCH] chore: Update version to 1.6.6 and refactor agentType method for context handling --- pom.xml | 2 +- src/main/java/de/extio/lmlib/agent/Agent.java | 8 ++++ .../lmlib/agent/AgentExecutorService.java | 2 +- .../java/de/extio/lmlib/agent/BaseAgent.java | 47 ++++++++++++------- .../java/de/extio/lmlib/agent/AgentTest.java | 22 +++++---- 5 files changed, 55 insertions(+), 26 deletions(-) diff --git a/pom.xml b/pom.xml index 11f44de..29ed5af 100755 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ lm-lib de.extio lm-lib - 1.6.4 + 1.6.6 21 diff --git a/src/main/java/de/extio/lmlib/agent/Agent.java b/src/main/java/de/extio/lmlib/agent/Agent.java index 08c085a..7724214 100755 --- a/src/main/java/de/extio/lmlib/agent/Agent.java +++ b/src/main/java/de/extio/lmlib/agent/Agent.java @@ -27,6 +27,14 @@ public record Agent(String name, throw new IllegalArgumentException("Agent type cannot be null"); } } + + @Override + public AgentType agentType(final AgentContext context) { + if (agentType != null) { + return agentType; + } + return BaseAgent.super.agentType(context); + } @Override public void preProcess(final AgentContext context) { diff --git a/src/main/java/de/extio/lmlib/agent/AgentExecutorService.java b/src/main/java/de/extio/lmlib/agent/AgentExecutorService.java index 267a4f0..175a284 100755 --- a/src/main/java/de/extio/lmlib/agent/AgentExecutorService.java +++ b/src/main/java/de/extio/lmlib/agent/AgentExecutorService.java @@ -67,7 +67,7 @@ public class AgentExecutorService implements InitializingBean, DisposableBean { LOGGER.debug("Agent: {}", agent.name()); Client client = null; - if (agent.agentType() != AgentType.PROCESSING_ONLY) { + if (agent.agentType(context) != AgentType.PROCESSING_ONLY) { client = this.clientService.getClient(agent.modelCategory()); } context.setAgentContextUpdateConsumer(agentContextUpdateConsumer); diff --git a/src/main/java/de/extio/lmlib/agent/BaseAgent.java b/src/main/java/de/extio/lmlib/agent/BaseAgent.java index 066a006..50b114b 100644 --- a/src/main/java/de/extio/lmlib/agent/BaseAgent.java +++ b/src/main/java/de/extio/lmlib/agent/BaseAgent.java @@ -34,10 +34,6 @@ public interface BaseAgent { throw new UnsupportedOperationException("Name must be implemented in the agent"); } - default AgentType agentType() { - throw new UnsupportedOperationException("Agent type must be implemented in the agent"); - } - default ModelCategory modelCategory() { return ModelCategory.MEDIUM; } @@ -53,6 +49,10 @@ public interface BaseAgent { default AgentResponseHandler responseHandler() { return new TextAgentResponseHandler("response"); } + + default AgentType agentType(final AgentContext context) { + throw new UnsupportedOperationException("Agent type must be implemented in the agent"); + } default void preProcess(final AgentContext context) { @@ -82,7 +82,7 @@ public interface BaseAgent { for (final var split : splits) { tasks.add(CompletableFuture.runAsync(() -> { try { - final boolean skipCompletion = split.context().isSkipNextCompletion() || this.agentType() == AgentType.PROCESSING_ONLY; + final boolean skipCompletion = split.context().isSkipNextCompletion() || this.agentType(split.context()) == AgentType.PROCESSING_ONLY; if (skipCompletion) { split.context().setSkipNextCompletion(false); split.context().getGraph().add("○"); @@ -263,13 +263,23 @@ public interface BaseAgent { conversation = Conversation.create(this.systemPrompt(), split.text()); split.context().setConversation(conversation); } - else if (this.agentType() == AgentType.START_CONVERSATION) { - conversation = Conversation.create(this.systemPrompt() + "\n" + split.text()); + else if (this.agentType(split.context()) == AgentType.START_CONVERSATION) { + if (this.systemPrompt() == null || this.systemPrompt().isEmpty()) { + conversation = Conversation.create(split.text()); + } + else { + conversation = Conversation.create(this.systemPrompt() + "\n" + split.text()); + } split.context().setConversation(conversation); } else { - if (conversation.getConversation().get(0).type() == TurnType.SYSTEM && this.agentType() != AgentType.CONVERSATION_WITH_SYSTEM_PROMPT) { - final var mergedSysAndUser = conversation.getConversation().get(0).text() + "\n" + conversation.getConversation().get(1).text(); + if (conversation.getConversation().get(0).type() == TurnType.SYSTEM && this.agentType(split.context()) != AgentType.CONVERSATION_WITH_SYSTEM_PROMPT) { + final String mergedSysAndUser; + if (conversation.getConversation().size() > 1) { + mergedSysAndUser = conversation.getConversation().get(0).text() + "\n" + conversation.getConversation().get(1).text(); + } else { + mergedSysAndUser = conversation.getConversation().get(0).text(); + } final var newConversation = Conversation.create(mergedSysAndUser); for (int n = 2; n < conversation.getConversation().size(); n++) { @@ -280,7 +290,12 @@ public interface BaseAgent { conversation = newConversation; } if (conversation.getConversation().get(conversation.getConversation().size() - 1).type() == TurnType.ASSISTANT) { - conversation.addTurn(new Conversation.Turn(TurnType.USER, String.join("\n", this.systemPrompt(), split.text()))); + if (this.systemPrompt() == null || this.systemPrompt().isEmpty() ||conversation.getConversation().size() > 1) { + conversation.addTurn(new Conversation.Turn(TurnType.USER, split.text())); + } + else { + conversation.addTurn(new Conversation.Turn(TurnType.USER, String.join("\n", this.systemPrompt(), split.text()))); + } } } return conversation; @@ -312,30 +327,30 @@ public interface BaseAgent { context.setNextAgent(null); } - case final BaseAgent a when a.agentType() == AgentType.COMPLETION -> { + case final BaseAgent a when a.agentType(context) == AgentType.COMPLETION -> { context.getGraph().add("→"); context.setConversation(null); } - case final BaseAgent a when a.agentType() == AgentType.START_CONVERSATION -> { + case final BaseAgent a when a.agentType(context) == AgentType.START_CONVERSATION -> { context.getGraph().add("🗨"); context.setConversation(null); } - case final BaseAgent a when a.agentType() == AgentType.CONVERSATION || a.agentType() == AgentType.CONVERSATION_WITH_SYSTEM_PROMPT -> { + case final BaseAgent a when a.agentType(context) == AgentType.CONVERSATION || a.agentType(context) == AgentType.CONVERSATION_WITH_SYSTEM_PROMPT -> { context.getGraph().add("↴"); if (context.getConversation().getConversation().getLast().type() != TurnType.ASSISTANT) { context.getConversation().addTurn(new Conversation.Turn(TurnType.ASSISTANT, context.getLastCompletion().response())); } } - case final BaseAgent a when a.agentType() == AgentType.PROCESSING_ONLY -> { - + case final BaseAgent a when a.agentType(context) == AgentType.PROCESSING_ONLY -> { + } default -> { context.getGraph().add("☢"); - LOGGER.error("Unknown agent type: {}", nextAgent.agentType()); + LOGGER.error("Unknown agent type: {}", nextAgent.agentType(context)); context.setNextAgent(null); } } diff --git a/src/test/java/de/extio/lmlib/agent/AgentTest.java b/src/test/java/de/extio/lmlib/agent/AgentTest.java index f3ca591..1faa3d8 100644 --- a/src/test/java/de/extio/lmlib/agent/AgentTest.java +++ b/src/test/java/de/extio/lmlib/agent/AgentTest.java @@ -10,7 +10,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -126,6 +125,7 @@ public class AgentTest { @Test void streamedAgenticFlow() throws IOException { + final var lastStreamedSummary = new AtomicReference(); final var agents = Map.of( "CodeSummarizer", new Agent("CodeSummarizer", @@ -133,7 +133,17 @@ public class AgentTest { ModelCategory.MEDIUM, "Generate a summary of the following Java source code.", "The source code is:\n{{code}}", - new TextAgentResponseHandler("summary"), + new TextAgentResponseHandler("summary", + null, + null, + null, + context -> { + if ("summary".equals(context.getStringValue(TextAgentResponseHandler.UPDATE_KEY))) { // UPDATE_KEY helps you to identify the streamed chunk + System.out.print(context.getStringValue("summary_chunk")); // Single chunks can be accessed via _chunk suffix, depends on the StreamedAgentResponseHandler implementation + lastStreamedSummary.set(context.getStringValue("summary")); // The current key value can also be accessed (e.g. concatenated, depends on the StreamedAgentResponseHandler implementation) + } + } + ), null, context -> { context.setStringValue("summary", context.getStringValue("summary") + "\npostprocessed"); @@ -145,16 +155,12 @@ public class AgentTest { context.setStreaming(true); context.getContext().put("code", List.of(Files.readString(Path.of("src/main/java/de/extio/lmlib/agent/BaseAgent.java")))); - final var lastStreamedSummary = new AtomicReference(); final var resultContexts = this.agentExecutor.walk(agents.get("CodeSummarizer"), context, contextUpdate -> { - if ("summary".equals(contextUpdate.getStringValue(TextAgentResponseHandler.UPDATE_KEY))) { // UPDATE_KEY helps you to identify the streamed chunk - System.out.print(contextUpdate.getStringValue("summary_chunk")); // Single chunks can be accessed via _chunk suffix, depends on the StreamedAgentResponseHandler implementation - lastStreamedSummary.set(contextUpdate.getStringValue("summary")); // The current key value can also be accessed (e.g. concatenated, depends on the StreamedAgentResponseHandler implementation) - } + // This is an optional consumer that can be used to receive updates from the agent context }); assertEquals(1, resultContexts.size()); - assertEquals(lastStreamedSummary.get(), resultContexts.getFirst().getStringValue("summary")); + assertEquals(lastStreamedSummary.get() + "\npostprocessed", resultContexts.getFirst().getStringValue("summary")); assertTrue(resultContexts.getFirst().getStringValue("summary").endsWith("postprocessed")); System.out.println();