From ace90e43664e7c2a2324b450012b146c181eaded Mon Sep 17 00:00:00 2001 From: siri-varma Date: Wed, 6 Aug 2025 21:21:12 -0700 Subject: [PATCH] Add examples Signed-off-by: siri-varma --- .../conversation/AssistantMessageDemo.java | 136 ++++++++++++++++++ .../conversation/DemoConversationAI.java | 49 ------- .../io/dapr/examples/conversation/README.md | 39 +++-- .../examples/conversation/ToolsCallDemo.java | 109 ++++++++++++++ .../conversation/UserMessageDemo.java | 77 ++++++++++ 5 files changed, 352 insertions(+), 58 deletions(-) create mode 100644 examples/src/main/java/io/dapr/examples/conversation/AssistantMessageDemo.java delete mode 100644 examples/src/main/java/io/dapr/examples/conversation/DemoConversationAI.java create mode 100644 examples/src/main/java/io/dapr/examples/conversation/ToolsCallDemo.java create mode 100644 examples/src/main/java/io/dapr/examples/conversation/UserMessageDemo.java diff --git a/examples/src/main/java/io/dapr/examples/conversation/AssistantMessageDemo.java b/examples/src/main/java/io/dapr/examples/conversation/AssistantMessageDemo.java new file mode 100644 index 000000000..7ff2d43be --- /dev/null +++ b/examples/src/main/java/io/dapr/examples/conversation/AssistantMessageDemo.java @@ -0,0 +1,136 @@ +/* + * Copyright 2021 The Dapr 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.dapr.examples.conversation; + +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.DaprPreviewClient; +import io.dapr.client.domain.AssistantMessage; +import io.dapr.client.domain.ConversationInputAlpha2; +import io.dapr.client.domain.ConversationMessage; +import io.dapr.client.domain.ConversationMessageContent; +import io.dapr.client.domain.ConversationRequestAlpha2; +import io.dapr.client.domain.ConversationResponseAlpha2; +import io.dapr.client.domain.ConversationResultAlpha2; +import io.dapr.client.domain.ConversationResultChoices; +import io.dapr.client.domain.ConversationToolCalls; +import io.dapr.client.domain.ConversationToolCallsOfFunction; +import io.dapr.client.domain.SystemMessage; +import io.dapr.client.domain.ToolMessage; +import io.dapr.client.domain.UserMessage; +import reactor.core.publisher.Mono; + +import java.util.ArrayList; +import java.util.List; + +public class AssistantMessageDemo { + /** + * The main method to demonstrate conversation AI with assistant messages and conversation history. + * + * @param args Input arguments (unused). + */ + public static void main(String[] args) { + try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) { + System.out.println("Demonstrating Conversation AI with Assistant Messages and Conversation History"); + + // Create a conversation history with multiple message types + List conversationHistory = new ArrayList<>(); + + // 1. System message to set context + SystemMessage systemMessage = new SystemMessage(List.of( + new ConversationMessageContent("You are a helpful assistant that can help with weather queries.") + )); + systemMessage.setName("WeatherBot"); + conversationHistory.add(systemMessage); + + // 2. Initial user greeting + UserMessage greeting = new UserMessage(List.of( + new ConversationMessageContent("Hello! I need help with weather information.") + )); + greeting.setName("User123"); + conversationHistory.add(greeting); + + // 3. Assistant response with tool call + AssistantMessage assistantResponse = new AssistantMessage( + List.of(new ConversationMessageContent("I'll help you with weather information. Let me check the weather for you.")), + List.of(new ConversationToolCalls( + new ConversationToolCallsOfFunction("get_weather", "{\"location\": \"San Francisco\", \"unit\": \"fahrenheit\"}") + )) + ); + assistantResponse.setName("WeatherBot"); + conversationHistory.add(assistantResponse); + + // 4. Tool response (simulating weather API response) + ToolMessage toolResponse = new ToolMessage(List.of( + new ConversationMessageContent("{\"temperature\": \"72F\", \"condition\": \"sunny\", \"humidity\": \"65%\"}") + )); + toolResponse.setName("weather_api"); + conversationHistory.add(toolResponse); + + // 5. Current user question + UserMessage currentQuestion = new UserMessage(List.of( + new ConversationMessageContent("Based on that weather data, should I wear a jacket today?") + )); + currentQuestion.setName("User123"); + conversationHistory.add(currentQuestion); + + // Create conversation input with the full history + ConversationInputAlpha2 conversationInput = new ConversationInputAlpha2(conversationHistory); + conversationInput.setScrubPii(false); + + // Create the conversation request + ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(conversationInput)) + .setContextId("assistant-demo-context") + .setTemperature(0.8d); + + // Send the request + System.out.println("Sending conversation with assistant messages and history..."); + System.out.println("Conversation includes:"); + System.out.println("- System message (context setting)"); + System.out.println("- User greeting"); + System.out.println("- Assistant response with tool call"); + System.out.println("- Tool response with weather data"); + System.out.println("- User follow-up question"); + + Mono responseMono = client.converseAlpha2(request); + ConversationResponseAlpha2 response = responseMono.block(); + + // Process and display the response + if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) { + ConversationResultAlpha2 result = response.getOutputs().get(0); + if (result.getChoices() != null && !result.getChoices().isEmpty()) { + ConversationResultChoices choice = result.getChoices().get(0); + + if (choice.getMessage() != null && choice.getMessage().getContent() != null) { + System.out.printf("Assistant Response: %s%n", choice.getMessage().getContent()); + } + + // Check for additional tool calls in the response + if (choice.getMessage() != null && choice.getMessage().getToolCalls() != null) { + System.out.println("Assistant requested additional tool calls:"); + choice.getMessage().getToolCalls().forEach(toolCall -> { + System.out.printf("Tool: %s, Arguments: %s%n", + toolCall.getFunction().getName(), + toolCall.getFunction().getArguments()); + }); + } + } + } + + System.out.println("Assistant message demonstration completed."); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/examples/src/main/java/io/dapr/examples/conversation/DemoConversationAI.java b/examples/src/main/java/io/dapr/examples/conversation/DemoConversationAI.java deleted file mode 100644 index 09c957026..000000000 --- a/examples/src/main/java/io/dapr/examples/conversation/DemoConversationAI.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2021 The Dapr 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.dapr.examples.conversation; - -import io.dapr.client.DaprClientBuilder; -import io.dapr.client.DaprPreviewClient; -import io.dapr.client.domain.ConversationInput; -import io.dapr.client.domain.ConversationRequest; -import io.dapr.client.domain.ConversationResponse; -import reactor.core.publisher.Mono; - -import java.util.List; - -public class DemoConversationAI { - /** - * The main method to start the client. - * - * @param args Input arguments (unused). - */ - public static void main(String[] args) { - try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) { - System.out.println("Sending the following input to LLM: Hello How are you? This is the my number 672-123-4567"); - - ConversationInput daprConversationInput = new ConversationInput("Hello How are you? " - + "This is the my number 672-123-4567"); - - // Component name is the name provided in the metadata block of the conversation.yaml file. - Mono responseMono = client.converse(new ConversationRequest("echo", - List.of(daprConversationInput)) - .setContextId("contextId") - .setScrubPii(true).setTemperature(1.1d)); - ConversationResponse response = responseMono.block(); - System.out.printf("Conversation output: %s", response.getConversationOutputs().get(0).getResult()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/examples/src/main/java/io/dapr/examples/conversation/README.md b/examples/src/main/java/io/dapr/examples/conversation/README.md index 29468cfb3..f84efcfba 100644 --- a/examples/src/main/java/io/dapr/examples/conversation/README.md +++ b/examples/src/main/java/io/dapr/examples/conversation/README.md @@ -45,30 +45,51 @@ Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initi ### Running the example This example uses the Java SDK Dapr client in order to **Converse** with an LLM. -`DemoConversationAI.java` is the example class demonstrating these features. +`UserMessageDemo.java` is the example class demonstrating these features. Kindly check [DaprPreviewClient.java](https://github.com/dapr/java-sdk/blob/master/sdk/src/main/java/io/dapr/client/DaprPreviewClient.java) for a detailed description of the supported APIs. ```java -public class DemoConversationAI { +public class UserMessageDemo { /** * The main method to start the client. * * @param args Input arguments (unused). */ public static void main(String[] args) { - try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) { + Map, String> overrides = Map.of( + Properties.HTTP_PORT, "3500", + Properties.GRPC_PORT, "50001" + ); + + try (DaprPreviewClient client = new DaprClientBuilder().withPropertyOverrides(overrides).buildPreviewClient()) { System.out.println("Sending the following input to LLM: Hello How are you? This is the my number 672-123-4567"); - ConversationInput daprConversationInput = new ConversationInput("Hello How are you? " - + "This is the my number 672-123-4567"); + // Create user message with content + UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("Hello How are you? " + + "This is the my number 672-123-4567"))); + + // Create conversation input with the user message + ConversationInputAlpha2 daprConversationInput = new ConversationInputAlpha2(List.of(userMessage)); // Component name is the name provided in the metadata block of the conversation.yaml file. - Mono responseMono = client.converse(new ConversationRequest("echo", + Mono responseMono = client.converseAlpha2(new ConversationRequestAlpha2("echo", List.of(daprConversationInput)) .setContextId("contextId") - .setScrubPii(true).setTemperature(1.1d)); - ConversationResponse response = responseMono.block(); - System.out.printf("Conversation output: %s", response.getConversationOutpus().get(0).getResult()); + .setScrubPii(true) + .setTemperature(1.1d)); + + ConversationResponseAlpha2 response = responseMono.block(); + + // Extract and print the conversation result + if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) { + ConversationResultAlpha2 result = response.getOutputs().get(0); + if (result.getChoices() != null && !result.getChoices().isEmpty()) { + ConversationResultChoices choice = result.getChoices().get(0); + if (choice.getMessage() != null && choice.getMessage().getContent() != null) { + System.out.printf("Conversation output: %s", choice.getMessage().getContent()); + } + } + } } catch (Exception e) { throw new RuntimeException(e); } diff --git a/examples/src/main/java/io/dapr/examples/conversation/ToolsCallDemo.java b/examples/src/main/java/io/dapr/examples/conversation/ToolsCallDemo.java new file mode 100644 index 000000000..30335802c --- /dev/null +++ b/examples/src/main/java/io/dapr/examples/conversation/ToolsCallDemo.java @@ -0,0 +1,109 @@ +/* + * Copyright 2021 The Dapr 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.dapr.examples.conversation; + +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.DaprPreviewClient; +import io.dapr.client.domain.ConversationInputAlpha2; +import io.dapr.client.domain.ConversationMessageContent; +import io.dapr.client.domain.ConversationRequestAlpha2; +import io.dapr.client.domain.ConversationResponseAlpha2; +import io.dapr.client.domain.ConversationResultAlpha2; +import io.dapr.client.domain.ConversationResultChoices; +import io.dapr.client.domain.ConversationTools; +import io.dapr.client.domain.ConversationToolsFunction; +import io.dapr.client.domain.SystemMessage; +import io.dapr.client.domain.UserMessage; +import reactor.core.publisher.Mono; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ToolsCallDemo { + /** + * The main method to demonstrate conversation AI with tools/function calling. + * + * @param args Input arguments (unused). + */ + public static void main(String[] args) { + try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) { + System.out.println("Demonstrating Conversation AI with Tools/Function Calling"); + + // Create system message to set context + SystemMessage systemMessage = new SystemMessage(List.of( + new ConversationMessageContent("You are a helpful weather assistant. Use the provided tools to get weather information.") + )); + + // Create user message asking for weather + UserMessage userMessage = new UserMessage(List.of( + new ConversationMessageContent("What's the weather like in San Francisco?") + )); + + // Create conversation input with messages + ConversationInputAlpha2 conversationInput = new ConversationInputAlpha2(List.of(systemMessage, userMessage)); + + // Define function parameters for the weather tool + Map functionParams = new HashMap<>(); + functionParams.put("location", "string"); + functionParams.put("unit", "string"); + + // Create the weather function definition + ConversationToolsFunction weatherFunction = new ConversationToolsFunction("get_current_weather", functionParams); + weatherFunction.setDescription("Get the current weather for a specified location"); + + // Create the tool wrapper + ConversationTools weatherTool = new ConversationTools(weatherFunction); + + // Create the conversation request with tools + ConversationRequestAlpha2 request = new ConversationRequestAlpha2("echo", List.of(conversationInput)) + .setContextId("weather-demo-context") + .setTemperature(0.7d) + .setTools(List.of(weatherTool)); + + // Send the request + System.out.println("Sending request to AI with weather tool available..."); + Mono responseMono = client.converseAlpha2(request); + ConversationResponseAlpha2 response = responseMono.block(); + + // Process and display the response + if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) { + ConversationResultAlpha2 result = response.getOutputs().get(0); + if (result.getChoices() != null && !result.getChoices().isEmpty()) { + ConversationResultChoices choice = result.getChoices().get(0); + + // Check if the AI wants to call a tool + if (choice.getMessage() != null && choice.getMessage().getToolCalls() != null) { + System.out.println("AI requested to call tools:"); + choice.getMessage().getToolCalls().forEach(toolCall -> { + System.out.printf("Tool: %s, Arguments: %s%n", + toolCall.getFunction().getName(), + toolCall.getFunction().getArguments()); + }); + } + + // Display the message content if available + if (choice.getMessage() != null && choice.getMessage().getContent() != null) { + System.out.printf("AI Response: %s%n", choice.getMessage().getContent()); + } + } + } + + System.out.println("Tools call demonstration completed."); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/examples/src/main/java/io/dapr/examples/conversation/UserMessageDemo.java b/examples/src/main/java/io/dapr/examples/conversation/UserMessageDemo.java new file mode 100644 index 000000000..58e847797 --- /dev/null +++ b/examples/src/main/java/io/dapr/examples/conversation/UserMessageDemo.java @@ -0,0 +1,77 @@ +/* + * Copyright 2021 The Dapr 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.dapr.examples.conversation; + +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.DaprPreviewClient; +import io.dapr.client.domain.ConversationInputAlpha2; +import io.dapr.client.domain.ConversationMessageContent; +import io.dapr.client.domain.ConversationRequestAlpha2; +import io.dapr.client.domain.ConversationResponseAlpha2; +import io.dapr.client.domain.ConversationResultAlpha2; +import io.dapr.client.domain.ConversationResultChoices; +import io.dapr.client.domain.UserMessage; +import io.dapr.config.Properties; +import io.dapr.config.Property; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.Map; + +public class UserMessageDemo { + /** + * The main method to start the client. + * + * @param args Input arguments (unused). + */ + public static void main(String[] args) { + Map, String> overrides = Map.of( + Properties.HTTP_PORT, "3500", + Properties.GRPC_PORT, "50001" + ); + + try (DaprPreviewClient client = new DaprClientBuilder().withPropertyOverrides(overrides).buildPreviewClient()) { + System.out.println("Sending the following input to LLM: Hello How are you? This is the my number 672-123-4567"); + + // Create user message with content + UserMessage userMessage = new UserMessage(List.of(new ConversationMessageContent("Hello How are you? " + + "This is the my number 672-123-4567"))); + + // Create conversation input with the user message + ConversationInputAlpha2 daprConversationInput = new ConversationInputAlpha2(List.of(userMessage)); + + // Component name is the name provided in the metadata block of the conversation.yaml file. + Mono responseMono = client.converseAlpha2(new ConversationRequestAlpha2("echo", + List.of(daprConversationInput)) + .setContextId("contextId") + .setScrubPii(true) + .setTemperature(1.1d)); + + ConversationResponseAlpha2 response = responseMono.block(); + + // Extract and print the conversation result + if (response != null && response.getOutputs() != null && !response.getOutputs().isEmpty()) { + ConversationResultAlpha2 result = response.getOutputs().get(0); + if (result.getChoices() != null && !result.getChoices().isEmpty()) { + ConversationResultChoices choice = result.getChoices().get(0); + if (choice.getMessage() != null && choice.getMessage().getContent() != null) { + System.out.printf("Conversation output: %s", choice.getMessage().getContent()); + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } +}