Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 41 additions & 16 deletions conversation/java/sdk/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Dapr Conversation API (Java SDK)

In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers. This example demonstrates both simple conversation and tool calling capabilities.

Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.

This quickstart includes one app:

- Conversation, responsible for sending an input to the underlying LLM and retrieving an output.
- Conversation, responsible for sending an input to the underlying LLM and retrieving an output, including tool call support.

## Run the app with the template file

Expand Down Expand Up @@ -35,8 +35,16 @@ cd ..
<!-- STEP
name: Run multi app run template
expected_stdout_lines:
- '== APP - conversation == Input: What is Dapr?'
- '== APP - conversation == Output response: What is Dapr?'
- '== APP - conversation == === Simple Conversation ==='
- '== APP - conversation == Conversation input sent: What is dapr?'
- '== APP - conversation == Output response: What is dapr?'
- '== APP - conversation == === Tool Calling ==='
- '== APP - conversation == Tool calling input sent: What is the weather like in San Francisco in celsius?'
- '== APP - conversation == Output message: What is the weather like in San Francisco in celsius?'
- '== APP - conversation == Tool calls detected:'
- '== APP - conversation == Tool call: {"id": "0", "function": {"name": "get_weather", "arguments": location,unit}}'
- '== APP - conversation == Function name: get_weather'
- '== APP - conversation == Function arguments: location,unit'
expected_stderr_lines:
output_match_mode: substring
match_order: none
Expand All @@ -51,12 +59,23 @@ dapr run -f .

The terminal console output should look similar to this, where:

- The app sends an input `What is Dapr?` to the `echo` Component mock LLM.
- The mock LLM echoes `What is Dapr?`.
- The app sends a simple conversation input `What is dapr?` to the `echo` Component mock LLM.
- The mock LLM echoes back the response.
- The app then demonstrates tool calling by sending `What is the weather like in San Francisco in celsius?`.
- The response includes detected tool calls with function name and arguments.

```text
== APP - conversation == Input: What is Dapr?
== APP - conversation == Output response: What is Dapr?
== APP - conversation == === Simple Conversation ===
== APP - conversation == Conversation input sent: What is dapr?
== APP - conversation == Output response: What is dapr?

== APP - conversation == === Tool Calling ===
== APP - conversation == Tool calling input sent: What is the weather like in San Francisco in celsius?
== APP - conversation == Output message: What is the weather like in San Francisco in celsius?
== APP - conversation == Tool calls detected:
== APP - conversation == Tool call: {"id": "0", "function": {"name": "get_weather", "arguments": location,unit}}
== APP - conversation == Function name: get_weather
== APP - conversation == Function arguments: location,unit
```

<!-- END_STEP -->
Expand All @@ -80,21 +99,27 @@ dapr stop -f .
```bash
cd ./conversation
mvn clean install
java -jar ConversationAIService-0.0.1-SNAPSHOT.jar com.service.Conversation
java -jar target/ConversationAIService-0.0.1-SNAPSHOT.jar com.service.Conversation
```

2. Run the Dapr process alongside the application.
2. Run the Dapr process alongside the application

```bash
dapr run --app-id conversation --resources-path ../../../components/
```

The terminal console output should look similar to below, where:

- The app sends an input `What is Dapr?` to the `echo` Component mock LLM.
- The mock LLM echoes `What is Dapr?`.
The terminal console output should look similar to this:

```text
== APP - conversation == Input: What is Dapr?
== APP - conversation == Output response: What is Dapr?
=== Simple Conversation ===
Conversation input sent: What is dapr?
Output response: What is dapr?

=== Tool Calling ===
Tool calling input sent: What is the weather like in San Francisco in celsius?
Output message: What is the weather like in San Francisco in celsius?
Tool calls detected:
Tool call: {"id": "0", "function": {"name": "get_weather", "arguments": location,unit}}
Function name: get_weather
Function arguments: location,unit
```
4 changes: 2 additions & 2 deletions conversation/java/sdk/conversation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<dependency>
<groupId>io.dapr</groupId>
<artifactId>dapr-sdk</artifactId>
<version>1.16.0</version>
<version>1.16.1-rc-2</version>
</dependency>
</dependencies>

Expand All @@ -23,7 +23,7 @@
<dependency>
<groupId>io.dapr</groupId>
<artifactId>dapr-sdk</artifactId>
<version>1.16.0</version>
<version>1.16.1-rc-2</version>
</dependency>
</dependencies>
</dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,117 @@
package com.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

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;
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.ConversationResultMessage;
import io.dapr.client.domain.ConversationToolCalls;
import io.dapr.client.domain.ConversationTools;
import io.dapr.client.domain.ConversationToolsFunction;
import io.dapr.client.domain.UserMessage;

public class Conversation {

public static void main(String[] args) {
String prompt = "What is Dapr?";
private static final String CONVERSATION_COMPONENT_NAME = "echo";
private static final String CONVERSATION_TEXT = "What is dapr?";
private static final String TOOL_CALL_INPUT = "What is the weather like in San Francisco in celsius?";

public static void main(String[] args) {
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
System.out.println("Input: " + prompt);

ConversationInput daprConversationInput = new ConversationInput(prompt);
// Define tool function parameters schema
Map<String, Object> locationProperty = new HashMap<>();
locationProperty.put("type", "string");
locationProperty.put("description", "The city and state, e.g. San Francisco, CA");

Map<String, Object> unitProperty = new HashMap<>();
unitProperty.put("type", "string");
unitProperty.put("enum", List.of("celsius", "fahrenheit"));
unitProperty.put("description", "The temperature unit to use");

Map<String, Object> properties = new HashMap<>();
properties.put("location", locationProperty);
properties.put("unit", unitProperty);

Map<String, Object> parameters = new HashMap<>();
parameters.put("type", "object");
parameters.put("properties", properties);
parameters.put("required", List.of("location"));

// Create the tool function
ConversationToolsFunction getWeatherFunction = new ConversationToolsFunction("get_weather", parameters)
.setDescription("Get the current weather for a location");
ConversationTools weatherTool = new ConversationTools(getWeatherFunction);

// ==========================================
// Simple Conversation
// ==========================================
System.out.println("=== Simple Conversation ===");

UserMessage conversationMessage = new UserMessage(
List.of(new ConversationMessageContent(CONVERSATION_TEXT)))
.setName("TestUser");
ConversationInputAlpha2 conversationInput = new ConversationInputAlpha2(List.of(conversationMessage));

ConversationResponseAlpha2 conversationResponse = client.converseAlpha2(
new ConversationRequestAlpha2(CONVERSATION_COMPONENT_NAME, List.of(conversationInput))
.setScrubPii(false)
.setToolChoice("auto")
.setTemperature(0.7)
.setTools(List.of(weatherTool))).block();

System.out.println("Conversation input sent: " + CONVERSATION_TEXT);
String outputContent = conversationResponse.getOutputs().get(0)
.getChoices().get(0).getMessage().getContent();
System.out.println("Output response: " + outputContent);

// ==========================================
// Tool Calling
// ==========================================
System.out.println("\n=== Tool Calling ===");

UserMessage toolCallMessage = new UserMessage(
List.of(new ConversationMessageContent(TOOL_CALL_INPUT)))
.setName("TestUser");
ConversationInputAlpha2 toolCallInput = new ConversationInputAlpha2(List.of(toolCallMessage));

ConversationResponseAlpha2 toolCallResponse = client.converseAlpha2(
new ConversationRequestAlpha2(CONVERSATION_COMPONENT_NAME, List.of(toolCallInput))
.setScrubPii(false)
.setToolChoice("auto")
.setTemperature(0.7)
.setTools(List.of(weatherTool))).block();

System.out.println("Tool calling input sent: " + TOOL_CALL_INPUT);

ConversationResultAlpha2 result = toolCallResponse.getOutputs().get(0);
ConversationResultChoices choice = result.getChoices().get(0);
ConversationResultMessage message = choice.getMessage();

System.out.println("Output message: " + message.getContent());

if (message.hasToolCalls()) {
System.out.println("Tool calls detected:");
for (ConversationToolCalls toolCall : message.getToolCalls()) {
String functionName = toolCall.getFunction().getName();
String functionArguments = toolCall.getFunction().getArguments();

System.out.println("Tool call: {\"id\": \"" + toolCall.getId()
+ "\", \"function\": {\"name\": \"" + functionName
+ "\", \"arguments\": " + functionArguments + "}}");
System.out.println("Function name: " + functionName);
System.out.println("Function arguments: " + functionArguments);
}
}

// 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("Output response: %s", response.getConversationOutputs().get(0).getResult());
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down
Loading