Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

DevExpress-Examples/blazor-ai-chat-spell-checker

Repository files navigation

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:

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.

string OpenAIKey = Environment.GetEnvironmentVariable("OPENAI_KEY");

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.

<DxSpinEdit @bind-Value="@Temperature" MinValue="0" MaxValue="2" Increment="0.05f" />



<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.

<DxSpinEdit @bind-Value="@MaxTokens" MinValue="0" Increment="10" />



<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 MessageSent="@MessageSent">
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.

string SystemPrompt { get; set; }

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 Markdig
@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:

void SendSampleMessage() {
RefAiChat.SendMessage("open code of this example and change OpenAI...",
ChatRole.User);
}

Files to Review

Documentation

Does This Example Address Your Development Requirements/Objectives?

(you will be redirected to DevExpress.com to submit your response)

About

Create a grammar and style checker powered by OpenAI services and dynamically adjust AI model parameters at runtime.

Topics

Resources

Readme

License

View license

Stars

Watchers

Forks

Contributors