DevExpress Blazor AI Chat -- Grammar & Style Assistant
The DevExpress AI Chat component is a versatile foundation for building AI-driven applications. This example uses OpenAI services to create a customizable grammar checker and demonstrates how to:
- Use inference parameters to control AI model behavior and creativity.
- Limit token usage for a single call to manage costs and performance.
- Sanitize user prompts and model outputs to secure your app.
- Define system prompts that give AI clear instructions on what to do.
- Request AI answers in Markdown and display them as HTML.
- Programmatically clear the chat and reset context.
- Programmatically send messages to the chat.
Setup and Configuration
To run this example, configure project dependencies and set up secure authentication for the desired AI service.
AI Packages
We use the following versions of Microsoft AI packages in the project:
- Microsoft.Extensions.AI | 9.7.1
- Microsoft.Extensions.AI.OpenAI | 9.7.1-preview.1.25365.4
We cannot guarantee compatibility or correct execution with newer versions. Refer to the following announcement for additional information: DevExpress.AIIntegration moves to a stable version.
Register AI Service
Note
DevExpress AI-powered extensions follow the "bring your own key" principle. DevExpress does not offer a REST API and does not ship any built-in LLMs/SLMs. You need an active Azure/Open AI subscription to obtain the REST API endpoint, key, and model deployment name. These variables must be specified at application startup to register AI clients and enable DevExpress AI-powered Extensions in your application.
This example uses the OpenAI service. For security, do not hardcode credentials in your source code. Instead, store your OpenAI API key in the OPENAI_KEY environment variable.
The following code in Program.cs retrieves the API key. Modify this code if you prefer to keep keys in appsettings.json or User Secrets.
Important
If your application throws an InvalidOperationException exception, restart your IDE or terminal to ensure they load the new variable.
Implementation Details
This section introduces key code blocks used in the example and how they work together to deliver a complete AI chat experience.
Inference Parameters
Inference parameters are runtime settings that control how a model generates output. You can use them to change creativity, length, or randomness of a response without retraining the model.
This example allows the user to control model temperature.
<DxAIChat Temperature="@Temperature"
MessageSent="@MessageSent">
DxAIChat>
@code {
float? Temperature { get; set; } = 0;
async Task MessageSent(MessageSentEventArgs args) {
/* ... */
var chatOptions = new ChatOptions {
Temperature = Temperature
};
var response = ChatClient.GetStreamingResponseAsync(messages, chatOptions);
/* ... */
}
}
Token Usage
A token is a basic unit of text that an AI model reads/writes. A token can be a whole word, part of a word, or a punctuation mark.
OpenAI bills you for the total token count. To save money, set a maximum number of tokens. A token limit also helps you stay within the model's context window, which ensures AI retains earlier parts of the conversation.
<DxAIChat MessageSent="@MessageSent">
DxAIChat>
@code {
int? MaxTokens { get; set; } = null;
async Task MessageSent(MessageSentEventArgs args) {
/* ... */
var chatOptions = new ChatOptions {
MaxOutputTokens = MaxTokens
};
var response = ChatClient.GetStreamingResponseAsync(messages, chatOptions);
/* ... */
}
}
Input Sanitization
To maintain data privacy, remove Personally Identifiable Information (PII) from your prompts. This practice ensures that sensitive details, such as email addresses or credit card numbers, do not reach external servers.
Handle the MessageSent event to override the automatic message delivery and preprocess messages before they are sent to OpenAI.
DxAIChat>
@code {
string ProcessText(string input) {
string placeholder = "[email removed]";
string emailPattern = @"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}";
return Regex.Replace(input, emailPattern, placeholder);
}
async Task MessageSent(MessageSentEventArgs args) {
var blazorMessages = args.Chat.SaveMessages();
var messages = blazorMessages.Select(m => new ChatMessage(
GetChatRole(m.Role),
ProcessText(m.Content))).ToList();
/* ... */
await args.Chat.SendMessage(responseString, ChatRole.Assistant);
}
}
After the message is processed, call SendMessage in the event handler.
AI Instructions
System prompts define instructions and boundaries for AI, which restrict the model's focus to a specific role. This prevents the model from "chatting" with the user.
This example establishes AI as the proofreader with expert English skills. This specific identity ensures that the model fixes all grammar and punctuation errors and enhances clarity/sentence flow.
You are a proofreader with excellent English skills. Your tasks:
- **Correct** grammar and punctuation
- **Improve** clarity and sentence structure
- **Be polite** and constructive
When a user sends text:
- Rewrite it with improvements
- Afterward, explain your changes with:
- The original phrase
- The updated version
- A brief explanation of why it was modified
This system prompt initializes at the start of each session and persists after a chat reset.
protected override void OnInitialized() {
base.OnInitialized();
using(var sr = new StreamReader("prompt.txt")) {
SystemPrompt = sr.ReadToEnd();
}
}
void ResetChat() {
List<BlazorChatMessage> initialMessages = new(){
new BlazorChatMessage(Microsoft.Extensions.AI.ChatRole.System, SystemPrompt),
new BlazorChatMessage(Microsoft.Extensions.AI.ChatRole.Assistant, "Welcome! Paste your text below and send it..."),
};
RefAiChat.LoadMessages(initialMessages);
}
protected override void OnAfterRender(bool firstRender) {
if(firstRender)
ResetChat();
}
Format AI Response
Set the ResponseContentFormat property to Markdown to request rich-formatted responses from the AI model. You can then use a markdown processor to convert this content to HTML and display it using the MessageContentTemplate property.
@using Ganss.Xss
<DxAIChat ResponseContentFormat="ResponseContentFormat.Markdown">
<MessageContentTemplate>
<div class="demo-chat-content">
@ToHtml(context.Content)
div>
MessageContentTemplate>
DxAIChat>
@code {
private readonly HtmlSanitizer sanitizer = new HtmlSanitizer();
MarkupString ToHtml(string markdown) {
string html = Markdown.ToHtml(markdown);
html = sanitizer.Sanitize(html);
return new MarkupString(html);
}
}
Important
Always sanitize HTML generated from Markdown to prevent cross-site scripting (XSS) attacks. Use a trusted sanitizer (for example, the HtmlSanitizer package) to allow only safe tags and attributes before the browser renders content.
Programmatically Handle Messages
Use the SendMessage method to programmatically send a message to the chat:
RefAiChat.SendMessage("open code of this example and change OpenAI...",
ChatRole.User);
}
Files to Review
Documentation
- DxAIChat
- MaxTokens
- Temperature
- ResponseContentFormat
- MessageContentTemplate
- SendMessage
- LoadMessages
- MessageSent
Does This Example Address Your Development Requirements/Objectives?
(you will be redirected to DevExpress.com to submit your response)