Thursday, November 14, 2024
HomeC#AI-Pushed Sensible Looking utilizing .NET MAUI ComboBox

AI-Pushed Sensible Looking utilizing .NET MAUI ComboBox


TL;DR: Discover ways to combine good AI-based looking out into the .NET MAUI ComboBox utilizing customized filters and Semantic Kernel. The tutorial walks you thru making a customized filtering logic to deal with spelling errors or incomplete inputs, making certain extra correct search outcomes. Moreover, it covers integrating Semantic Kernel for superior AI-powered filtering, enhancing the person expertise in data-driven functions.

Introduction

The .NET MAUI ComboBox management is a flexible choice element that lets customers kind a price or choose an possibility from a predefined checklist. It’s designed to show options from giant datasets primarily based on person enter effectively.

On this weblog, we’ll display find out how to implement good AI-powered looking out, permitting the ComboBox to return correct outcomes, even when there are not any actual matches, by integrating the .NET MAUI ComboBox with Semantic Kernel.

Implementing the Sensible AI Looking

To implement good AI looking out, we’ll use the customized filtering characteristic of the .NET MAUI ComboBox management. We’ll first stroll you thru implementing customized filtering after which combine AI-driven search. For this demonstration, we use Semantic Kernel, a superb instrument for incorporating AI into .NET functions.

Customized filtering

The .NET MAUI ComboBox management means that you can apply customized filter logic to recommend objects that meet particular standards, leveraging the FilterBehavior property.

Step 1: Creating the Enterprise Mannequin for Meals Search

First, create a easy enterprise mannequin for meals search. Under is an instance of find out how to outline it:

// Mannequin.cs
public class FoodModel
{
    public string? Identify { get; set; }
}

Subsequent, create the ViewModel, which accommodates a set of meals objects.

// ViewModel.cs
public class FoodViewModel : INotifyPropertyChanged
{
    personal ObservableCollection meals;

    public ObservableCollection Meals
    {
        get { return meals; }
        set { meals = worth; OnPropertyChanged(nameof(Meals)); }
    }

    public FoodViewModel()
    {
        meals = new ObservableCollection
        {
            new FoodModel { Identify = "Acai Bowl" },
            new FoodModel { Identify = "Aloo Gobi" },
            new FoodModel { Identify = "Arepas" },
            new FoodModel { Identify = "Baba Ganoush" },
            // Extra meals objects...
        };
    }

    public occasion PropertyChangedEventHandler? PropertyChanged;

    protected digital void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Step 2: Making a Customized Filter Class

Now, create a category that implements the IComboBoxFilterBehavior interface. This class will outline customized filtering logic.

public class ComboBoxCustomFilter: IComboBoxFilterBehavior
{

}

Step 3: Implementing the GetMatchingIndexes Technique

Subsequent, implement the GetMatchingIndexes methodology from the IComboBoxFilterBehavior interface to create a suggestion checklist. This checklist will embody the filtered objects primarily based in your customized logic and might be displayed within the drop-down of the .NET MAUI ComboBox management. This methodology takes the next arguments:

  • supply: This argument refers back to the ComboBox that owns the filter conduct. It offers entry to properties like ItemsSource and different related information.
  • filterInfo: This argument accommodates the textual content entered by the person within the ComboBox. You should use this enter to generate a filtered suggestion checklist that can seem within the drop-down.

Under is an instance of filtering and displaying an inventory of meals within the ComboBox. The checklist exhibits solely the meals objects that begin with the textual content entered by the person:

public class ComboBoxCustomFilter : IComboBoxFilterBehavior
{
    public async Activity<object?> GetMatchingIndexes(SfComboBox supply, ComboBoxFilterInfo filterInfo)
    {
        IEnumerable? itemssource = supply.ItemsSource as IEnumerable;
        var filteredItems = from FoodModel merchandise in itemssource
                            the place merchandise.Identify.StartsWith(filterInfo.Textual content, StringComparison.CurrentCultureIgnoreCase)
                            choose merchandise;

        return await Activity.FromResult(filteredItems);
    }
}</object?>

Step 4: Making use of Customized Filtering to ComboBox

Lastly, bind the customized filter to the ComboBox management utilizing the FilterBehavior property.

<ContentPage.BindingContext>
    <native:FoodViewModel />
</ContentPage.BindingContext>
<VerticalStackLayout>
<syncfusion:SfTextInputLayout Trace="Select Meals Merchandise"
                              ContainerType="Outlined"
                              WidthRequest="248"
                              ContainerBackground="Clear">
    <editors:SfComboBox x:Identify="combobox" 
                        DropDownPlacement="Backside"
                        MaxDropDownHeight="200"
                        IsEditable="True"
                        TextSearchMode="StartsWith"
                        IsFilteringEnabled="True"
                        DisplayMemberPath="Identify"
                        TextMemberPath="Identify"
                        ItemsSource="{Binding Meals}">
        <editors:SfComboBox.FilterBehavior>
            <native:ComboBoxCustomFilter/>
        </editors:SfComboBox.FilterBehavior>
    </editors:SfComboBox>
</syncfusion:SfTextInputLayout>
</VerticalStackLayout>

The next picture demonstrates the output of the above customized filtering pattern..NET MAUI ComboBox with custom filtering

Integrating Semantic Kernel along with your .NET MAUI app

Semantic Kernel is an open-source software program improvement equipment (SDK) created by Microsoft, designed to assist builders construct clever functions powered by giant language fashions (LLMs). This SDK simplifies the mixing of LLMs like OpenAI, Azure OpenAI, Google, and Hugging Face Transformers into conventional programming environments.

On this instance, we’ll deal with utilizing Azure OpenAI, however you may select any chat completion service. In the event you’re choosing Azure OpenAI, guarantee you’ve entry and arrange a deployment by way of the Azure portal. For directions, discuss with the Create and Deploy Azure OpenAI Service Information.

On this weblog, we’re utilizing the Semantic Kernel NuGet bundle, accessible within the NuGet Gallery. Earlier than beginning, set up this bundle in your .NET MAUI software to proceed with the mixing.

Organising Semantic Kernel

Now, let’s start creating the Semantic Kernel and Chat completion.

Step 1: Putting in Semantic Kernel

Start by putting in the Semantic Kernel NuGet bundle in your .NET MAUI software.

Step 2: Set up the Needed NuGet Packages

Then, set up the required NuGet packages and embody the suitable namespaces outlined on this getting began documentation.

Set up-Bundle Microsoft.SemanticKernel

Step 3: Setting Up Semantic Kernel

On this setup, we’ll make the most of Azure OpenAI with the GPT-35 mannequin, particularly deployed beneath the identify GPT35Turbo. To ascertain a profitable connection to the service, change the endpoint, deployment identify, and key along with your particular particulars.

Step 4: Chat Completion and Filtering

Now, you may make the most of the Chat completion characteristic to outline the chat historical past. The ChatHistory contains messages from the system, person, and assistant. In our software, we’ve got used the next messages as enter:

  • System Message: Act as a filtering assistant.
  • Person Message: Filter the checklist objects primarily based on the person enter utilizing characters beginning with phonetic algorithms like Soundex or Damerau-Levenshtein Distance. ” +r$” The filter ought to ignore spelling errors and be case insensitive.

Step 5: Using Chat Completion

Subsequent, make the most of the chat completion characteristic to acquire completion outcomes utilizing the GetChatMessageContentAsync methodology. We have now beforehand outlined the ChatHistory format for the AI response, permitting us to obtain the correctly formatted response message.

Under is the entire code for the ComboBoxAzureAIService class. Observe that I’ve commented out the Google Gemini codes. In the event you want to use them, merely uncomment the GetGoogleGeminiAIKernel methodology.

public class ComboBoxAzureAIService
{
    personal const string endpoint = "https://YOUR_ACCOUNT.openai.azure.com/";
    personal const string deploymentName = "GPT35Turbo";
    personal const string key = "";
    personal IChatCompletionService? _chatCompletion;
    personal Kernel? _kernel;
    personal ChatHistory? _chatHistory;
    inside bool IsCredentialValid = false;
    personal Uri? _uriResult;

    public ComboBoxAzureAIService()
    {
        ValidateCredential();
    }

    personal async void ValidateCredential()
    {
        #area Azure OpenAI
        // Use beneath methodology for Azure Open AI
        this.GetAzureOpenAIKernel();
        #endregion

        #area Google Gemini
        // Use beneath methodology for Google Gemini
        // this.GetGoogleGeminiAIKernel();
        #endregion

        bool isValidUri = Uri.TryCreate(endpoint, UriKind.Absolute, out _uriResult)
            && (_uriResult.Scheme == Uri.UriSchemeHttp || _uriResult.Scheme == Uri.UriSchemeHttps);

        if (!isValidUri || !endpoint.Comprises("http") || string.IsNullOrEmpty(key) 
            || key.Comprises("API key") || string.IsNullOrEmpty(deploymentName) 
            || deploymentName.Comprises("deployment identify"))
        {
            ShowAlertAsync();
            return;
        }

        attempt
        {
            if (_chatHistory != null && _chatCompletion != null)
            {
                // Take a look at the semantic kernel with message
                _chatHistory.AddSystemMessage("Whats up, Take a look at Examine");
                await _chatCompletion.GetChatMessageContentAsync(chatHistory: _chatHistory, kernel: _kernel);
            }
        }
        catch (Exception)
        {
            // Deal with any exceptions that point out the credentials or endpoint are invalid.               
            ShowAlertAsync();
            return;
        }

        IsCredentialValid = true;
    }

    #area Azure OpenAI
    personal void GetAzureOpenAIKernel()
    {
        // Create the chat historical past
        _chatHistory = new ChatHistory();
        
        attempt
        {
            var builder = Kernel.CreateBuilder()
                .AddAzureOpenAIChatCompletion(deploymentName, endpoint, key);

            // Get the kernel from construct
            _kernel = builder.Construct();

            // Get the chat completion from kernel
            _chatCompletion = _kernel.GetRequiredService();
        }
        catch (Exception)
        {
            return;
        }
    }
    #endregion

    #area Google Gemini
    personal void GetGoogleGeminiAIKernel()
    {
        // Add bundle Microsoft.SemanticKernel.Connectors.Google

        // _chatHistory = new ChatHistory();
        // IKernelBuilder _kernelBuilder = Kernel.CreateBuilder();
        // _kernelBuilder.AddGoogleAIGeminiChatCompletion(modelId: "NAME_OF_MODEL", apiKey: key);
        // Kernel _kernel = _kernelBuilder.Construct();
        // _chatCompletion = _kernel.GetRequiredService();
    }
    #endregion

    personal async void ShowAlertAsync()
    {
        if (Utility.Present?.MainPage != null && !IsCredentialValid)
        {
            await Utility.Present.MainPage.DisplayAlert("Alert", 
                "The Azure API key or endpoint is lacking or incorrect. Please confirm your credentials. " +
                "You may also proceed with the offline information.", "OK");
        }
    }

    public async Activity GetCompletion(string immediate, CancellationToken cancellationToken)
    {
        if (_chatHistory != null && _chatCompletion != null)
        {
            if (_chatHistory.Rely > 5)
            {
                _chatHistory.RemoveRange(0, 2); // Take away the message historical past to keep away from exceeding the token restrict
            }

            _chatHistory.AddUserMessage(immediate);

            attempt
            {
                cancellationToken.ThrowIfCancellationRequested();
                var chatResponse = await _chatCompletion.GetChatMessageContentAsync(chatHistory: _chatHistory, kernel: _kernel);
                cancellationToken.ThrowIfCancellationRequested();
                _chatHistory.AddAssistantMessage(chatResponse.ToString());
                return chatResponse.ToString();
            }
            catch (RequestFailedException ex)
            {
                Debug.WriteLine($"Request failed: {ex.Message}");
                throw;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"An error occurred: {ex.Message}");
                throw;
            }
        }

        return "";
    }
}

Connecting to Semantic Kernel

Our .NET MAUI software can connect with the Semantic Kernel chat completion service by means of a customized filtering class. This practice filtering class makes use of the GetMatchingIndexes methodology, which is triggered every time enter textual content is entered into the .NET MAUI ComboBox management. By connecting to the Semantic Kernel chat completion service, we generate a immediate primarily based on the enter textual content and retrieve the response message, which is then transformed into an output assortment.

To ascertain this connection, we’ll modify the prevailing ComboBoxFilterBehavior to combine with the Semantic Kernel chat completion service. Under is the implementation of the ComboBoxCustomFilter class.

public class ComboBoxCustomFilter : IComboBoxFilterBehavior
{
    personal readonly ComboBoxAzureAIService _azureAIService;
    public ObservableCollection Gadgets { get; set; }
    public ObservableCollection FilteredItems { get; set; } = new ObservableCollection();
    personal CancellationTokenSource? _cancellationTokenSource;

    public ComboBoxCustomFilter()
    {
        _azureAIService = new ComboBoxAzureAIService();
        Gadgets = new ObservableCollection();
        _cancellationTokenSource = new CancellationTokenSource();
    }

    public async Activity<object?> GetMatchingIndexes(SfComboBox supply, ComboBoxFilterInfo filterInfo)
    {
        Gadgets = (ObservableCollection)supply.ItemsSource;

        // If credential is just not legitimate, the filtering information exhibits as empty
        if (!_azureAIService.IsCredentialValid || string.IsNullOrEmpty(filterInfo.Textual content))
        {
            _cancellationTokenSource?.Cancel();
            FilteredItems.Clear();
            return await Activity.FromResult(FilteredItems);
        }

        string listItems = string.Be a part of(", ", Gadgets!.Choose(c => c.Identify));

        // Be a part of the primary 5 objects with newline characters for demo output template for AI
        string outputTemplate = string.Be a part of("n", Gadgets.Take(5).Choose(c => c.Identify));

        // Cancel the earlier token if the person sorts repeatedly
        _cancellationTokenSource?.Cancel();
        _cancellationTokenSource = new CancellationTokenSource();
        var cancellationToken = _cancellationTokenSource.Token;

        // Passing the Person Enter, ItemsSource, Reference output, and CancellationToken
        var filteredItems = await FilterItemsUsingAzureAI(filterInfo.Textual content, listItems, outputTemplate, cancellationToken);

        return await Activity.FromResult(filteredItems);
    }

    public async Activity<observablecollection> FilterItemsUsingAzureAI(string userInput, string itemsList, string outputTemplate, CancellationToken cancellationToken)
    {
        if (!string.IsNullOrEmpty(userInput))
        {
            var immediate = $"Filter the checklist objects primarily based on the person enter utilizing character beginning with and phonetic algorithms like Soundex or Damerau-Levenshtein Distance. " +
                         $"The filter ought to ignore spelling errors and be case insensitive. " +
                         $"Return solely the filtered objects with every merchandise on a brand new line with none further content material like explanations, hyphens, numberings, and minus indicators. Ignore phrases like 'Listed below are the filtered objects.' " +
                         $"Solely return objects which are current within the Listing Gadgets. " +
                         $"Be certain that every filtered merchandise is returned in its entirety with out lacking any a part of its content material. " +
                         $"Organize the filtered objects in order that these beginning with the person enter's first letter seem on the prime, adopted by different matches. " +
                         $"The instance information is for reference; don't present it as output. Filter the objects from the checklist correctly. " +
                         $"Right here is the Person enter: {userInput}, " +
                         $"Listing of Gadgets: {itemsList}. " +
                         $"If no objects are discovered, return 'Empty'. " +
                         $"Don't embody 'Listed below are the filtered objects:' within the output. Examine this demo output template, and return output like this: {outputTemplate}.";

            var completion = await _azureAIService.GetCompletion(immediate, cancellationToken);

            var filteredItems = completion.Cut up('n')
                                          .Choose(x => x.Trim())
                                          .The place(x => !string.IsNullOrEmpty(x))
                                          .ToList();

            if (FilteredItems.Rely > 0)
                FilteredItems.Clear();

            FilteredItems.AddRange(
                Gadgets.The place(i => filteredItems.Any(merchandise => i.Identify!.StartsWith(merchandise)))
            );

            cancellationToken.ThrowIfCancellationRequested();
        }

        return FilteredItems;
    }
}</observablecollection</object?>

The picture beneath illustrates the outcomes of an AI-based search utilizing customized filters.

.NET MAUI ComboBox with AI-based serch using custom filtering

GitHub reference

For extra particulars, discuss with the Sensible AI Search GitHub demo.

Supercharge your cross-platform apps with Syncfusion’s strong .NET MAUI controls.

Attempt It Free

Conclusion

Thanks for studying! On this weblog, we explored find out how to implement a sensible AI search that delivers seamless outcomes, even when there are not any actual matches, utilizing the .NET MAUI ComboBox management. Attempt the steps shared right here and go away suggestions within the feedback part beneath!

This characteristic is on the market within the newest 2024 Quantity 3 launch. You’ll be able to take a look at all of the options in our Launch Notes and What’s New pages.

You’ll be able to obtain and take a look at our MAUI demo app from Google Play and the Microsoft Shops.

The present clients can obtain the brand new model of Important Studio on the License and Downloads web page. If you’re not a Syncfusion buyer, attempt our 30-day free trial to take a look at our unimaginable options. 

You may also contact us by means of our help discussion boardhelp portal, or suggestions portal. We’re at all times comfortable to help you!

Associated blogs

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments