|
3 | 3 | [](https://docs.devexpress.com/GeneralInformation/403183)
|
4 | 4 | [](#does-this-example-address-your-development-requirementsobjectives)
|
5 | 5 | <!-- default badges end -->
|
6 |
| -# Product/Platform - Task |
| 6 | +# Report Viewer and Data Grid for Blazor — Integrate an AI Assistant based on Azure OpenAI |
7 | 7 |
|
8 |
| -This is the repository template for creating new examples. Describe the solved task here. |
| 8 | +This example integrates an AI assistant into DevExpress Blazor Components. User requests and assistant responses are displayed on-screen using the [DevExpress Blazor AI Chat](http://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat?v=24.2) component. |
9 | 9 |
|
10 |
| -Put a screenshot that illustrates the result here. |
| 10 | +With an AI Assistant integrated in our AI-chat component, you can filter and manipulate data, generate document summaries, and ask context-aware questions about report content, table data, and more — all within the user interface. |
11 | 11 |
|
12 |
| -Then, add implementation details (steps, code snippets, and other technical information in a free form), or add a link to an existing document with implementation details. |
| 12 | +This example demonstrates the following DevExpress Blazor Components: |
| 13 | + |
| 14 | +- [Blazor Data Grid](https://www.devexpress.com/blazor/data-grid/) |
| 15 | + |
| 16 | + The Grid is bound to a project management data that tracks tasks or issues across various projects. It includes details like task subject, owner and assignee, status, priority, and key dates (created, modified, fixed). You can ask the AI Assistant questions about task data: |
| 17 | + - What tasks should the team focus on first? |
| 18 | + - How many tasks are currently marked as New? |
| 19 | + - What tasks are of the highest priority for Mike Roller? |
| 20 | + |
| 21 | +- [Blazor Report Viewer](https://www.devexpress.com/subscriptions/reporting/) |
| 22 | + |
| 23 | + The Report Viewer presents multiple reports bound to different data sources. The available reports include: |
| 24 | + |
| 25 | + - The *Drill-Down Report* displays invoices where the expandable/collapsible sections list purchased products. You can ask the AI Assistant: Which invoice has the highest total order value? How many orders are currently in transit, pending, or delivered? What is the average order value per invoice? |
| 26 | + - The *Market Share Report* includes sales figures, changes from the prior year, and current market share percentages for various regions and countries across different time periods. ou can ask the AI Assistant: Which region had the highest market share in September? How did market share change for India? How does Canada’s market share growth compare to the USA’s? |
| 27 | + - The *Restaurant Menu* includes multiple groups, each group represents a different category and sub-category of meals and beverages. ou can ask the AI Assistant: What are the price ranges for the menu items? Are there any vegetarian or non-meat options on this menu? |
| 28 | + |
| 29 | +To navigate to page with the component, click in the corresponding card on the root page: |
| 30 | + |
| 31 | + |
| 32 | + |
| 33 | +>[!TIP] |
| 34 | +> Please note that AI Assistant initialization takes time. The assistant tab appears once Microsoft Azure scans the source document (i.e., grid or report data) on the server side. |
| 35 | +
|
| 36 | +## Implementation Details |
| 37 | + |
| 38 | +### Register AI Services |
| 39 | + |
| 40 | +> [!NOTE] |
| 41 | +> 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. |
| 42 | +
|
| 43 | +Create an Azure OpenAI resource in the Azure portal to use AI Assistants. Refer to the following help topic for details: [Microsoft - Create and deploy an Azure OpenAI Service resource](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource?pivots=web-portal). |
| 44 | + |
| 45 | +Once you obtain a private endpoint and an API key, register them as `AZURE_OPENAI_ENDPOINT` and `AZURE_OPENAI_APIKEY` environment variables in your application. |
| 46 | + |
| 47 | +Add the following code to the *Program.cs* file to register the AI Services and an [OpenAI Assistant](https://platform.openai.com/docs/assistants/overview) in your application: |
| 48 | + |
| 49 | +```cs |
| 50 | +using Azure.AI.OpenAI; |
| 51 | +using DevExpress.AIIntegration; |
| 52 | +using Microsoft.Extensions.AI; |
| 53 | +using System.ClientModel; |
| 54 | +//... |
| 55 | +string azureOpenAIEndpoint = "AZURE_OPENAI_ENDPOINT"; |
| 56 | +string azureOpenAIKey = "AZURE_OPENAI_API_KEY"; |
| 57 | +string deploymentName = "YOUR_MODEL_NAME"; |
| 58 | +//... |
| 59 | +var azureClient = new AzureOpenAIClient( |
| 60 | + new Uri(azureOpenAIEndpoint), |
| 61 | + new ApiKeyCredential(azureOpenAIKey)); |
| 62 | +builder.Services.AddChatClient(config => |
| 63 | + config.Use(azureClient.AsChatClient(deploymentName)) |
| 64 | +); |
| 65 | +builder.Services.AddDevExpressAI((config) => { |
| 66 | + config.RegisterOpenAIAssistants(azureClient, deploymentName); |
| 67 | +}); |
| 68 | +``` |
| 69 | + |
| 70 | +For more information on AI Assistants, refer to the following topic: [AI Service Assistants in the DxAIChat component](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat#ai-service-assistants). |
| 71 | + |
| 72 | +**Files to Review:** |
| 73 | + |
| 74 | +- [Program.cs](./DevExpress.AI.Samples.Blazor/Program.cs) |
| 75 | + |
| 76 | +### Add an AI Assistant to Grid |
| 77 | + |
| 78 | +The following image displays page with `DxGrid` and `DxAIChat` components implemented in this example: |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | +For the `DxGrid` configuration (data binding and customizations), review the [Grid.razor](./DevExpress.AI.Samples.Blazor/Components/Pages/Grid.razor) file. |
| 83 | + |
| 84 | +#### Add AI Chat to the Grid Page |
| 85 | + |
| 86 | +The following code snippet adds the [`DxAIChat`](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat) to the page: |
| 87 | + |
| 88 | +```razor |
| 89 | +@using DevExpress.AIIntegration.Blazor.Chat |
| 90 | +@using Markdig |
| 91 | +
|
| 92 | +<DxGrid @ref="grid" Data="@DataSource" CssClass="my-grid" ShowGroupPanel="true" TextWrapEnabled="false"> |
| 93 | + @* ... *@ |
| 94 | +</DxGrid> |
| 95 | +<DxAIChat @ref="chat" CssClass="my-grid-chat"> |
| 96 | + <MessageContentTemplate> |
| 97 | + <div class="my-chat-content"> |
| 98 | + @ToHtml(context.Content) |
| 99 | + </div> |
| 100 | + </MessageContentTemplate> |
| 101 | +</DxAIChat> |
| 102 | +
|
| 103 | +@code { |
| 104 | + MarkupString ToHtml(string text) { |
| 105 | + return (MarkupString)Markdown.ToHtml(text); |
| 106 | + } |
| 107 | +} |
| 108 | +``` |
| 109 | + |
| 110 | +Use the [`MessageContentTemplate`](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat.MessageContentTemplate) property to display any render fragment in a message bubble. For more information on appearance customization, refer to the following help document: [Customizable Message Appearance and Empty Message Area](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat#customizable-message-appearance-and-empty-message-area). To display rich formatted messages, use a markdown processor to convert the response content to HTML code. |
| 111 | + |
| 112 | +**Files to Review:** |
| 113 | + |
| 114 | +- [Grid.razor](./DevExpress.AI.Samples.Blazor/Components/Pages/Grid.razor) |
| 115 | + |
| 116 | +#### Set Up the AI Assistant |
| 117 | + |
| 118 | +Handle the `OnAfterRenderAsync` event and call the [`SetupAssistantAsync`](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.IAIChat.SetupAssistantAsync(DevExpress.AIIntegration.Services.Assistant.AIAssistantOptions)) method to create an AI assistant and provide it with data and instructions. In this example, grid data is exported to XLSX using the [`ExportToXlsxAsync`](https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxGrid.ExportToXlsxAsync.overloads) method and is passed to the assistant along with the instructions: |
| 119 | + |
| 120 | +```razor |
| 121 | +@using DevExpress.AIIntegration.OpenAI.Services |
| 122 | +
|
| 123 | +@* ... *@ |
| 124 | +@code { |
| 125 | + protected override async Task OnAfterRenderAsync(bool firstRender) { |
| 126 | + if(firstRender) { |
| 127 | + using(MemoryStream ms = new MemoryStream()) { |
| 128 | + grid.BeginUpdate(); |
| 129 | + grid.ShowGroupedColumns = true; |
| 130 | + await grid.ExportToXlsxAsync(ms, new GridXlExportOptions() { |
| 131 | + ExportDisplayText = true |
| 132 | + }); |
| 133 | + await chat.SetupAssistantAsync(new OpenAIAssistantOptions("grid_data.xlsx", ms) { |
| 134 | + Instructions = AssistantHelper.GetAIAssistantInstructions("xlsx"), |
| 135 | + UseFileSearchTool = false |
| 136 | + }); |
| 137 | + grid.ShowGroupedColumns = false; |
| 138 | + grid.EndUpdate(); |
| 139 | + } |
| 140 | + } |
| 141 | + await base.OnAfterRenderAsync(firstRender); |
| 142 | + } |
| 143 | +} |
| 144 | +``` |
| 145 | + |
| 146 | +You can review and tailor assistant instructions according to your needs in the following file: [Instructions.cs](./DevExpress.AI.Samples.Blazor/Instructions.cs). |
| 147 | + |
| 148 | +For information on OpenAI Assistants, refer to the following article: [Assistants API overview](https://platform.openai.com/docs/assistants/overview). |
| 149 | + |
| 150 | +**Files to Review:** |
| 151 | + |
| 152 | +- [Grid.razor](./DevExpress.AI.Samples.Blazor/Components/Pages/Grid.razor) |
| 153 | +- [Instructions.cs](./DevExpress.AI.Samples.Blazor/Instructions.cs) |
| 154 | + |
| 155 | +### Add an AI Assistant to Report Viewer |
| 156 | + |
| 157 | +The following image displays Blazor Report Viewer UI implemented in this example. The AI Assistant tab uses the `DxAIChat` component to display requests and responses: |
| 158 | + |
| 159 | + |
| 160 | + |
| 161 | +Use the [DxListBox](https://docs.devexpress.com/Blazor/DevExpress.Blazor.DxListBox-2) component to select a report and explore how different data is handled. |
| 162 | + |
| 163 | +#### Add a New Tab |
| 164 | + |
| 165 | +Use the [`OnCustomizeTabs`](https://docs.devexpress.com/XtraReports/DevExpress.Blazor.DxViewer.OnCustomizeTabs) event to add a new tab: |
| 166 | + |
| 167 | +```razor |
| 168 | +@using DevExpress.AI.Samples.Blazor.Components.Reporting |
| 169 | +@using DevExpress.AI.Samples.Blazor.Models |
| 170 | +@using DevExpress.Blazor.Reporting.Models |
| 171 | +
|
| 172 | +@* ... *@ |
| 173 | +<DxReportViewer @ref="Viewer" CssClass="my-report" OnCustomizeTabs="OnCustomizeTabs"> |
| 174 | +</DxReportViewer> |
| 175 | +@* ... *@ |
| 176 | +
|
| 177 | +@code { |
| 178 | + // ... |
| 179 | + void OnCustomizeTabs(List<TabModel> tabs) { |
| 180 | + tabs.Add(new TabModel(new UserAssistantTabContentModel(() => CurrentReport), "AI", "AI Assistant") { |
| 181 | + TabTemplate = (tabModel) => { |
| 182 | + return (builder) => { |
| 183 | + builder.OpenComponent<AITabRenderer>(0); |
| 184 | + builder.AddComponentParameter(1, "Model", tabModel.ContentModel); |
| 185 | + builder.CloseComponent(); |
| 186 | + }; |
| 187 | + } |
| 188 | + }); |
| 189 | + } |
| 190 | +} |
| 191 | +``` |
| 192 | + |
| 193 | +A new [`TabModel`](https://docs.devexpress.com/XtraReports/DevExpress.Blazor.Reporting.Models.TabModel._members) object is added to the list of tabs. The `UserAssistantTabContentModel` class implements the [`ITabContentModel`](https://docs.devexpress.com/XtraReports/DevExpress.Blazor.Reporting.Models.ITabContentModel) interface which defines the logic used to determine when the AI Assistant tab is displayed. The AI Assistant tab is only displayed when the report is initialized and contains at least one page. |
| 194 | + |
| 195 | +The `TabTemplate` property specifies the content of the tab. It dynamically renders an `DxAIChat` component inside the tab and passes the `ContentModel` as a parameter to control the tab's content. |
| 196 | + |
| 197 | +The content fot the AI Assistant tab is defined in the [AITabRenderer.razor](./DevExpress.AI.Samples.Blazor/Components/Reporting/AITabRenderer.razor) file: |
| 198 | + |
| 199 | +```razor |
| 200 | +@using DevExpress.AI.Samples.Blazor.Models |
| 201 | +@using DevExpress.AIIntegration.Blazor.Chat |
| 202 | +@using System.Text.RegularExpressions |
| 203 | +@using Markdig |
| 204 | +
|
| 205 | +<DxAIChat CssClass="my-report-chat"> |
| 206 | + <MessageContentTemplate> |
| 207 | + <div class="my-chat-content"> |
| 208 | + @ToHtml(context.Content) |
| 209 | + </div> |
| 210 | + </MessageContentTemplate> |
| 211 | +</DxAIChat> |
| 212 | +
|
| 213 | +@code { |
| 214 | + [Parameter] public UserAssistantTabContentModel Model { get; set; } |
| 215 | + string ClearAnnotations(string text) { |
| 216 | + //To clear out the annotations in a response from assistant. |
| 217 | + return Regex.Replace(text, @"\【.*?】", ""); |
| 218 | + } |
| 219 | + |
| 220 | + MarkupString ToHtml(string text) { |
| 221 | + text = ClearAnnotations(text); |
| 222 | + return (MarkupString)Markdown.ToHtml(text); |
| 223 | + } |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +Use the [`MessageContentTemplate`](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat.MessageContentTemplate) property to display any render fragment in a message bubble. For more information on appearance customization, refer to the following help document: [Customizable Message Appearance and Empty Message Area](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat#customizable-message-appearance-and-empty-message-area). To display rich formatted messages, use a markdown processor to convert the response content to HTML code. |
| 228 | + |
| 229 | +**Files to Review:** |
| 230 | + |
| 231 | +- [ReportViewer.razor](./DevExpress.AI.Samples.Blazor/Components/Pages/ReportViewer.razor) |
| 232 | +- [AITabRenderer.razor](./DevExpress.AI.Samples.Blazor/Components/Reporting/AITabRenderer.razor) |
| 233 | +- [UserAssistantTabContentModel.cs](./DevExpress.AI.Samples.Blazor/Models/UserAssistantTabContentModel.cs) |
| 234 | + |
| 235 | +#### Set Up the AI Assistant |
| 236 | + |
| 237 | +Handle the [`Initialized`](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat.Initialized) event and call the [`SetupAssistantAsync`](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.IAIChat.SetupAssistantAsync(DevExpress.AIIntegration.Services.Assistant.AIAssistantOptions)) method to create an AI assistant and provide it with data and instructions. In this example, report data is exported to PDF using the [`ExportToPdf`](https://docs.devexpress.com/CoreLibraries/DevExpress.XtraPrinting.PrintingSystemBase.ExportToPdf(System.IO.Stream)) method and is passed to the assistant along with the instructions: |
| 238 | + |
| 239 | +```razor |
| 240 | +@using DevExpress.AIIntegration.Blazor.Chat |
| 241 | +@using DevExpress.AIIntegration.OpenAI.Services |
| 242 | +
|
| 243 | +<DxAIChat CssClass="my-report-chat" Initialized="ChatInitialized"> |
| 244 | + @* ... *@ |
| 245 | +</DxAIChat> |
| 246 | +
|
| 247 | +@code { |
| 248 | + // ... |
| 249 | + async Task ChatInitialized(IAIChat aIChat) { |
| 250 | + using (MemoryStream ms = Model.GetReportData()) { |
| 251 | + await aIChat.SetupAssistantAsync(new OpenAIAssistantOptions("report.pdf", ms) { |
| 252 | + Instructions = AssistantHelper.GetAIAssistantInstructions("pdf") |
| 253 | + }); |
| 254 | + } |
| 255 | + } |
| 256 | +} |
| 257 | +``` |
| 258 | + |
| 259 | +You can review and tailor instructions to your needs in the following file: [Instructions.cs](./DevExpress.AI.Samples.Blazor/Instructions.cs). |
| 260 | + |
| 261 | +For information on OpenAI Assistants, refer to the following article: [Assistants API overview](https://platform.openai.com/docs/assistants/overview). |
| 262 | + |
| 263 | +**Files to Review:** |
| 264 | + |
| 265 | +- [ReportViewer.razor](./DevExpress.AI.Samples.Blazor/Components/Pages/ReportViewer.razor) |
| 266 | +- [AITabRenderer.razor](./DevExpress.AI.Samples.Blazor/Components/Reporting/AITabRenderer.razor) |
| 267 | +- [UserAssistantTabContentModel.cs](./DevExpress.AI.Samples.Blazor/Models/UserAssistantTabContentModel.cs) |
| 268 | +- [Instructions.cs](./DevExpress.AI.Samples.Blazor/Instructions.cs) |
13 | 269 |
|
14 | 270 | ## Files to Review
|
15 | 271 |
|
16 |
| -- link.cs (VB: link.vb) |
17 |
| -- link.js |
18 |
| -- ... |
| 272 | +- [Program.cs](./DevExpress.AI.Samples.Blazor/Program.cs) |
| 273 | +- [ReportViewer.razor](./DevExpress.AI.Samples.Blazor/Components/Pages/ReportViewer.razor) |
| 274 | +- [Grid.razor](./DevExpress.AI.Samples.Blazor/Components/Pages/Grid.razor) |
| 275 | +- [AITabRenderer.razor](./DevExpress.AI.Samples.Blazor/Components/Reporting/AITabRenderer.razor) |
| 276 | +- [UserAssistantTabContentModel.cs](./DevExpress.AI.Samples.Blazor/Models/UserAssistantTabContentModel.cs) |
| 277 | +- [Instructions.cs](./DevExpress.AI.Samples.Blazor/Instructions.cs) |
19 | 278 |
|
20 | 279 | ## Documentation
|
21 | 280 |
|
22 |
| -- link |
23 |
| -- link |
24 |
| -- ... |
| 281 | +- [Blazor AI Chat](https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat) |
| 282 | +- [Blazor Grid](https://docs.devexpress.com/Blazor/403143/components/grid) |
| 283 | +- [Blazor Report Viewer](https://docs.devexpress.com/XtraReports/403594/web-reporting/blazor-reporting/server/blazor-report-viewer-native) |
| 284 | +- [AI-powered Extensions for DevExpress Reporting](https://docs.devexpress.com/XtraReports/405211/ai-powered-functionality/ai-for-devexpress-reporting) |
25 | 285 |
|
26 | 286 | ## More Examples
|
27 | 287 |
|
28 |
| -- link |
29 |
| -- link |
30 |
| -- ... |
| 288 | +- [Reporting for Blazor - Integrate AI-powered Summarize and Translate Features based on Azure OpenAI](https://github.com/DevExpress-Examples/blazor-reporting-ai/) |
| 289 | +- [AI Chat for Blazor - How to add DxAIChat component in Blazor, MAUI, WPF, and WinForms applications](https://github.com/DevExpress-Examples/devexpress-ai-chat-samples) |
| 290 | +- [Rich Text Editor and HTML Editor for Blazor - How to integrate AI-powered extensions](https://github.com/DevExpress-Examples/blazor-ai-integration-to-text-editors) |
31 | 291 | <!-- feedback -->
|
32 | 292 | ## Does this example address your development requirements/objectives?
|
33 | 293 |
|
|
0 commit comments