diff --git a/README.md b/README.md index fdcb2d5..ad97c93 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,23 @@ Note that the agents selected depend on the user's query and the available agent ### Prerequisites - Java 21 or higher - Maven 3.6 or higher +- A [Secure Repository Token](https://account.akka.io/token) ### Build and run +--- + +### Secure Repository Token + +Building requires a secure repository token, which is set up as part of [Akka CLI](https://doc.akka.io/getting-started/quick-install-cli.html)'s `akka code init` command. + +If you still need to configure your system with the token there are two additional ways: + +1. Use the Akka CLI's `akka code token` command and follow the instructions. +2. Set up the token manually as described [here](https://account.akka.io/token). + +--- + To run the application, you need to provide the following environment variables: - `OPENAI_API_KEY`: Your OpenAI API key. If you prefer to use a different LLM model, follow the instructions in `application.conf` to change it. - `WEATHER_API_KEY`: (Optional) API key for the weather service diff --git a/pom.xml b/pom.xml index 4fdcfe3..2991f12 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.akka akka-javasdk-parent - 3.5.10 + 3.5.11 io.akka.ai diff --git a/src/main/java/demo/multiagent/application/ActivityView.java b/src/main/java/demo/multiagent/application/ActivityView.java index 323fd3f..327ca59 100644 --- a/src/main/java/demo/multiagent/application/ActivityView.java +++ b/src/main/java/demo/multiagent/application/ActivityView.java @@ -18,7 +18,11 @@ public record ActivityEntry( String sessionId, String userQuestion, String finalAnswer - ) {} + ) { + public boolean hasFinalAnswer() { + return finalAnswer != null && !finalAnswer.isEmpty(); + } + } @Query("SELECT * AS entries FROM activities WHERE userId = :userId") public QueryEffect getActivities(String userId) { diff --git a/src/main/java/demo/multiagent/application/PreferencesConsumer.java b/src/main/java/demo/multiagent/application/PreferencesConsumer.java index a22824a..cbffe8a 100644 --- a/src/main/java/demo/multiagent/application/PreferencesConsumer.java +++ b/src/main/java/demo/multiagent/application/PreferencesConsumer.java @@ -32,7 +32,7 @@ public Effect onPreferenceAdded(PreferencesEvent.PreferenceAdded event) { // Call EvaluatorAgent for each session for (var activity : activities.entries()) { - if (activity.finalAnswer() != null && !activity.finalAnswer().isEmpty()) { + if (activity.hasFinalAnswer()) { var evaluationRequest = new EvaluatorAgent.EvaluationRequest( userId, activity.userQuestion(), diff --git a/src/test/java/demo/multiagent/api/ActivityEndpointIntegrationTest.java b/src/test/java/demo/multiagent/api/ActivityEndpointIntegrationTest.java index 98ed1ca..e4285b5 100644 --- a/src/test/java/demo/multiagent/api/ActivityEndpointIntegrationTest.java +++ b/src/test/java/demo/multiagent/api/ActivityEndpointIntegrationTest.java @@ -9,7 +9,12 @@ import akka.javasdk.testkit.TestKit; import akka.javasdk.testkit.TestKitSupport; import akka.javasdk.testkit.TestModelProvider; -import demo.multiagent.application.*; +import demo.multiagent.application.ActivityAgent; +import demo.multiagent.application.EvaluatorAgent; +import demo.multiagent.application.PlannerAgent; +import demo.multiagent.application.SelectorAgent; +import demo.multiagent.application.SummarizerAgent; +import demo.multiagent.application.WeatherAgent; import demo.multiagent.domain.AgentSelection; import demo.multiagent.domain.Plan; import demo.multiagent.domain.PlanStep; @@ -52,10 +57,14 @@ public void shouldHandleFullActivitySuggestionWorkflowWithPreferenceUpdate() { // Setup initial AI model responses setupInitialModelResponses(); + //debug id for correlating tracing information + String debugId = "12345"; + // 1. Call suggestActivities endpoint var suggestResponse = httpClient .POST("/activities/" + userId) .withRequestBody(new ActivityEndpoint.Request(query)) + .addHeader("akka-debug-id", debugId) .invoke(); assertThat(suggestResponse.status()).isEqualTo(StatusCodes.CREATED); @@ -103,13 +112,35 @@ public void shouldHandleFullActivitySuggestionWorkflowWithPreferenceUpdate() { var suggestion = activitiesList.suggestions().getFirst(); assertThat(suggestion.userQuestion()).isEqualTo(query); assertThat(suggestion.answer()).contains("bike tour"); + + var steps = telemetryReader.getWorkflowSteps(debugId); + assertThat(steps).containsOnly( + "select-agents", + "create-plan", + "execute-plan", + "execute-plan", + "summarize" + ); + + var agents = telemetryReader.getAgents(debugId); + assertThat(agents).containsOnly( + "selector-agent", + "planner-agent", + "weather-agent", + "activity-agent", + "summarizer-agent", + "toxicity-evaluator", + "summarization-evaluator" + ); }); // 4. Add preference that invalidates previous suggestion setupUpdatedModelResponsesForPreference(); + var nextDebugId = "67890"; var preferenceResponse = httpClient .POST("/preferences/" + userId) + .addHeader("akka-debug-id", nextDebugId) .withRequestBody( new ActivityEndpoint.AddPreference( "I hate outdoor activities and prefer indoor museums" @@ -135,6 +166,17 @@ public void shouldHandleFullActivitySuggestionWorkflowWithPreferenceUpdate() { assertThat(updatedAnswer).contains("Vasa Museum"); assertThat(updatedAnswer).contains("indoor"); assertThat(updatedAnswer).doesNotContain("bike tour"); + + assertThat(telemetryReader.getAgents(nextDebugId)).containsOnly( + "evaluator-agent", + "selector-agent", + "planner-agent", + "weather-agent", + "activity-agent", + "summarizer-agent", + "toxicity-evaluator", + "summarization-evaluator" + ); }); }