|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Using Azure OpenAI with Syncfusion Blazor AI | Syncfusion |
| 4 | +description: Learn how to set up and use Syncfusion.Blazor.AI with Azure OpenAI for AI-powered features in your Blazor apps, including configuration and examples. |
| 5 | +platform: Blazor |
| 6 | +control: AI Integration |
| 7 | +documentation: ug |
| 8 | +--- |
| 9 | + |
| 10 | +# Using Azure OpenAI with Syncfusion Blazor AI package |
| 11 | + |
| 12 | +This section helps to configuring and using the **Syncfusion.Blazor.AI** package with **Azure OpenAI** to enable AI functionalities in your Blazor applications. The package provides seamless integration with Azure OpenAI's API, allowing you to enhance any Syncfusion Blazor component with intelligent features. |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | +- Install the following NuGet packages: |
| 16 | + - `Syncfusion.Blazor.AI` |
| 17 | + - `Azure.AI.OpenAI` |
| 18 | +- For **Azure OpenAI**, first [deploy an Azure OpenAI Service resource and model](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource), then values for `apiKey`, `deploymentName` and `endpoint` will all be provided to you. |
| 19 | +- Ensure your Blazor application meets the [System Requirements](https://blazor.syncfusion.com/documentation/system-requirements). |
| 20 | + |
| 21 | +## Configuration |
| 22 | +To use Azure OpenAI, configure the AI service in your `Program.cs` file by registering the `AIServiceCredentials` and `IChatInferenceService`. |
| 23 | + |
| 24 | +### Steps |
| 25 | +1. Open your Blazor application's `Program.cs`. |
| 26 | +2. Add the following code to configure Azure OpenAI credentials: |
| 27 | + |
| 28 | +```csharp |
| 29 | +builder.Services.AddSingleton(new AIServiceCredentials |
| 30 | +{ |
| 31 | + ApiKey = "your-azure-openai-key", // Replace with your Azure OpenAI API key |
| 32 | + DeploymentName = "your-deployment-name", // Specify the Azure OpenAI deployment name |
| 33 | + Endpoint = new Uri("https://your-openai.azure.com/") // Replace with your Azure OpenAI endpoint |
| 34 | +}); |
| 35 | + |
| 36 | +// Register the inference backend |
| 37 | +builder.Services.AddSingleton<IChatInferenceService, SyncfusionAIService>(); |
| 38 | +``` |
| 39 | + |
| 40 | +3. Ensure the required Syncfusion Blazor namespaces are included in your `Program.cs`: |
| 41 | +```csharp |
| 42 | +using Syncfusion.Blazor.AI; |
| 43 | +``` |
| 44 | + |
| 45 | +## Example: Syncfusion Query Builder with Azure OpenAI in a Blazor Application |
| 46 | + |
| 47 | +This example demonstrates using the **Syncfusion.Blazor.AI** package with **Azure OpenAI** to enable natural language querying in a Blazor application. The application features a Syncfusion Tab component with a textarea for entering natural language queries, a QueryBuilder component to visualize the generated query rules, and a Grid component to display filtered results based on the query processed by Azure OpenAI. |
| 48 | + |
| 49 | +### Prerequisites |
| 50 | +- Install the following NuGet packages: |
| 51 | + - `Syncfusion.Blazor.Grid` |
| 52 | + - `Syncfusion.Blazor.Themes` |
| 53 | + - `Syncfusion.Blazor.AI` |
| 54 | + - `Syncfusion.Blazor.QueryBuilder` |
| 55 | + - `Azure.AI.OpenAI` |
| 56 | +- Ensure your Blazor application meets the [System Requirements](https://blazor.syncfusion.com/documentation/system-requirements). |
| 57 | +- Add the following to `App.razor` for Syncfusion themes and scripts: |
| 58 | + |
| 59 | +```html |
| 60 | +<head> |
| 61 | + .... |
| 62 | + <link href="_content/Syncfusion.Blazor.Themes/tailwind.css" rel="stylesheet" /> |
| 63 | +</head> |
| 64 | + |
| 65 | +<body> |
| 66 | + .... |
| 67 | + <script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script> |
| 68 | +</body> |
| 69 | +``` |
| 70 | + |
| 71 | +Now, register the Syncfusion<sup style="font-size:70%">®</sup> Blazor Service in the **~/Program.cs** file of your Blazor WebAssembly App. |
| 72 | + |
| 73 | +{% tabs %} |
| 74 | +{% highlight C# tabtitle="~/Program.cs" hl_lines="3 11" %} |
| 75 | + |
| 76 | +using Microsoft.AspNetCore.Components.Web; |
| 77 | +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
| 78 | +using Syncfusion.Blazor; |
| 79 | + |
| 80 | +var builder = WebAssemblyHostBuilder.CreateDefault(args); |
| 81 | +builder.RootComponents.Add<App>("#app"); |
| 82 | +builder.RootComponents.Add<HeadOutlet>("head::after"); |
| 83 | + |
| 84 | +builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); |
| 85 | + |
| 86 | +builder.Services.AddSyncfusionBlazor(); |
| 87 | +await builder.Build().RunAsync(); |
| 88 | +.... |
| 89 | + |
| 90 | +{% endhighlight %} |
| 91 | +{% endtabs %} |
| 92 | + |
| 93 | +### Razor Component (`Home.razor`) |
| 94 | +```csharp |
| 95 | +@page "/" |
| 96 | + |
| 97 | +@using Syncfusion.Blazor.QueryBuilder |
| 98 | +@using Syncfusion.Blazor.Navigations |
| 99 | +@using Syncfusion.Blazor.Grids |
| 100 | +@using Syncfusion.Blazor.Buttons |
| 101 | +@using Syncfusion.Blazor.Spinner |
| 102 | +@using Syncfusion.Blazor.AI |
| 103 | +@inject IChatInferenceService AzureAIService |
| 104 | + |
| 105 | +<title>Syncfusion - Smart Natural Language Querying</title> |
| 106 | +<SfTab LoadOn="ContentLoad.Init"> |
| 107 | + <TabItems> |
| 108 | + <TabItem> |
| 109 | + <ChildContent> |
| 110 | + <TabHeader Text="Natural Language Query"></TabHeader> |
| 111 | + </ChildContent> |
| 112 | + <ContentTemplate> |
| 113 | + <span class="e-text">Query</span> |
| 114 | + <textarea id="text-area" @bind="TextAreaValue" placeholder="Find all users who lives in California and have over 500 credits"></textarea> |
| 115 | + </ContentTemplate> |
| 116 | + </TabItem> |
| 117 | + <TabItem> |
| 118 | + <ChildContent> |
| 119 | + <TabHeader Text="QueryBuilder UI"></TabHeader> |
| 120 | + </ChildContent> |
| 121 | + <ContentTemplate> |
| 122 | + <SfQueryBuilder Readonly="true" TValue="User" @ref="QueryBuilderObj" DataSource="@DataSource"> |
| 123 | + <QueryBuilderColumns> |
| 124 | + <QueryBuilderColumn Field="id" Label="ID" Type="Syncfusion.Blazor.QueryBuilder.ColumnType.Number"></QueryBuilderColumn> |
| 125 | + <QueryBuilderColumn Field="name" Label="Name" Type="Syncfusion.Blazor.QueryBuilder.ColumnType.String"></QueryBuilderColumn> |
| 126 | + <QueryBuilderColumn Field="email" Label="Email" Type="Syncfusion.Blazor.QueryBuilder.ColumnType.String"></QueryBuilderColumn> |
| 127 | + <QueryBuilderColumn Field="address" Label="Address" Type="Syncfusion.Blazor.QueryBuilder.ColumnType.Boolean"></QueryBuilderColumn> |
| 128 | + <QueryBuilderColumn Field="city" Label="City" Type="Syncfusion.Blazor.QueryBuilder.ColumnType.String"></QueryBuilderColumn> |
| 129 | + <QueryBuilderColumn Field="state" Label="State" Type="Syncfusion.Blazor.QueryBuilder.ColumnType.String"></QueryBuilderColumn> |
| 130 | + <QueryBuilderColumn Field="credits" Label="Credits" Type="Syncfusion.Blazor.QueryBuilder.ColumnType.Number"></QueryBuilderColumn> |
| 131 | + </QueryBuilderColumns> |
| 132 | + </SfQueryBuilder> |
| 133 | + </ContentTemplate> |
| 134 | + </TabItem> |
| 135 | + </TabItems> |
| 136 | +</SfTab> |
| 137 | +<div class="e-custom-elem"> |
| 138 | + <SfButton Content="Run Query" CssClass="e-primary" IconCss="e-icons e-play" @onclick="GenBtnClick"></SfButton> |
| 139 | +</div> |
| 140 | +<div class="e-custom-elem"> |
| 141 | + <span class="e-text">Results</span> |
| 142 | + <SfGrid TValue="User" DataSource="@GridData" AllowPaging="true"> |
| 143 | + <SfSpinner @bind-Visible="@VisibleProperty"></SfSpinner> |
| 144 | + <GridEvents Created="GridCreated" TValue="User"></GridEvents> |
| 145 | + <GridColumns> |
| 146 | + <GridColumn Field=@nameof(User.id) HeaderText="ID" TextAlign="TextAlign.Right"></GridColumn> |
| 147 | + <GridColumn Field=@nameof(User.name) HeaderText="Name"></GridColumn> |
| 148 | + <GridColumn Field=@nameof(User.email) HeaderText="Email" TextAlign="TextAlign.Right"></GridColumn> |
| 149 | + <GridColumn Field=@nameof(User.address) HeaderText="Address"></GridColumn> |
| 150 | + <GridColumn Field=@nameof(User.city) HeaderText="City"></GridColumn> |
| 151 | + <GridColumn Field=@nameof(User.state) HeaderText="State"></GridColumn> |
| 152 | + <GridColumn Field=@nameof(User.credits) HeaderText="Credits"></GridColumn> |
| 153 | + </GridColumns> |
| 154 | + </SfGrid> |
| 155 | +</div> |
| 156 | + |
| 157 | +<style> |
| 158 | + #container { |
| 159 | + margin: 10px; |
| 160 | + border: 1px solid lightgray; |
| 161 | + border-radius: 4px; |
| 162 | + } |
| 163 | + #container .e-tab { |
| 164 | + margin-top: 16px; |
| 165 | + } |
| 166 | + .e-tab .e-content { |
| 167 | + padding: 16px; |
| 168 | + } |
| 169 | + #text-area { |
| 170 | + width: 100%; |
| 171 | + height: 100px; |
| 172 | + margin-top: 5px; |
| 173 | + margin-bottom: 0px; |
| 174 | + padding: 10px; |
| 175 | + border: 1px solid #ccc; |
| 176 | + border-radius: 4px; |
| 177 | + resize: none; |
| 178 | + } |
| 179 | + .e-text { |
| 180 | + font-weight: bold; |
| 181 | + font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", sans-serif; |
| 182 | + font-size: 14px; |
| 183 | + } |
| 184 | + .e-custom-elem { |
| 185 | + margin-bottom: 16px; |
| 186 | + margin-left: 16px; |
| 187 | + width: calc(100% - 32px); |
| 188 | + } |
| 189 | +</style> |
| 190 | +``` |
| 191 | + |
| 192 | +(`Home.razor.cs`) |
| 193 | +```csharp |
| 194 | +using Microsoft.Extensions.AI; |
| 195 | +using Syncfusion.Blazor.AI; |
| 196 | +using Syncfusion.Blazor.QueryBuilder; |
| 197 | + |
| 198 | +namespace AzureOpenAIExample.Components.Pages |
| 199 | +{ |
| 200 | + public partial class Home |
| 201 | + { |
| 202 | + public bool VisibleProperty = false; |
| 203 | + public class User |
| 204 | + { |
| 205 | + public int id { get; set; } |
| 206 | + public string name { get; set; } |
| 207 | + public string email { get; set; } |
| 208 | + public string address { get; set; } |
| 209 | + public string city { get; set; } |
| 210 | + public string state { get; set; } |
| 211 | + public int credits { get; set; } |
| 212 | + } |
| 213 | + private static readonly string[] Names = { "John", "Jane", "Bob", "Alice", "Tom", "Sally", "Jim", "Mary", "Peter", "Nancy" }; |
| 214 | + private static readonly string[] Cities = { "Los Angeles", "San Diego", "New York", "Chicago", "Houston", "Phoenix", "Philadelphia", "San Antonio", "Dallas", "San Jose" }; |
| 215 | + private static readonly string[] States = { "California", "New York", "Illinois", "Texas", "Arizona", "Pennsylvania" }; |
| 216 | + private static readonly string[] Streets = { "Elm St", "Oak St", "Maple Ave", "Pine St", "Cedar St", "Birch St" }; |
| 217 | + private static readonly string[] Emails = { "example.com", "test.com", "demo.com" }; |
| 218 | + |
| 219 | + public static List<User> GenerateRandomUsers(int count) |
| 220 | + { |
| 221 | + var random = new Random(); |
| 222 | + var users = new List<User>(); |
| 223 | + |
| 224 | + for (int i = 0; i < count; i++) |
| 225 | + { |
| 226 | + var id = i + 1; |
| 227 | + var name = Names[random.Next(Names.Length)]; |
| 228 | + var email = $"{name.ToLower()}{id}@{Emails[random.Next(Emails.Length)]}"; |
| 229 | + var address = $"{random.Next(10000)} {Streets[random.Next(Streets.Length)]}"; |
| 230 | + var city = Cities[random.Next(Cities.Length)]; |
| 231 | + var state = States[random.Next(States.Length)]; |
| 232 | + var credits = random.Next(2001); |
| 233 | + |
| 234 | + users.Add(new User |
| 235 | + { |
| 236 | + id = id, |
| 237 | + name = name, |
| 238 | + email = email, |
| 239 | + address = address, |
| 240 | + city = city, |
| 241 | + state = state, |
| 242 | + credits = credits |
| 243 | + }); |
| 244 | + } |
| 245 | + |
| 246 | + return users; |
| 247 | + } |
| 248 | + |
| 249 | + List<User> Users = GenerateRandomUsers(7); |
| 250 | + |
| 251 | + private string TextAreaValue { get; set; } = "Find all users who lives in Los Angeles and have over 500 credits"; |
| 252 | + SfQueryBuilder<User> QueryBuilderObj; |
| 253 | + private IEnumerable<User> GridData { get; set; } |
| 254 | + private IEnumerable<User> DataSource { get; set; } |
| 255 | + protected override void OnInitialized() |
| 256 | + { |
| 257 | + DataSource = Users; |
| 258 | + } |
| 259 | + private void GridCreated() |
| 260 | + { |
| 261 | + GridData = DataSource; |
| 262 | + } |
| 263 | + |
| 264 | + private async void GenBtnClick() |
| 265 | + { |
| 266 | + VisibleProperty = true; |
| 267 | + string prompt = "Create an SQL query to achieve the following task: " + TextAreaValue + " from a single table. Focus on constructing a valid SQL query that directly addresses the specified task, ensuring it adheres to standard SQL syntax for querying a single table. NOTE: Return only the SQL query without any additional explanation or commentary. The response should contain the query itself, formatted correctly and ready for execution."; |
| 268 | + |
| 269 | + ChatParameters chatParameters = new ChatParameters |
| 270 | + { |
| 271 | + Messages = new List<ChatMessage> |
| 272 | + { |
| 273 | + new ChatMessage(ChatRole.User, prompt) |
| 274 | + } |
| 275 | + }; |
| 276 | + string result = await AzureAIService.GenerateResponseAsync(chatParameters); |
| 277 | + |
| 278 | + string value = result.Split("WHERE ")[1].Split(";\n")[0]; |
| 279 | + value = value.Replace("\n", " "); |
| 280 | + value = value.Replace(";", ""); |
| 281 | + QueryBuilderObj.SetRulesFromSql(value); |
| 282 | + GridData = QueryBuilderObj.GetFilteredRecords().ToList().AsEnumerable<User>(); |
| 283 | + StateHasChanged(); |
| 284 | + VisibleProperty = false; |
| 285 | + } |
| 286 | + } |
| 287 | +} |
| 288 | +``` |
| 289 | + |
| 290 | + |
| 291 | + |
| 292 | +### Explanation |
| 293 | +- **IChatInferenceService**: Injected to interact with the OpenAI service. |
| 294 | +- **ChatParameters**: Configures the AI request, including system and user messages, temperature, and token limits. |
| 295 | +- **GenerateResponseAsync**: Sends the request to OpenAI and retrieves the response asynchronously. |
| 296 | +- **Response**: Displays the AI-generated text. |
| 297 | + |
0 commit comments