ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [DX_WPF] AI Chat Control
    DevExpress/DX_WPF 2025. 12. 18. 09:03

     

    view

    <UserControl x:Class="LS.CommonUI.EngSearch.Com.Views.EngCopilotView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
                 xmlns:ViewModels="clr-namespace:LS.CommonUI.EngSearch.Com.ViewModels" 
                 xmlns:dxaichat="http://schemas.devexpress.com/winfx/2008/xaml/aichat" 
                 xmlns:chat="clr-namespace:DevExpress.AIIntegration.Blazor.Chat;assembly=DevExpress.AIIntegration.Blazor.Chat.v25.2"
                 xmlns:system="clr-namespace:System;assembly=mscorlib"
                 mc:Ignorable="d"
                 d:DesignHeight="300" d:DesignWidth="600">
        <Grid>
            <dxaichat:AIChatControl x:Name="aiChatControl"
                ContentFormat="Markdown" 
                UseStreaming="True"
                InputEnabled="True"
                FileUploadEnabled="True"
                HorizontalAlignment="Stretch" 
                VerticalAlignment="Stretch" 
                Margin="10">
    
                <dxmvvm:Interaction.Behaviors>
                    <dxmvvm:EventToCommand 
                            SourceName="aiChatControl"
                            EventName="MarkdownConvert" 
                            Command="{Binding MarkdownConvertCommand}"
                            PassEventArgsToCommand="True"/>
                    <dxmvvm:EventToCommand 
                            SourceName="aiChatControl"
                            EventName="MessageSent" 
                            Command="{Binding MessageSentCommand}"
                            PassEventArgsToCommand="True"/>
                </dxmvvm:Interaction.Behaviors>
                
                <dxaichat:AIChatControl.FileUploadSettings>
                    <chat:DxAIChatFileUploadSettings MaxFileSize="5000000" MaxFileCount="5">
                        <chat:DxAIChatFileUploadSettings.AllowedFileExtensions>
                            <system:String>.png</system:String>
                            <system:String>.pdf</system:String>
                            <system:String>.txt</system:String>
                        </chat:DxAIChatFileUploadSettings.AllowedFileExtensions>
                        <chat:DxAIChatFileUploadSettings.FileTypeFilter>
                            <system:String>image/png</system:String>
                            <system:String>application/pdf</system:String>
                            <system:String>text/plain</system:String>
                        </chat:DxAIChatFileUploadSettings.FileTypeFilter>
                    </chat:DxAIChatFileUploadSettings>
                </dxaichat:AIChatControl.FileUploadSettings>
                <dxaichat:AIChatControl.PromptSuggestions>
                    <chat:DxAIChatPromptSuggestion
                Title="Birthday Wish"
                Text="A warm and cheerful birthday greeting message."
                PromptMessage="Write a heartfelt birthday message for a close friend." />
                    <chat:DxAIChatPromptSuggestion
                Title="Thank You Note"
                Text="A polite thank you note to express gratitude."
                PromptMessage="Compose a short thank you note to a colleague who helped with a project." />
                </dxaichat:AIChatControl.PromptSuggestions>
            </dxaichat:AIChatControl>
        </Grid>
    </UserControl>

     

     

    viewModel

    using Azure.AI.OpenAI;
    using DevExpress.AIIntegration;
    using DevExpress.AIIntegration.Blazor.Chat.WebView;
    using DevExpress.Data.Utils;
    using DevExpress.Mvvm;
    using LS.CommonUI.EngSearch.Com.Models;
    using Microsoft.AspNetCore.Components;
    using Microsoft.Extensions.AI;
    using Microsoft.Extensions.Logging;
    using ModelContextProtocol.Client;
    using OpenAI.Chat;
    using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
    using ChatMessage = Microsoft.Extensions.AI.ChatMessage;
    
    namespace LS.CommonUI.EngSearch.Com.ViewModels;
    
    public class EngCopilotViewModel : ViewModelBase
    {
        public string Header { get; set; } = "XGPilot";
        IChatClient asChatClient = null;
        List<Microsoft.Extensions.AI.ChatMessage> messages = [];
    
        public EngCopilotViewModel()
        {
            RegisterAIChatClient();
            //var tools = GetMCPToolTest();
            //ApplyToolsToChatClient();
    
           
        }
    
        private DelegateCommand<object> markdownConvertCommand;
        public DelegateCommand<object> MarkdownConvertCommand =>
            markdownConvertCommand ?? (markdownConvertCommand = new DelegateCommand<object>(ExecuteMarkdownConvertCommand));
        void ExecuteMarkdownConvertCommand(object obj)
        {
            var e = obj as AIChatControlMarkdownConvertEventArgs;
            e.HtmlText = (MarkupString)Markdig.Markdown.ToHtml(e.MarkdownText);
        }
    
        private DelegateCommand<object> messageSentCommand;
        public DelegateCommand<object> MessageSentCommand =>
            messageSentCommand ?? (messageSentCommand = new DelegateCommand<object>(ExecuteMessageSentCommand));
        async void ExecuteMessageSentCommand(object obj)
        {
            var e = obj as AIChatControlMessageSentEventArgs;
            var message = e.Content;
    
            var messages = await ApplyToolsToChatClient(message, e);
    
            //await e.SendMessage(, ChatRole.Assistant);
        }
    
    
    
        async Task<IList<McpClientTool>> GetMCPToolTest()
        {
            var client = McpClientCollection.GetAxMcpClient();
            var tools = await client.ListToolsAsync();
            return tools;
        }
    
    
        async Task<List<ChatMessage>> ApplyToolsToChatClient(string message, AIChatControlMessageSentEventArgs eventArgs)
        {
            //Console.Write("Q: ");
            messages.Add(new(ChatRole.User, message));
    
            List<ChatResponseUpdate> updates = [];
            string updateText = string.Empty;
            var tools = await GetMCPToolTest();
            await foreach (var update in asChatClient.GetStreamingResponseAsync(messages, new() { Tools = [.. tools] }))
            {
                updateText += update.Text;
                updates.Add(update);
            }
            await eventArgs.SendMessage(updateText, ChatRole.Assistant);
    
            //messages.Clear();
            messages.AddMessages(updates);
            return Task.FromResult(messages).Result;
        }
    
        private void RegisterAIChatClient()
        {
            string azureOpenAIEndpoint = "https://iskimls.openai.azure.com/";
            string azureOpenAIKey = "3XP9Nm6azrubLH0LTc8UmMvpZcVRYFTGF4rO1ywWhb4QQxlWGsQiJQQJ99BLACHYHv6XJ3w3AAABACOGjeb3";
            string deployment = "gpt-5-chat";
    
            var container = AIExtensionsContainerDesktop.Default;
    
            asChatClient = new ChatClientBuilder( 
                new AzureOpenAIClient(new Uri(azureOpenAIEndpoint),
                    new System.ClientModel.ApiKeyCredential(azureOpenAIKey))
                .GetChatClient(deployment).AsIChatClient() 
                ).UseDXTools()
                .UseFunctionInvocation()
                .Build(container);
    
            container.RegisterChatClient(asChatClient);
    
        }
    }

     

     

    asChatClient = new ChatClientBuilder( ... )

     

    ChatClientBuilder 사용해야 GetStreamingResponseAsync 에서 오류 안남.

     

     

     

    # MessageSent

     

      <dxmvvm:EventToCommand 
              SourceName="aiChatControl"
              EventName="MessageSent" 
              Command="{Binding MessageSentCommand}"
              PassEventArgsToCommand="True"/>

     

    
        private DelegateCommand<object> messageSentCommand;
        public DelegateCommand<object> MessageSentCommand =>
            messageSentCommand ?? (messageSentCommand = new DelegateCommand<object>(ExecuteMessageSentCommand));
        async void ExecuteMessageSentCommand(object obj)
        {
            var e = obj as AIChatControlMessageSentEventArgs;
            var message = e.Content;
    
            var messages = await ApplyToolsToChatClient(message, e);
    
        }

     

    AI Chat Control에서 prompt 입력시 Message를 기존 DevExpress 로직이 아니라 Custom 해서 Reply 가능하게 함.

    # 직접 Reply를 얻어서 반환해줘야 함.

     

     

     

     

    MessageSent 사용시 기존 AIChatControl과의 호환성 문제 있음.

    Ex) ChatResources 적용 안된다던가..


     

     

    https://docs.devexpress.com/WPF/405434/ai-powered-extensions/ai-chat-control?v=25.2&utm_source=SupportCenter&utm_medium=mail&utm_campaign=docs-feedback&utm_content=T1316946#tool-calling

     

    AI Chat Control | WPF Controls | DevExpress Documentation

    Developer documentation for all DevExpress products.

    docs.devexpress.com

     

    https://docs.devexpress.com/WPF/405613/ai-powered-extensions/ai-chat-control/resources?v=25.2&utm_source=SupportCenter&utm_medium=mail&utm_campaign=docs-feedback&utm_content=T1316946

     

    Chat Resources | WPF Controls | DevExpress Documentation

    Developer documentation for all DevExpress products.

    docs.devexpress.com

     

     

    https://docs.devexpress.com/CoreLibraries/405585/ai-integration/ai-tool-calling?v=25.2&utm_source=SupportCenter&utm_medium=mail&utm_campaign=docs-feedback&utm_content=T1316946

     

    Tool Calling (AI Chat Control) | Cross-Platform Class Library | DevExpress Documentation

    Developer documentation for all DevExpress products.

    docs.devexpress.com

     

     

    728x90

    'DevExpress > DX_WPF' 카테고리의 다른 글

    [DX_WPF] DevExpress Toolbox is not presented  (0) 2025.06.26
    [DX_WPF] RatingEdit 5 Star  (0) 2025.06.24
    [DX_WPF] ModuleManager Module ViewModel Command  (0) 2025.06.20
    [DX_WPF] DevExpress Package folder  (0) 2025.06.19
    [DX_WPF] DevExpressMvvm  (0) 2025.06.17

    댓글

Designed by Tistory.