How to: Using Microsoft's AI extensions with Dapr's .NET Conversation SDK

Learn how to create and use Dapr with Microsoft’s AI extensions

Prerequisites

Installation

To get started with this SDK, install both the Dapr.AI and Dapr.AI.Microsoft.Extensions packages from NuGet:

dotnet add package Dapr.AI
dotnet add package Dapr.AI.Microsoft.Extensions

The DaprChatClient is a Dapr-based implementation of the IChatClient interface provided in the Microsoft.Extensions.AI.Abstractions package using Dapr’s [conversation building block]({{ ref conversation-overview.md }}). It allows developers to build against the types provided by Microsoft’s abstraction while providing the greatest conformity to the Dapr conversation building block available. As both approaches adopt OpenAI’s API approach, these are expected to increasingly converge over time.

About Microsoft.Extensions.AI

The Dapr.AI.Microsoft.Extensions package implements the Microsoft.Extensions.AI abstractions, providing a unified API for AI services in .NET applications. Microsoft.Extensions.AI is designed to offer a consistent programming model across different AI providers and scenarios. For detailed information about Microsoft.Extensions.AI, refer to the official documentation.

Service Registration

The DaprChatClient can be registered with the dependency injection container using several extension methods. First, ensure that you reigster the DaprConversationClient that’s part of the Dapr.AI package from NuGet:

services.AddDaprConversationClient();

Then register the DaprChatClient with your conversation component name:

services.AddDaprChatClient("my-conversation-component");

Configuration Options

You can confiugre the DaprChatClient using the DaprChatClientOptions though the current implementation only provides configuration for the component name itself. This is expected to change in future releases.

services.AddDaprChatClient("my-conversation-component", options => 
{
   // Configure additional options here 
});

You can also configure the service lifetime (this defaults to ServiceLifetime.Scoped):

services.AddDaprChatClient("my-conversation-component", ServiceLifetime.Singleton);

Usage

Once registered, you can inject and use IChatClient in your services:

public class ChatService(IChatClient chatClient)
{
    public async Task<IReadOnlyList<string>> GetResponseAsync(string message)
    {
        var response = await chatClient.GetResponseAsync([
            new ChatMessage(ChatRole.User,
                "Please write me a poem in iambic pentameter about the joys of using Dapr to develop distributed applications with .NET")
            ]);
        
        return response.Messages.Select(msg => msg.Text).ToList();
    }
}

Streaming Conversations

The DaprChatClient does not yet support streaming responses and use of the corresponding GetStreamingResponseAsync methods will throw a NotImplemenetedException. This is expected to change in a future release once the Dapr runtime supports this functionality.

Tool Integration

The client supports function calling through the Microsoft.Extensions.AI tool integration. Tools registered with the conversation will be automatically available to the large language model.

string GetCurrentWeather() => Random.Shared.NextDouble() > 0.5 ? "It's sunny today!" : "It's raining today!";
var toolChatOptions = new ChatOptions { Tools = [AIFunctionFactory.Create(GetCurrentWeather, "weather")] };
var toolResponse = await chatClient.GetResponseAsync("What's the weather like today?", toolChatOptions);
foreach (var toolResp in toolResponse.Messages)
{
    Console.WriteLine(toolResp);
}

Error Handling

The DaprChatClient integrates with Dapr’s error handling and will throw appropriate exceptions when issues occur.

Configuration and Metadata

The underlying Dapr conversation component can be configured with metadata and parameters through the Dapr conversation building block configuration. The DaprChatClient will respect these settings when making calls to the conversation component.

Best Practices

  1. Service Lifetime: Use ServiceLifetime.Scoped or ServiceLifetime.Singleton for the DaprChatClient registration to avoid creating multiple instances unnecessarily.

  2. Error Handling: Always wrap calls in appropriate try-catch blocks to handle both Dapr-specific and general exceptions.

  3. Resource Management: The DaprChatClient properly implements IDisposable through its base classes, so resources are automatically managed when using dependency injection.

  4. Configuration: Configure your Dapr conversation component properly to ensure optimal performance and reliability.