From ab41f489f943c61a1043696e7444ebfc9ff8f895 Mon Sep 17 00:00:00 2001 From: Anton Mironov Date: Tue, 16 Dec 2025 13:11:09 +0200 Subject: [PATCH] update grid ai smart example to use the telerik extension telerik/kendo#24327 --- .../Controllers/Grid/SmartGridController.cs | 47 +++++- .../Telerik.Examples.Mvc/Program.cs | 16 ++ .../Telerik.Examples.Mvc.csproj | 4 + .../Views/Grid/SmartGrid.cshtml | 151 +++--------------- 4 files changed, 84 insertions(+), 134 deletions(-) diff --git a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Controllers/Grid/SmartGridController.cs b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Controllers/Grid/SmartGridController.cs index 946d48c..4a2d257 100644 --- a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Controllers/Grid/SmartGridController.cs +++ b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Controllers/Grid/SmartGridController.cs @@ -2,22 +2,32 @@ using Kendo.Mvc.UI; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using OpenAI.Chat; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Linq; +using System.Text.Json; using System.Threading.Tasks; +using Telerik.AI.SmartComponents.Extensions; using Telerik.Examples.Mvc.Models; +using Telerik.SvgIcons; namespace Telerik.Examples.Mvc.Controllers.Grid { public class SmartGridController : Controller { private readonly AiService _smartGridService; + IChatClient _chatClient; - public SmartGridController(AiService smartGridService) + public SmartGridController(IChatClient smartGridService) { - _smartGridService = smartGridService; + _chatClient = smartGridService; } public IActionResult SmartGrid() @@ -32,10 +42,37 @@ public IActionResult GetSales([DataSourceRequest] DataSourceRequest request) } [HttpPost] - public async Task Analyze([FromBody] GridAnalysisRequest request) + public async Task Analyze([FromBody] GridAIRequest request) { - var result = await _smartGridService.AnalyzeGridDataAsync(request.Instructions, request.GridJson); - return Json(new { result }); + var messages = request.Contents.Select(dto => dto).ToList(); + + var options = new ChatOptions(); + options.AddGridChatTools(request.Columns); + + List conversationMessages = request.Contents + .Select(m => new Microsoft.Extensions.AI.ChatMessage(ChatRole.User, m.Text)) + .ToList(); + + if (_chatClient == null) + { + return StatusCode(500, "Chat service is not available."); + } + + ChatResponse completion = await _chatClient.GetResponseAsync(conversationMessages, options); + + GridAIResponse response = completion.ExtractGridResponse(); + + return new ContentResult + { + Content = System.Text.Json.JsonSerializer.Serialize( + response, + new System.Text.Json.JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }), + ContentType = "application/json" + }; + } private List GetFullSalesData() diff --git a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Program.cs b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Program.cs index 7cf9221..1c82902 100644 --- a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Program.cs +++ b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Program.cs @@ -1,5 +1,7 @@ using AutoMapper; using AutoMapper.Internal; +using Azure; +using Azure.AI.OpenAI; using Kendo.Mvc.Extensions; using Kendo.Mvc.UI; using Microsoft.AspNetCore.Builder; @@ -13,6 +15,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.AI; using Microsoft.OData.Edm; using Microsoft.OData.ModelBuilder; using Newtonsoft.Json.Serialization; @@ -23,6 +26,7 @@ using System.Threading; using System.Threading.Tasks; using Telerik.Examples.Mvc.Controllers; +using Telerik.AI.SmartComponents.Extensions; using Telerik.Examples.Mvc.Database; using Telerik.Examples.Mvc.Hubs; using Telerik.Examples.Mvc.Models; @@ -57,6 +61,18 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); +// Register the Azure OpenAI client. +builder.Services.AddSingleton(new AzureOpenAIClient( + new Uri(builder.Configuration["OpenAI:Endpoint"]), + new AzureKeyCredential(builder.Configuration["OpenAI:ApiKey"]) +)); + +// Register the Chat client with the specified model. +builder.Services.AddChatClient(services => + services.GetRequiredService() + .GetChatClient("gpt-4.1-nano").AsIChatClient() +); + builder.Services.AddMvc() .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()); diff --git a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Telerik.Examples.Mvc.csproj b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Telerik.Examples.Mvc.csproj index 9e03ede..0788e7d 100644 --- a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Telerik.Examples.Mvc.csproj +++ b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Telerik.Examples.Mvc.csproj @@ -6,6 +6,7 @@ + @@ -18,11 +19,14 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Views/Grid/SmartGrid.cshtml b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Views/Grid/SmartGrid.cshtml index 31dd44b..45b00f5 100644 --- a/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Views/Grid/SmartGrid.cshtml +++ b/Telerik.Examples.Mvc/Telerik.Examples.Mvc/Views/Grid/SmartGrid.cshtml @@ -6,6 +6,14 @@ @(Html.Kendo().Grid() .Name("salesGrid") + .ToolBar(t => + { + t.AIAssistant(); + t.Spacer(); + t.Custom().Name("resetChanges") + .Text("Reset changes") + .IconClass("k-icon k-i-arrow-rotate-ccw"); + }) .Columns(columns => { columns.Bound(c => c.Id).Width(80); @@ -17,137 +25,22 @@ }) .Scrollable(s => s.Height("300px")) .DataSource(ds => ds.Ajax() + .Model(m => m.Id(x => x.Id)) .Read(read => read.Url("/SmartGrid/GetSales")) ) + .AI(ai => ai + .Service("/SmartGrid/Analyze") + .AIAssistant(aiAsst => aiAsst + .PromptSuggestions(new[] + { + "Sort the grid by Total descending.", + "Filter to only show data from July.", + "Show only rows where Units Sold is greater than 130.", + }) + .PromptTextArea(p => p.Rows(2).Resize(TextAreaResize.Auto).MaxRows(5)) + ) + .AIAssistantWindow(ws => ws.Width(558).Actions(a => a.Minimize().Close())) + ) .Sortable() .Filterable() ) - -
- - -
    -
  • Which salesperson has the highest total sales?
  • -
  • What is the average units sold per region?
  • -
  • Show the month with the lowest performance.
  • -
  • Sort the grid by Total descending
  • -
  • Filter to only show data from July
  • -
  • Show only rows where Units Sold is greater than 130
  • -
  • What is the total revenue by month?
  • -
  • How many units did Alice sell in total?
  • -
- - - @(Html.Kendo().TextArea() - .Name("instructionBox") - .Placeholder("e.g. Which region had the lowest total?") - .Rows(4) - .HtmlAttributes(new { style = "width:100%; background-color:#1f1f1f; color:white;", @class = "k-textbox" }) - ) - -
- @(Html.Kendo().Button() - .Name("analyzeButton") - .Content("Analyze") - .ThemeColor(ThemeColor.Success) - .HtmlAttributes(new { onclick = "analyzeGrid()" }) - ) -
-
- -
- AI Response: -
-
- -@section scripts { - -} - -