- 
                Notifications
    You must be signed in to change notification settings 
- Fork 224
Add Conversation AI to Java SDK #1235
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
          
     Merged
      
      
            cicoyle
  merged 27 commits into
  dapr:master
from
siri-varma:users/svegiraju/conversation-api-2
  
      
      
   
  May 1, 2025 
      
    
  
     Merged
                    Changes from all commits
      Commits
    
    
            Show all changes
          
          
            27 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      5421ac1
              
                Conversation first commit
              
              
                siri-varma 61aa209
              
                Add unit tests
              
              
                siri-varma 93c13d4
              
                change ai to conv
              
              
                siri-varma cd87ca5
              
                Move to single module
              
              
                siri-varma 00a0280
              
                Remove module
              
              
                siri-varma 90a68ea
              
                Add Integration tests
              
              
                siri-varma fcb3177
              
                Update sdk-tests/src/test/java/io/dapr/it/testcontainers/DaprConversa…
              
              
                siri-varma 9bb922e
              
                Fix things
              
              
                siri-varma 1d6f7c7
              
                Address comments
              
              
                siri-varma f646a26
              
                Import tag
              
              
                siri-varma 6498cd1
              
                Address comments
              
              
                siri-varma e29c06b
              
                Make common config
              
              
                siri-varma 38e3f82
              
                Address comments
              
              
                siri-varma 9e23ce1
              
                fix constant
              
              
                siri-varma 3b6b0a5
              
                fix constant
              
              
                siri-varma b795391
              
                Merge branch 'master' into users/svegiraju/conversation-api-2
              
              
                siri-varma c0c3f63
              
                fix constant
              
              
                siri-varma 6f54ac2
              
                Merge branch 'users/svegiraju/conversation-api-2' of https://github.c…
              
              
                siri-varma 6e303fa
              
                fix s
              
              
                siri-varma 655ef70
              
                Fix things
              
              
                siri-varma bff8932
              
                Fix things
              
              
                siri-varma 6a1e09a
              
                Fix things
              
              
                siri-varma e618070
              
                Make common config
              
              
                siri-varma eb77e88
              
                Merge branch 'master' into users/svegiraju/conversation-api-2
              
              
                siri-varma f994c8a
              
                Update README.md
              
              
                siri-varma ce7067a
              
                Update README.md
              
              
                siri-varma af02465
              
                Merge branch 'master' into users/svegiraju/conversation-api-2
              
              
                cicoyle File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| apiVersion: dapr.io/v1alpha1 | ||
| kind: Component | ||
| metadata: | ||
| name: echo | ||
| spec: | ||
| type: conversation.echo | ||
| version: v1 | 
        
          
  
    
      
          
            49 changes: 49 additions & 0 deletions
          
          49 
        
  examples/src/main/java/io/dapr/examples/conversation/DemoConversationAI.java
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* | ||
| * 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<ConversationResponse> responseMono = client.converse(new ConversationRequest("echo", | ||
|         
                  siri-varma marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| 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); | ||
| } | ||
| } | ||
| } | ||
        
          
  
    
      
          
            114 changes: 114 additions & 0 deletions
          
          114 
        
  examples/src/main/java/io/dapr/examples/conversation/README.md
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| ## Manage Dapr via the Conversation API | ||
|  | ||
| This example provides the different capabilities provided by Dapr Java SDK for Conversation. For further information about Conversation APIs please refer to [this link](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) | ||
|  | ||
| ### Using the Conversation API | ||
|  | ||
| The Java SDK exposes several methods for this - | ||
| * `client.converse(...)` for conversing with an LLM through Dapr. | ||
|  | ||
| ## Pre-requisites | ||
|  | ||
| * [Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/). | ||
| * Java JDK 11 (or greater): | ||
| * [Microsoft JDK 11](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-11) | ||
| * [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11) | ||
| * [OpenJDK 11](https://jdk.java.net/11/) | ||
| * [Apache Maven](https://maven.apache.org/install.html) version 3.x. | ||
|  | ||
| ### Checking out the code | ||
|  | ||
| Clone this repository: | ||
|  | ||
| ```sh | ||
| git clone https://github.com/dapr/java-sdk.git | ||
| cd java-sdk | ||
| ``` | ||
|  | ||
| Then build the Maven project: | ||
|  | ||
| ```sh | ||
| # make sure you are in the `java-sdk` directory | ||
| mvn install | ||
| ``` | ||
|  | ||
| Then get into the examples directory: | ||
|  | ||
| ```sh | ||
| cd examples | ||
| ``` | ||
|  | ||
| ### Initialize Dapr | ||
|  | ||
| Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initialized. | ||
|  | ||
| ### 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. | ||
| 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 { | ||
| /** | ||
| * 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<ConversationResponse> 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.getConversationOutpus().get(0).getResult()); | ||
| } catch (Exception e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|  | ||
| Use the following command to run this example- | ||
|  | ||
| <!-- STEP | ||
| name: Run Demo Conversation Client example | ||
| expected_stdout_lines: | ||
| - "== APP == Conversation output: Hello How are you? This is the my number <ISBN>" | ||
| background: true | ||
| output_match_mode: substring | ||
| sleep: 10 | ||
| --> | ||
|  | ||
| ```bash | ||
| dapr run --resources-path ./components/conversation --app-id myapp --app-port 8080 --dapr-http-port 3500 --dapr-grpc-port 51439 --log-level debug -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.conversation.DemoConversationAI | ||
| ``` | ||
|  | ||
| <!-- END_STEP --> | ||
|  | ||
| ### Sample output | ||
| ``` | ||
| == APP == Conversation output: Hello How are you? This is the my number <ISBN> | ||
| ``` | ||
| ### Cleanup | ||
|  | ||
| To stop the app, run (or press CTRL+C): | ||
|  | ||
| <!-- STEP | ||
|  | ||
| name: Cleanup | ||
| --> | ||
|  | ||
| ```bash | ||
| dapr stop --app-id myapp | ||
| ``` | ||
|  | ||
| <!-- END_STEP --> | ||
|  | 
        
          
  
    
      
          
            133 changes: 133 additions & 0 deletions
          
          133 
        
  sdk-tests/src/test/java/io/dapr/it/testcontainers/DaprConversationIT.java
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| /* | ||
| * 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.it.testcontainers; | ||
|  | ||
| import io.dapr.client.DaprPreviewClient; | ||
| import io.dapr.client.domain.ConversationInput; | ||
| import io.dapr.client.domain.ConversationRequest; | ||
| import io.dapr.client.domain.ConversationResponse; | ||
| import io.dapr.testcontainers.Component; | ||
| import io.dapr.testcontainers.DaprContainer; | ||
| import io.dapr.testcontainers.DaprLogLevel; | ||
| import org.junit.jupiter.api.Assertions; | ||
| import org.junit.jupiter.api.BeforeEach; | ||
| import org.junit.jupiter.api.Tag; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.boot.test.context.SpringBootTest; | ||
| import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; | ||
| import org.springframework.test.context.DynamicPropertyRegistry; | ||
| import org.springframework.test.context.DynamicPropertySource; | ||
| import org.testcontainers.containers.Network; | ||
| import org.testcontainers.junit.jupiter.Container; | ||
| import org.testcontainers.junit.jupiter.Testcontainers; | ||
|  | ||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Random; | ||
|  | ||
| import static io.dapr.it.testcontainers.ContainerConstants.DAPR_RUNTIME_IMAGE_TAG; | ||
|  | ||
| @SpringBootTest( | ||
| webEnvironment = WebEnvironment.RANDOM_PORT, | ||
| classes = { | ||
| DaprPreviewClientConfiguration.class, | ||
| TestConversationApplication.class | ||
| } | ||
| ) | ||
| @Testcontainers | ||
| @Tag("testcontainers") | ||
| public class DaprConversationIT { | ||
|  | ||
| private static final Network DAPR_NETWORK = Network.newNetwork(); | ||
| private static final Random RANDOM = new Random(); | ||
| private static final int PORT = RANDOM.nextInt(1000) + 8000; | ||
|  | ||
| @Container | ||
| private static final DaprContainer DAPR_CONTAINER = new DaprContainer(DAPR_RUNTIME_IMAGE_TAG) | ||
| .withAppName("conversation-dapr-app") | ||
| .withComponent(new Component("echo", "conversation.echo", "v1", new HashMap<>())) | ||
| .withNetwork(DAPR_NETWORK) | ||
| .withDaprLogLevel(DaprLogLevel.DEBUG) | ||
| .withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String())) | ||
| .withAppChannelAddress("host.testcontainers.internal") | ||
| .withAppPort(PORT); | ||
|  | ||
| /** | ||
| * Expose the Dapr port to the host. | ||
| * | ||
| * @param registry the dynamic property registry | ||
| */ | ||
| @DynamicPropertySource | ||
| static void daprProperties(DynamicPropertyRegistry registry) { | ||
| registry.add("dapr.http.endpoint", DAPR_CONTAINER::getHttpEndpoint); | ||
| registry.add("dapr.grpc.endpoint", DAPR_CONTAINER::getGrpcEndpoint); | ||
| registry.add("server.port", () -> PORT); | ||
| } | ||
|  | ||
| @Autowired | ||
| private DaprPreviewClient daprPreviewClient; | ||
|  | ||
| @BeforeEach | ||
| public void setUp(){ | ||
| org.testcontainers.Testcontainers.exposeHostPorts(PORT); | ||
| } | ||
|  | ||
| @Test | ||
| public void testConversationSDKShouldHaveSameOutputAndInput() { | ||
| ConversationInput conversationInput = new ConversationInput("input this"); | ||
| List<ConversationInput> conversationInputList = new ArrayList<>(); | ||
| conversationInputList.add(conversationInput); | ||
|  | ||
| ConversationResponse response = | ||
| this.daprPreviewClient.converse(new ConversationRequest("echo", conversationInputList)).block(); | ||
|  | ||
| Assertions.assertEquals("", response.getContextId()); | ||
| Assertions.assertEquals("input this", response.getConversationOutputs().get(0).getResult()); | ||
| } | ||
|  | ||
| @Test | ||
| public void testConversationSDKShouldScrubPIIWhenScrubPIIIsSetInRequestBody() { | ||
| List<ConversationInput> conversationInputList = new ArrayList<>(); | ||
| conversationInputList.add(new ConversationInput("input this abcd@gmail.com")); | ||
| conversationInputList.add(new ConversationInput("input this +12341567890")); | ||
|  | ||
| ConversationResponse response = | ||
| this.daprPreviewClient.converse(new ConversationRequest("echo", conversationInputList) | ||
| .setScrubPii(true)).block(); | ||
|  | ||
| Assertions.assertEquals("", response.getContextId()); | ||
| Assertions.assertEquals("input this <EMAIL_ADDRESS>", | ||
| response.getConversationOutputs().get(0).getResult()); | ||
| Assertions.assertEquals("input this <PHONE_NUMBER>", | ||
| response.getConversationOutputs().get(1).getResult()); | ||
| } | ||
|  | ||
| @Test | ||
| public void testConversationSDKShouldScrubPIIOnlyForTheInputWhereScrubPIIIsSet() { | ||
| List<ConversationInput> conversationInputList = new ArrayList<>(); | ||
| conversationInputList.add(new ConversationInput("input this abcd@gmail.com")); | ||
| conversationInputList.add(new ConversationInput("input this +12341567890").setScrubPii(true)); | ||
|  | ||
| ConversationResponse response = | ||
| this.daprPreviewClient.converse(new ConversationRequest("echo", conversationInputList)).block(); | ||
|  | ||
| Assertions.assertEquals("", response.getContextId()); | ||
| Assertions.assertEquals("input this abcd@gmail.com", | ||
| response.getConversationOutputs().get(0).getResult()); | ||
| Assertions.assertEquals("input this <PHONE_NUMBER>", | ||
| response.getConversationOutputs().get(1).getResult()); | ||
| } | ||
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              
        
          
  
    
      
          
            25 changes: 25 additions & 0 deletions
          
          25 
        
  sdk-tests/src/test/java/io/dapr/it/testcontainers/TestConversationApplication.java
  
  
      
      
   
        
      
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| /* | ||
| * Copyright 2024 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.it.testcontainers; | ||
|  | ||
| import org.springframework.boot.SpringApplication; | ||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|  | ||
| @SpringBootApplication | ||
| public class TestConversationApplication { | ||
|  | ||
| public static void main(String[] args) { | ||
| SpringApplication.run(TestConversationApplication.class, args); | ||
| } | ||
| } | 
      
      Oops, something went wrong.
        
    
  
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.