blazor-devexpress-dot-aiintegration-dot-blazor-dot-chat.md
An AI-powered chat component.
Namespace : DevExpress.AIIntegration.Blazor.Chat
Assembly : DevExpress.AIIntegration.Blazor.Chat.v25.2.dll
NuGet Package : DevExpress.AIIntegration.Blazor.Chat
public class DxAIChat :
DxComponentBase,
IAsyncDisposable,
IAIChat,
INestedSettingsOwner
DevExpress Blazor AI Chat (<DxAIChat>) is an AI-powered chat component that allows users to interact with AI services.
Run Demo: AI Chat
View Example: Add a DxAIChat component in Blazor, MAUI, WPF, and WinForms applications
View Example: Build a Multi-LLM Chat Application
View Example: Implement Function/Tool Calling
The DevExpress Blazor AI Chat component is compatible with major cloud AI providers and self-hosted language models. Its architecture also allows you to integrate custom AI providers or implement support for proprietary, in-house LLMs.
For a complete list of supported AI providers and detailed integration instructions, see the following help topic: DevExpress AI-powered Extensions for Blazor.
Note
DevExpress AI-powered extensions operate on a “bring your own key” (BYOK) model. We do not provide a proprietary REST API or bundled language models (LLMs/SLMs).
You can either deploy a self-hosted model or connect to a cloud AI provider and obtain necessary connection parameters (endpoint, API key, language model identifier, and so on). These parameters must be configured at application startup to register an AI client and enable extension functionality.
Follow the steps below to add an AI Chat component to an application:
Create a Blazor Server or Blazor WebAssembly application.
Install NuGet packages and register the AI model in the project’s entry point class.
Add the following markup to a .razor file:
Optional Configure other model options (see sections below).
Important
Never hardcode AI provider access keys, credentials, or API endpoints directly in your source code. Refer to the following help topic for additional information: Secret Management for Blazor AI Components.
Refer to the following list for the component API reference: DxAIChat Members.
Use Blazor Hybrid technology to integrate DevExpress AI Chat into WinForms, WPF, or .NET MAUI applications. The following GitHub repository includes an implementation example: Blazor AI Chat - How to add the DevExpress Blazor AI Chat component to your next Blazor, MAUI, WPF, and WinForms application.
The DxAIChat component allows you to specify the following AI model settings:
FrequencyPenaltySpecifies how the model penalizes new tokens based on their frequency in the text.MaxTokensLimits the maximum number of tokens to generate in a single call to a GPT model.TemperatureSpecifies the response text randomness.
Enable the UseStreaming property for a more responsive chat experience. This setting allows the AI client to send parts of the response once they become available, and the chat component will update the display message accordingly.
<DxAIChat UseStreaming="true" />
The AI service uses plain text as the default response format. To display rich formatted responses, set the ResponseContentFormat property to Markdown and use a markdown processor to convert response content to HTML code.
Important
Always sanitize HTML generated from Markdown to prevent cross-site scripting (XSS). Use a trusted sanitizer (for example, the HtmlSanitizer package) to allow only safe tags and attributes before the browser renders content.
@using Markdig
@using Ganss.Xss
<DxAIChat ResponseContentFormat="ResponseContentFormat.Markdown">
<MessageContentTemplate>
@ToHtml(context.Content)
</MessageContentTemplate>
</DxAIChat>
@code {
private readonly HtmlSanitizer sanitizer = new HtmlSanitizer();
MarkupString ToHtml(string markdown) {
string html = Markdown.ToHtml(markdown);
// Sanitize the HTML to prevent XSS attacks
html = sanitizer.Sanitize(html);
return new MarkupString(html);
}
}
<DxAIChat> allows users to attach files when sending messages to the chat. Set the DxAIChat.FileUploadEnabled property to true to enable file upload operations.
Once a user attaches files to a message, the AI Chat component validates attached files. To configure validation rules, declare a DxAIChatFileUploadSettings object in AIChatSettings component markup. You can validate file size, extension, and type as well as limit the number of files.
The following code snippet activates the file upload functionality in Blazor AI Chat and configures validation rules for uploaded files:
@using DevExpress.AIIntegration.Blazor.Chat
<DxAIChat CssClass="demo-chat"
FileUploadEnabled="true">
<AIChatSettings>
<DxAIChatFileUploadSettings MaxFileCount="2"
MaxFileSize="20000"
AllowedFileExtensions="@(new List<string> { ".jpg", ".pdf" })"
FileTypeFilter="@(new List<string> { "image/*", "application/pdf"})" />
</AIChatSettings>
</DxAIChat>
You can also use the AIChatUploadFileInfo class to send messages with file attachments in code (via the SendMessage method) or access and process uploaded files in a MessageSent event handler.
Run Demo: AI Chat - File Attachments
Note
The DevExpress Blazor AI Chat component only facilitates the file upload. It does not process or analyze the file’s content. The ability to interpret a specific file format depends entirely on the capabilities of the connected AI model.
See the AIChatUploadFileInfo class description for details.
The DxAIChat component includes the following message customization properties:
MessageTemplateChanges the message bubble rendering, including paddings and inner content alignment.MessageContentTemplateAlters message bubble content without affecting layout.EmptyMessageAreaTemplateSpecifies the template used to display the message area if there are no message bubbles.
Important
Always sanitize HTML generated from Markdown to prevent cross-site scripting (XSS). Use a trusted sanitizer (for example, the HtmlSanitizer package) to allow only safe tags and attributes before the browser renders content.
@using Markdig
@using Ganss.Xss
<DxAIChat CssClass="demo-chat"
Initialized="ChatInitialized"
ResponseContentFormat="ResponseContentFormat.Markdown">
<MessageContentTemplate>
<div class="demo-chat-content">
@ToHtml(context.Content)
</div>
</MessageContentTemplate>
</DxAIChat>
</div>
@code {
private readonly HtmlSanitizer sanitizer = new HtmlSanitizer();
MarkupString ToHtml(string markdown) {
string html = Markdown.ToHtml(markdown);
// Sanitize the HTML to prevent XSS attacks
html = sanitizer.Sanitize(html);
return new MarkupString(html);
}
void ChatInitialized(IAIChat chat) {
chat.LoadMessages(new[] {
new BlazorChatMessage(Microsoft.Extensions.AI.ChatRole.User, "Hello, AI!"),
new BlazorChatMessage(Microsoft.Extensions.AI.ChatRole.Assistant, "Hey there, human! What's on your mind? 😊")
});
}
}
.demo-chat {
width: 100%;
height: 400px;
}
.demo-chat .demo-chat-content > p:last-child {
margin-bottom: 0;
}
Run Demo: AI Chat - Rich Formatted Response
When a user sends a message to the chat, the MessageSent event fires. Handle the event to manually process this action. You can use the Content event argument to access user input and call the SendMessage(String, ChatRole, List<AIChatUploadFileInfo>) method to send another message to the chat.
<DxAIChat MessageSent="MessageSent" />
@code {
async Task MessageSent(MessageSentEventArgs args) {
await args.Chat.SendMessage($"Processed: {args.Content}", ChatRole.Assistant);
}
}
Run Demo: AI Chat - Manual Message Processing
Our Blazor AI Chat component allows users to stop chat message generation before it is complete. You can also use the CancellationToken argument property in a MessageSent event handler to process cancellations in code.
Use SaveMessages and LoadMessages methods to manage chat history.
<DxAIChat Initialized="ChatInitialized" />
@code {
void ChatInitialized(IAIChat chat) {
chat.LoadMessages(new[] {
new BlazorChatMessage(Microsoft.Extensions.AI.ChatRole.Assistant, "Hello, how can I help you?")
});
}
}
DevExpress Blazor AI Chat allows you to create a system prompt that provides the AI model with initial role context and specific instructions. The following code snippet adds a system prompt to the chat using the LoadMessages method in the DxAIChat.Initialized event handler:
<DxAIChat Initialized="ChatInitialized" />
@code {
async Task ChatInitialized(IAIChat chat) {
var prompt = @"
You are a friendly hiking enthusiast who helps people discover fun hikes in their area.
You introduce yourself when first saying hello.
When helping people out, you always ask them for this information
to inform the hiking recommendation you provide:
1. The location where they would like to hike
2. What hiking intensity they are looking for
You will then provide three suggestions for nearby hikes that vary in length
after you get that information. You will also share an interesting fact about
local nature on the hikes when making a recommendation. At the end of your
response, ask if there is anything else you can help with.
";
chat.LoadMessages(new[] {
new BlazorChatMessage(Microsoft.Extensions.AI.ChatRole.System, prompt),
});
}
}
DevExpress Blazor AI Chat supports prompt suggestions – hints that guide users to possible actions. The component displays prompt suggestions (hint bubbles) when the chat area is empty.
Follow the steps below to enable and configure prompt suggestions:
Run Demo: AI Chat – Prompt Suggestions
@using DevExpress.AIIntegration.Blazor.Chat
<DxAIChat Initialized="ChatInitialized">
<PromptSuggestions>
@foreach (var suggestion in PromptSuggestions) {
<DxAIChatPromptSuggestion Title="@suggestion.Title"
Text="@suggestion.Text"
PromptMessage="@suggestion.PromptMessage" />
}
</PromptSuggestions>
</DxAIChat>
@code {
List<PromptSuggestion> PromptSuggestions { get; set; }
void ChatInitialized() {
PromptSuggestions = GetData();
}
}
public List<PromptSuggestion> GetData() {
return new List<PromptSuggestion>() {
new PromptSuggestion("Tell me a joke", "Take a break and enjoy a quick laugh", "Tell me a joke."),
new PromptSuggestion("Summarize text", "Extract a quick summary (main ideas)", "Summarize the following text:"),
new PromptSuggestion("Write an email", "Make your text look and sound professional", "Format text as a formal email to a client:"),
new PromptSuggestion("Brainstorm ideas", "Get creative input for your tasks", "Help me brainstorm ideas for:"),
new PromptSuggestion("Fix my writing", "Avoid spelling, grammar, and style errors", "Proofread the following text:"),
};
}
public class PromptSuggestion {
public string Title { get; set; }
public string Text { get; set; }
public string PromptMessage { get; set; }
public PromptSuggestion (string title, string text, string promptMessage) {
Title = title;
Text = text;
PromptMessage = promptMessage;
}
}
Additionally, you can use the PromptSuggestionContentTemplate property to specify a template for prompt suggestions.
The DevExpress AI Chat component supports OpenAI Assistants. You can use a single OpenAI Assistant instance to initiate multiple tasks within a single application. To connect the chat to an existing assistant, pass the asisstant and thread IDs to the SetupAssistantAsync(String, String) method as parameters.
Note
Availability of Azure Open AI Assistants depends on the region. Refer to the following article for more details: Assistants (Preview).
The following code snippet creates an OpenAI Assistant, obtains the assistant and thread IDs, and connects the Blazor AI Chat to the assistant in a DxAIChat.Initialized event handler:
@using DevExpress.AIIntegration.OpenAI.Services
@using DevExpress.AIIntegration.Blazor.Chat
@using AIIntegration.Services.Chat
@using Markdig
@using Ganss.Xss
@inject ReportingApp.AIAssistantCreator assistantCreator
<DxAIChat CssClass="my-chat"
Initialized="Initialized"
ResponseContentFormat="ResponseContentFormat.Markdown">
<MessageContentTemplate>
<div class="my-chat-content">
@ToHtml(context.Content)
</div>
</MessageContentTemplate>
</DxAIChat>
@code {
private readonly HtmlSanitizer sanitizer = new HtmlSanitizer();
const string DocumentResourceName = "DevExpress.AI.Samples.Blazor.Data.Restaurant Menu.pdf";
const string prompt = "You are an analytics assistant specialized in analyzing PDF files. Your role is to assist users by providing accurate answers to their questions about data contained within these files.\n \n### Tasks:\n- Perform various types of data analyses, including summaries, calculations, data filtering, and trend identification.\n- Clearly explain your analysis process to ensure users understand how you arrived at your answers.\n- Always provide precise and accurate information based on the Excel data.\n- If you cannot find an answer based on the provided data, explicitly state: \"The requested information cannot be found in the data provided.\"\n \n### Examples:\n1. **Summarization:** \n - **User Question:** \"What is the average sales revenue for Q1?\"\n - **Response:** \"The average sales revenue for Q1 is calculated as $45,000, based on the data in Sheet1, Column C.\"\n \n2. **Data Filtering:** \n - **User Question:** \"Which products had sales over $10,000 in June?\"\n - **Response:** \"The products with sales over $10,000 in June are listed in Sheet2, Column D, and they include Product A, Product B, and Product C.\"\n \n3. **Insufficient Data:** \n - **User Question:** \"What is the market trend for Product Z over the past 5 years?\"\n - **Response:** \"The requested information cannot be found in the data provided, as the dataset only includes data for the current year.\"\n \n### Additional Instructions:\n- Format your responses to clearly indicate which sheet and column the data was extracted from when necessary.\n- Avoid providing any answers if the data in the file is insufficient for a reliable response.\n- Ask clarifying questions if the user's query is ambiguous or lacks detail.\n \nRemember, your primary goal is to provide helpful, data-driven insights that directly answer the user's questions. Do not assume or infer information not present in the dataset.";
async Task Initialized(IAIChat chat) {
(string assistantId, string threadId) = await assistantCreator.CreateAssistantAsync(
Assembly.GetExecutingAssembly().GetManifestResourceStream(DocumentResourceName)!,
$"{Guid.NewGuid().ToString("N")}.pdf",
prompt);
await chat.SetupAssistantAsync(assistantId, threadId);
}
MarkupString ToHtml(string markdown) {
string html = Markdown.ToHtml(markdown);
// Sanitize the HTML to prevent XSS attacks
html = sanitizer.Sanitize(html);
return new MarkupString(html);
}
}
// ...
var azureClient = new AzureOpenAIClient(
new Uri(azureOpenAIEndpoint),
new AzureKeyCredential(azureOpenAIKey));
IChatClient chatClient = azureClient.GetChatClient(deploymentName).AsIChatClient();
var assistantCreator = new AIAssistantCreator(azureClient, deploymentName);
builder.Services.AddDevExpressBlazor();
builder.Services.AddChatClient(chatClient);
builder.Services.AddSingleton(assistantCreator);
builder.Services.AddDevExpressAI(config => {
// Reference the DevExpress.AIIntegration.OpenAI NuGet package to use Open AI Assistants
config.RegisterOpenAIAssistants(azureClient, deploymentName);
});
// ...
using System.ClientModel;
using OpenAI;
using OpenAI.Assistants;
using OpenAI.Files;
namespace ReportingApp {
public class AIAssistantCreator {
readonly AssistantClient assistantClient;
readonly OpenAIFileClient fileClient;
readonly string deployment;
public AIAssistantCreator(OpenAIClient client, string deployment) {
assistantClient = client.GetAssistantClient();
fileClient = client.GetOpenAIFileClient();
this.deployment = deployment;
}
public async Task<(string assistantId, string threadId)> CreateAssistantAsync(Stream data, string fileName, string instructions, bool useFileSearchTool = true, CancellationToken ct = default) {
data.Position = 0;
ClientResult<OpenAIFile> fileResponse = await fileClient.UploadFileAsync(data, fileName, FileUploadPurpose.Assistants, ct);
OpenAIFile file = fileResponse.Value;
var resources = new ToolResources() {
CodeInterpreter = new CodeInterpreterToolResources(),
FileSearch = useFileSearchTool ? new FileSearchToolResources() : null
};
resources.FileSearch?.NewVectorStores.Add(new VectorStoreCreationHelper([file.Id]));
resources.CodeInterpreter.FileIds.Add(file.Id);
AssistantCreationOptions assistantCreationOptions = new AssistantCreationOptions() {
Name = Guid.NewGuid().ToString(),
Instructions = instructions,
ToolResources = resources
};
assistantCreationOptions.Tools.Add(new CodeInterpreterToolDefinition());
if (useFileSearchTool) {
assistantCreationOptions.Tools.Add(new FileSearchToolDefinition());
}
ClientResult<Assistant> assistantResponse = await assistantClient.CreateAssistantAsync(deployment, assistantCreationOptions, ct);
ClientResult<AssistantThread> threadResponse = await assistantClient.CreateThreadAsync(cancellationToken: ct);
return (assistantResponse.Value.Id, threadResponse.Value.Id);
}
}
}
The DevExpress AI Chat component enables the integration of Blazor application logic with natural language input. It can invoke methods annotated with metadata (called AI tools) to execute any action in the UI or business logic. Each tool describes its purpose, input parameters, and (optionally) the target object on which it operates.
The AI service automatically resolves a relevant function at runtime based on chat context. The selection depends on the capabilities of the configured IChatClient and the model. If the model does not support tool calling or if no function is considered relevant, a normal text response is generated.
We have added an AI tool calling layer that extends capabilities found in Microsoft.Extensions.AI:
Target-aware tools Tools can operate on specific object instances (UI controls, pages, data services, business objects). The API automatically resolves target objects at runtime based on context and descriptions. Flexible tool contexts Tools can be grouped into contexts that can be enabled, disabled, or removed dynamically based on application state or user workflow. Seamless integration with the AI Chat Control The DevExpress Blazor AI Chat Control discovers and merges tools from all registered contexts and manages tool selection, target resolution, parameter binding, and invocation.
The following code snippet registers DevExpress AI services, defines a contextual AI tool, and integrates an AI tool calling pipeline into an application:
@using DevExpress.AIIntegration.Blazor.Chat
@using DevExpress.AIIntegration.Tools
@inject AIToolsContextContainer container
<DxAIChat />
<DxGrid @ref="grid">
<!-- ... -->
</DxGrid>
@code {
DxGrid grid;
AIToolsContext context;
protected override void OnAfterRender(bool firstRender) {
if (firstRender) {
context = new AIToolsContextBuilder()
.WithToolMethods(ExpandGroups)
.Build();
container.Add(context);
}
}
}
using DevExpress.AIIntegration;
/* ... */
[AIIntegrationTool("GridControl_ExpandGroups")]
[Description("Expands all group rows in the grid.")]
public static string ExpandGroups(
[AIIntegrationToolTarget("The grid with collapsed group rows.")]
GridControl target_grid
) {
if (target_grid.GroupCount == 0) return "No grouped rows found.";
target_grid.ExpandAllGroups();
return "All groups are expanded.";
}
using Azure.AI.OpenAI;
using DevExpress.AIIntegration;
using Microsoft.Extensions.AI;
// Create Azure OpenAI client
AzureOpenAIClient azureOpenAIClient = new(
new Uri(azureOpenAiEndpoint),
new ApiKeyCredential(azureOpenAiKey)
);
IChatClient azureOpenAIChatClient = azureOpenAIClient.GetChatClient(azureOpenAiModel).AsIChatClient();
// Register scoped chat client with DevExpress AI tool calling
builder.Services.AddScoped((sp) => {
return azureOpenAIChatClient.AsBuilder()
.UseDXTools() // DevExpress AI tool calling
.UseFunctionInvocation() // Microsoft.Extensions.AI function invocation
.Build(sp);
});
// Register DevExpress AI services
builder.Services.AddDevExpressAI();
Refer to the Tool Calling help topic for additional information.
Object ComponentBase DxComponentBase DxAIChat
See Also