chore: Update version to 1.6.6 and refactor agentType method for context handling

This commit is contained in:
extio-de
2025-07-10 00:20:16 +02:00
parent df3034e6ca
commit d9fae7eebd
5 changed files with 55 additions and 26 deletions

View File

@@ -4,7 +4,7 @@
<artifactId>lm-lib</artifactId> <artifactId>lm-lib</artifactId>
<groupId>de.extio</groupId> <groupId>de.extio</groupId>
<name>lm-lib</name> <name>lm-lib</name>
<version>1.6.4</version> <version>1.6.6</version>
<properties> <properties>
<java.version>21</java.version> <java.version>21</java.version>

View File

@@ -28,6 +28,14 @@ public record Agent(String name,
} }
} }
@Override
public AgentType agentType(final AgentContext context) {
if (agentType != null) {
return agentType;
}
return BaseAgent.super.agentType(context);
}
@Override @Override
public void preProcess(final AgentContext context) { public void preProcess(final AgentContext context) {
if (preProcessor != null) { if (preProcessor != null) {

View File

@@ -67,7 +67,7 @@ public class AgentExecutorService implements InitializingBean, DisposableBean {
LOGGER.debug("Agent: {}", agent.name()); LOGGER.debug("Agent: {}", agent.name());
Client client = null; Client client = null;
if (agent.agentType() != AgentType.PROCESSING_ONLY) { if (agent.agentType(context) != AgentType.PROCESSING_ONLY) {
client = this.clientService.getClient(agent.modelCategory()); client = this.clientService.getClient(agent.modelCategory());
} }
context.setAgentContextUpdateConsumer(agentContextUpdateConsumer); context.setAgentContextUpdateConsumer(agentContextUpdateConsumer);

View File

@@ -34,10 +34,6 @@ public interface BaseAgent {
throw new UnsupportedOperationException("Name must be implemented in the agent"); 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() { default ModelCategory modelCategory() {
return ModelCategory.MEDIUM; return ModelCategory.MEDIUM;
} }
@@ -54,6 +50,10 @@ public interface BaseAgent {
return new TextAgentResponseHandler("response"); 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) { default void preProcess(final AgentContext context) {
} }
@@ -82,7 +82,7 @@ public interface BaseAgent {
for (final var split : splits) { for (final var split : splits) {
tasks.add(CompletableFuture.runAsync(() -> { tasks.add(CompletableFuture.runAsync(() -> {
try { 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) { if (skipCompletion) {
split.context().setSkipNextCompletion(false); split.context().setSkipNextCompletion(false);
split.context().getGraph().add("○"); split.context().getGraph().add("○");
@@ -263,13 +263,23 @@ public interface BaseAgent {
conversation = Conversation.create(this.systemPrompt(), split.text()); conversation = Conversation.create(this.systemPrompt(), split.text());
split.context().setConversation(conversation); split.context().setConversation(conversation);
} }
else if (this.agentType() == AgentType.START_CONVERSATION) { 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()); conversation = Conversation.create(this.systemPrompt() + "\n" + split.text());
}
split.context().setConversation(conversation); split.context().setConversation(conversation);
} }
else { else {
if (conversation.getConversation().get(0).type() == TurnType.SYSTEM && this.agentType() != AgentType.CONVERSATION_WITH_SYSTEM_PROMPT) { if (conversation.getConversation().get(0).type() == TurnType.SYSTEM && this.agentType(split.context()) != AgentType.CONVERSATION_WITH_SYSTEM_PROMPT) {
final var mergedSysAndUser = conversation.getConversation().get(0).text() + "\n" + conversation.getConversation().get(1).text(); 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); final var newConversation = Conversation.create(mergedSysAndUser);
for (int n = 2; n < conversation.getConversation().size(); n++) { for (int n = 2; n < conversation.getConversation().size(); n++) {
@@ -280,9 +290,14 @@ public interface BaseAgent {
conversation = newConversation; conversation = newConversation;
} }
if (conversation.getConversation().get(conversation.getConversation().size() - 1).type() == TurnType.ASSISTANT) { if (conversation.getConversation().get(conversation.getConversation().size() - 1).type() == TurnType.ASSISTANT) {
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()))); conversation.addTurn(new Conversation.Turn(TurnType.USER, String.join("\n", this.systemPrompt(), split.text())));
} }
} }
}
return conversation; return conversation;
} }
@@ -312,30 +327,30 @@ public interface BaseAgent {
context.setNextAgent(null); 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.getGraph().add("→");
context.setConversation(null); 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.getGraph().add("🗨");
context.setConversation(null); 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("↴"); context.getGraph().add("↴");
if (context.getConversation().getConversation().getLast().type() != TurnType.ASSISTANT) { if (context.getConversation().getConversation().getLast().type() != TurnType.ASSISTANT) {
context.getConversation().addTurn(new Conversation.Turn(TurnType.ASSISTANT, context.getLastCompletion().response())); 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 -> { default -> {
context.getGraph().add("☢"); context.getGraph().add("☢");
LOGGER.error("Unknown agent type: {}", nextAgent.agentType()); LOGGER.error("Unknown agent type: {}", nextAgent.agentType(context));
context.setNextAgent(null); context.setNextAgent(null);
} }
} }

View File

@@ -10,7 +10,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -126,6 +125,7 @@ public class AgentTest {
@Test @Test
void streamedAgenticFlow() throws IOException { void streamedAgenticFlow() throws IOException {
final var lastStreamedSummary = new AtomicReference<String>();
final var agents = Map.of( final var agents = Map.of(
"CodeSummarizer", "CodeSummarizer",
new Agent("CodeSummarizer", new Agent("CodeSummarizer",
@@ -133,7 +133,17 @@ public class AgentTest {
ModelCategory.MEDIUM, ModelCategory.MEDIUM,
"Generate a summary of the following Java source code.", "Generate a summary of the following Java source code.",
"The source code is:\n{{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, null,
context -> { context -> {
context.setStringValue("summary", context.getStringValue("summary") + "\npostprocessed"); context.setStringValue("summary", context.getStringValue("summary") + "\npostprocessed");
@@ -145,16 +155,12 @@ public class AgentTest {
context.setStreaming(true); context.setStreaming(true);
context.getContext().put("code", List.of(Files.readString(Path.of("src/main/java/de/extio/lmlib/agent/BaseAgent.java")))); context.getContext().put("code", List.of(Files.readString(Path.of("src/main/java/de/extio/lmlib/agent/BaseAgent.java"))));
final var lastStreamedSummary = new AtomicReference<String>();
final var resultContexts = this.agentExecutor.walk(agents.get("CodeSummarizer"), context, contextUpdate -> { 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 // This is an optional consumer that can be used to receive updates from the agent context
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)
}
}); });
assertEquals(1, resultContexts.size()); 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")); assertTrue(resultContexts.getFirst().getStringValue("summary").endsWith("postprocessed"));
System.out.println(); System.out.println();