Skip to content

Commit d78c7d1

Browse files
Merge branch 'development' into 979392-gemini-integration
2 parents ad48ce4 + 4fa2a92 commit d78c7d1

File tree

2 files changed

+389
-0
lines changed

2 files changed

+389
-0
lines changed

blazor-toc.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,13 @@
657657
</ul>
658658
</li>
659659
</ul>
660+
<ul>
661+
<li>Tree Grid
662+
<ul>
663+
<li><a href="/blazor/smart-ai-solutions/ai-samples/treegrid/adaptive-structuring">Adaptive Structuring</a></li>
664+
</ul>
665+
</li>
666+
</ul>
660667
</li>
661668
<li>AI AssistView
662669
<ul>
Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
---
2+
layout: post
3+
title: Data Restructuring with Blazor TreeGrid and AI Models | Syncfusion
4+
description: Learn how to use Syncfusion Blazor TreeGrid with AI service to automatically organize hierarchical data.
5+
platform: Blazor
6+
control: AI Integration
7+
documentation: ug
8+
keywords: Blazor TreeGrid, AI data restructuring, Syncfusion Blazor AI
9+
---
10+
11+
# Data Restructuring with Blazor TreeGrid and Ollama
12+
13+
This guide demonstrates how to use the [**Syncfusion.Blazor.AI**](https://www.nuget.org/packages/Syncfusion.Blazor.AI) package to automatically organize hierarchical data in a Syncfusion Blazor TreeGrid component. The [**Syncfusion.Blazor.AI**](https://www.nuget.org/packages/Syncfusion.Blazor.AI) package enables integration with AI models to process and structure data, while Ollama provides self-hosted or cloud-based AI capabilities for analyzing relationships in datasets. In this example, the application assigns appropriate `ParentId` values based on `CategoryName` relationships, dynamically updating the TreeGrid to reflect the corrected hierarchical structure.
14+
15+
## Prerequisites
16+
17+
Ensure the following NuGet packages are installed based on your chosen AI service:
18+
19+
### For OpenAI
20+
- **Microsoft.Extensions.AI**
21+
- **Microsoft.Extensions.AI.OpenAI**
22+
23+
### For Azure OpenAI
24+
- **Microsoft.Extensions.AI**
25+
- **Microsoft.Extensions.AI.OpenAI**
26+
- **Azure.AI.OpenAI**
27+
28+
### For Ollama
29+
- **Microsoft.Extensions.AI**
30+
- **OllamaSharp**
31+
32+
{% tabs %}
33+
{% highlight C# tabtitle="Package Manager" %}
34+
35+
Install-Package Syncfusion.Blazor.TreeGrid -Version {{ site.releaseversion }}
36+
Install-Package Syncfusion.Blazor.Themes -Version {{ site.releaseversion }}
37+
Install-Package Syncfusion.Blazor.AI -Version {{ site.releaseversion }}
38+
Install-Package Microsoft.Extensions.AI
39+
Install-Package Microsoft.Extensions.AI.OpenAI # For OpenAI or Azure OpenAI
40+
Install-Package Azure.AI.OpenAI # For Azure OpenAI
41+
Install-Package OllamaSharp # For Ollama
42+
43+
{% endhighlight %}
44+
{% endtabs %}
45+
46+
## Add Stylesheet and Script Resources
47+
48+
Include the theme stylesheet and script from NuGet via [Static Web Assets](https://blazor.syncfusion.com/documentation/appearance/themes#static-web-assets) in the `<head>` of your main page:
49+
50+
- For **.NET 6** Blazor Server apps, add to **~/Pages/_Layout.cshtml**.
51+
- For **.NET 8 or .NET 9** Blazor Server apps, add to **~/Components/App.razor**.
52+
53+
```html
54+
<head>
55+
<link href="_content/Syncfusion.Blazor.Themes/tailwind.css" rel="stylesheet" />
56+
</head>
57+
<body>
58+
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
59+
</body>
60+
```
61+
62+
N> Explore the [Blazor Themes](https://blazor.syncfusion.com/documentation/appearance/themes) topic for methods to reference themes ([Static Web Assets](https://blazor.syncfusion.com/documentation/appearance/themes#static-web-assets), [CDN](https://blazor.syncfusion.com/documentation/appearance/themes#cdn-reference), or [CRG](https://blazor.syncfusion.com/documentation/common/custom-resource-generator)). Refer to the [Adding Script Reference](https://blazor.syncfusion.com/documentation/common/adding-script-references) topic for different approaches to adding script references in your Blazor application.
63+
64+
## Configure AI Service
65+
66+
Choose one of the following AI services (OpenAI, Azure OpenAI, or Ollama) based on your requirements:
67+
- **OpenAI**: Best for cloud-based, general-purpose AI models with minimal setup.
68+
- **Azure OpenAI**: Ideal for enterprise-grade deployments with enhanced security and scalability.
69+
- **Ollama**: Suitable for self-hosted, privacy-focused AI models.
70+
71+
Follow the instructions for your selected service to register the AI model in your application.
72+
73+
### OpenAI
74+
75+
Generate an API key from OpenAI and set `openAIApiKey`. Specify the desired model (e.g., `gpt-3.5-turbo`, `gpt-4`) in `openAIModel`.
76+
77+
- Install the required NuGet packages:
78+
79+
{% tabs %}
80+
{% highlight C# tabtitle="Package Manager" %}
81+
82+
Install-Package Microsoft.Extensions.AI
83+
Install-Package Microsoft.Extensions.AI.OpenAI
84+
85+
{% endhighlight %}
86+
{% endtabs %}
87+
88+
- Add the following to the **~/Program.cs** file in your Blazor WebApp:
89+
90+
{% tabs %}
91+
{% highlight C# tabtitle="Blazor WebApp" hl_lines="7 8 9 11 12 13" %}
92+
93+
using Syncfusion.Blazor.AI;
94+
using Microsoft.Extensions.AI;
95+
using OpenAI;
96+
97+
var builder = WebApplication.CreateBuilder(args);
98+
99+
string openAIApiKey = "API-KEY";
100+
string openAIModel = "OPENAI_MODEL";
101+
OpenAIClient openAIClient = new OpenAIClient(openAIApiKey);
102+
IChatClient openAIChatClient = openAIClient.GetChatClient(openAIModel).AsIChatClient();
103+
builder.Services.AddChatClient(openAIChatClient);
104+
builder.Services.AddSingleton<IChatInferenceService, SyncfusionAIService>();
105+
106+
var app = builder.Build();
107+
108+
{% endhighlight %}
109+
{% endtabs %}
110+
111+
### Azure OpenAI
112+
113+
Deploy an Azure OpenAI Service resource and model as described in [Microsoft's documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource). Obtain values for `azureOpenAIKey`, `azureOpenAIEndpoint`, and `azureOpenAIModel`.
114+
115+
- Install the required NuGet packages:
116+
117+
{% tabs %}
118+
{% highlight C# tabtitle="Package Manager" %}
119+
120+
Install-Package Microsoft.Extensions.AI
121+
Install-Package Microsoft.Extensions.AI.OpenAI
122+
Install-Package Azure.AI.OpenAI
123+
124+
{% endhighlight %}
125+
{% endtabs %}
126+
127+
- Add the following to the **~/Program.cs** file in your Blazor WebApp:
128+
129+
{% tabs %}
130+
{% highlight C# tabtitle="Blazor WebApp" hl_lines="7 8 9 11 12 13" %}
131+
132+
using Syncfusion.Blazor.AI;
133+
using Azure.AI.OpenAI;
134+
using Microsoft.Extensions.AI;
135+
using System.ClientModel;
136+
137+
var builder = WebApplication.CreateBuilder(args);
138+
139+
string azureOpenAIKey = "AZURE_OPENAI_KEY";
140+
string azureOpenAIEndpoint = "AZURE_OPENAI_ENDPOINT";
141+
string azureOpenAIModel = "AZURE_OPENAI_MODEL";
142+
AzureOpenAIClient azureOpenAIClient = new AzureOpenAIClient(
143+
new Uri(azureOpenAIEndpoint),
144+
new ApiKeyCredential(azureOpenAIKey)
145+
);
146+
IChatClient azureOpenAIChatClient = azureOpenAIClient.GetChatClient(azureOpenAIModel).AsIChatClient();
147+
builder.Services.AddChatClient(azureOpenAIChatClient);
148+
builder.Services.AddSingleton<IChatInferenceService, SyncfusionAIService>();
149+
150+
var app = builder.Build();
151+
152+
{% endhighlight %}
153+
{% endtabs %}
154+
155+
### Ollama
156+
157+
To use Ollama for self-hosted AI models:
158+
159+
1. **Download and install Ollama**: Visit [Ollama's official website](https://ollama.com) and install the application for your operating system.
160+
2. **Install a model**: Choose a model from the [Ollama Library](https://ollama.com/library) (e.g., `llama2:13b`, `mistral:7b`).
161+
3. **Configure the application**: Provide the `Endpoint` URL (e.g., `http://localhost:11434`) and `ModelName` (e.g., `llama2:13b`).
162+
163+
- Install the required NuGet packages:
164+
165+
{% tabs %}
166+
{% highlight C# tabtitle="Package Manager" %}
167+
168+
Install-Package Microsoft.Extensions.AI
169+
Install-Package OllamaSharp
170+
171+
{% endhighlight %}
172+
{% endtabs %}
173+
174+
- Add the following to the **~/Program.cs** file in your Blazor WebApp:
175+
176+
{% tabs %}
177+
{% highlight C# tabtitle="Blazor WebApp" hl_lines="7 8 9 11 12 13" %}
178+
179+
using Syncfusion.Blazor.AI;
180+
using Microsoft.Extensions.AI;
181+
using OllamaSharp;
182+
183+
var builder = WebApplication.CreateBuilder(args);
184+
185+
string ModelName = "MODEL_NAME";
186+
IChatClient chatClient = new OllamaApiClient("http://localhost:11434", ModelName);
187+
builder.Services.AddChatClient(chatClient);
188+
builder.Services.AddSingleton<IChatInferenceService, SyncfusionAIService>();
189+
190+
var app = builder.Build();
191+
192+
{% endhighlight %}
193+
{% endtabs %}
194+
195+
- **Verify connectivity**: Ensure the Ollama server is running and accessible at the specified endpoint (e.g., `http://localhost:11434`) before starting the application.
196+
197+
## Register Syncfusion Blazor Service
198+
199+
Add the Syncfusion Blazor service to your **~/Program.cs** file. The configuration depends on your app's **Interactive Render Mode**:
200+
201+
- **Server Mode**: Register the service in the single **~/Program.cs** file.
202+
- **WebAssembly or Auto Mode**: Register the service in both the server-side **~/Program.cs** and client-side **~/Program.cs** files.
203+
204+
{% tabs %}
205+
{% highlight C# tabtitle="Server (~/_Program.cs)" hl_lines="3 11" %}
206+
207+
using Syncfusion.Blazor;
208+
209+
var builder = WebApplication.CreateBuilder(args);
210+
211+
builder.Services.AddRazorComponents()
212+
.AddInteractiveServerComponents()
213+
.AddInteractiveWebAssemblyComponents();
214+
builder.Services.AddSyncfusionBlazor();
215+
216+
var app = builder.Build();
217+
218+
{% endhighlight %}
219+
{% highlight C# tabtitle="Client (~/_Program.cs)" hl_lines="2 5" %}
220+
221+
using Syncfusion.Blazor;
222+
223+
var builder = WebAssemblyHostBuilder.CreateDefault(args);
224+
builder.Services.AddSyncfusionBlazor();
225+
226+
await builder.Build().RunAsync();
227+
228+
{% endhighlight %}
229+
{% endtabs %}
230+
231+
## Razor Component (`Home.razor`)
232+
233+
This section implements the Syncfusion Blazor TreeGrid with AI-driven data restructuring using the AI model to assign `ParentId` values based on `CategoryName` relationships.
234+
235+
```csharp
236+
@page "/"
237+
238+
@inject IChatInferenceService AIService
239+
@using Syncfusion.Blazor.TreeGrid
240+
@using Syncfusion.Blazor.Navigations
241+
@using Syncfusion.Blazor.Buttons
242+
@using Syncfusion.Blazor.AI
243+
@using System.Text.Json;
244+
245+
<div style="padding-bottom: 10px;">
246+
<span>@message</span>
247+
</div>
248+
<div style="width: 100%; position: relative">
249+
<SfTreeGrid @ref="TreeGrid" DataSource="@TreeGridData" IdMapping="CategoryId" ParentIdMapping="ParentId" TreeColumnIndex="1">
250+
<TreeGridEditSettings AllowEditing="true" />
251+
<TreeGridColumns>
252+
<TreeGridColumn Field="CategoryId" HeaderText="Category ID" IsPrimaryKey="true" Width="60" TextAlign="Syncfusion.Blazor.Grids.TextAlign.Right"></TreeGridColumn>
253+
<TreeGridColumn Field="CategoryName" HeaderText="Category Name" Width="100"></TreeGridColumn>
254+
<TreeGridColumn Field="Status" HeaderText="Status" Width="70"></TreeGridColumn>
255+
<TreeGridColumn Field="OrderDate" HeaderText="Last Order Date" Format="d" Width="90"></TreeGridColumn>
256+
</TreeGridColumns>
257+
<SfToolbar ID="TreeGrid_AISample_Toolbar">
258+
<ToolbarItems>
259+
<ToolbarItem>
260+
<Template>
261+
<SfButton IsPrimary ID="openAI" @onclick="OpenAIHandler">Smart Data Restructure</SfButton>
262+
</Template>
263+
</ToolbarItem>
264+
</ToolbarItems>
265+
</SfToolbar>
266+
</SfTreeGrid>
267+
</div>
268+
```
269+
270+
`Home.razor.cs`
271+
```csharp
272+
using Microsoft.Extensions.AI;
273+
using Syncfusion.Blazor.AI;
274+
using Syncfusion.Blazor.TreeGrid;
275+
using System.Text.Json;
276+
277+
namespace AISamples.Components.Pages
278+
{
279+
public partial class Home
280+
{
281+
public SfTreeGrid<TreeData.BusinessObject> TreeGrid;
282+
private string AIPrompt = string.Empty;
283+
private string message = string.Empty;
284+
public List<TreeData.BusinessObject> TreeGridData { get; set; }
285+
protected override void OnInitialized()
286+
{
287+
this.TreeGridData = TreeData.GetAdaptiveStructureData().ToList();
288+
}
289+
290+
private async Task OpenAIHandler()
291+
{
292+
await TreeGrid.ShowSpinnerAsync();
293+
List<TreeData.BusinessObject> sortedCollection = new List<TreeData.BusinessObject>();
294+
var AIPrompt = GeneratePrompt(TreeGridData);
295+
ChatParameters chatParameters = new ChatParameters
296+
{
297+
Messages = new List<ChatMessage>
298+
{
299+
new ChatMessage(ChatRole.User, AIPrompt)
300+
}
301+
};
302+
var result = await AIService.GenerateResponseAsync(chatParameters);
303+
result = result.Replace("```json", "").Replace("```", "").Trim();
304+
305+
string response = JsonDocument.Parse(result).RootElement.GetProperty("TreeGridData").ToString();
306+
if (response is not null)
307+
{
308+
sortedCollection = JsonSerializer.Deserialize<List<TreeData.BusinessObject>>(response);
309+
}
310+
if (sortedCollection is not null && sortedCollection.Count > 0)
311+
{
312+
TreeGridData = sortedCollection.Cast<TreeData.BusinessObject>().ToList();
313+
}
314+
else
315+
{
316+
message = "Oops.! Please try Again !";
317+
}
318+
await TreeGrid.HideSpinnerAsync();
319+
await Task.CompletedTask;
320+
}
321+
322+
private string GeneratePrompt(List<TreeData.BusinessObject> TreeGridData)
323+
{
324+
Dictionary<string, IEnumerable<object>> treeData = new Dictionary<string, IEnumerable<object>>();
325+
treeData.Add("TreeGridData", TreeGridData);
326+
var jsonData = JsonSerializer.Serialize(treeData);
327+
return @"I want you to act as a TreeGrid Data Organizer.
328+
Your task is to organize a dataset based on a hierarchical structure using 'CategoryId' and 'ParentId'.
329+
Each item in the dataset has a 'CategoryName' representing categories, and some categories have a null 'ParentId', indicating they are top-level categories.
330+
Your role will be to examine the entire dataset to identify related items based on their 'CategoryName' values and nest them under the appropriate top-level categories by updating their 'ParentId' to match the 'CategoryId' of the corresponding top-level category.
331+
For example, if a category like 'Furniture' exists, you should examine the dataset for items such as 'Chair' and 'Table' and update their 'ParentId' to the 'CategoryId' of 'Furniture'.
332+
The output should be the newly prepared TreeGridData with correctly assigned 'ParentId' values. Please ensure that all subcategories are correctly nested under their respective top-level categories.
333+
Return the newly prepared TreeGridData alone and don't share any other information with the response: Here is the dataset " + jsonData + "/n Note: Return response must be in json string and with no other explanation. ";
334+
}
335+
public class TreeData
336+
{
337+
public class BusinessObject
338+
{
339+
public int CategoryId { get; set; }
340+
public string CategoryName { get; set; }
341+
public string Status { get; set; }
342+
public DateTime OrderDate { get; set; }
343+
public int? ParentId { get; set; }
344+
}
345+
346+
public static List<BusinessObject> GetAdaptiveStructureData()
347+
{
348+
List<BusinessObject> BusinessObjectCollection = new List<BusinessObject>();
349+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 1, CategoryName = "Electronics", Status = "Available", OrderDate = new DateTime(2021, 7, 12), ParentId = null });
350+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 2, CategoryName = "Cell phone", Status = "out of Stock", OrderDate = new DateTime(2021, 6, 17), ParentId = 1 });
351+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 3, CategoryName = "Computer", Status = "Available", OrderDate = new DateTime(2021, 7, 12), ParentId = 7 });
352+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 4, CategoryName = "Cloth", Status = "Available", OrderDate = new DateTime(2021, 10, 5), ParentId = null });
353+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 5, CategoryName = "Silk", Status = "Out of Stock", OrderDate = new DateTime(2021, 9, 2), ParentId = 7 });
354+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 6, CategoryName = "Chair", Status = "Available", OrderDate = new DateTime(2021, 3, 3), ParentId = 1 });
355+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 7, CategoryName = "Furniture", Status = "Available", OrderDate = new DateTime(2021, 3, 5), ParentId = null });
356+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 8, CategoryName = "Bed", Status = "Available", OrderDate = new DateTime(2021, 3, 5), ParentId = 7 });
357+
BusinessObjectCollection.Add(new BusinessObject() { CategoryId = 9, CategoryName = "Fabrics", Status = "Available", OrderDate = new DateTime(2021, 10, 5), ParentId = 4 });
358+
return BusinessObjectCollection;
359+
}
360+
}
361+
}
362+
}
363+
```
364+
365+
## Error Handling and Troubleshooting
366+
367+
If the AI service fails to return a valid response, the TreeGrid will display an error message ("Oops! Please try again!"). Common issues include:
368+
369+
- **Invalid API Key or Endpoint**: Verify that the `openAIApiKey`, `azureOpenAIKey`, or Ollama `Endpoint` is correct and the service is accessible.
370+
- **Model Unavailable**: Ensure the specified `openAIModel`, `azureOpenAIModel`, or `ModelName` is deployed and supported.
371+
- **Network Issues**: Check connectivity to the AI service endpoint, especially for self-hosted Ollama instances.
372+
- **Large Datasets**: Processing large datasets may cause timeouts. Consider batching data or optimizing the prompt for efficiency.
373+
374+
## Performance Considerations
375+
376+
When handling large datasets, ensure the Ollama server has sufficient resources (CPU/GPU) to process requests efficiently. For datasets exceeding 10,000 records, consider splitting the data into smaller batches to avoid performance bottlenecks. Test the application with your specific dataset to determine optimal performance.
377+
378+
## Sample Code
379+
380+
A complete working example is available in the [Syncfusion Blazor AI Samples GitHub repository](https://github.com/syncfusion/smart-ai-samples).
381+
382+
![Smart Structuring - Output](../../ai/images/adaptive-datastructuring.gif)

0 commit comments

Comments
 (0)