Custom AI Service Integration

17 Jul 20268 minutes to read

Overview

Syncfusion Smart PDF Viewer provides built-in support for OpenAI and Azure OpenAI services. It can also connect to other AI providers through the IChatInferenceService interface, which acts as a bridge between the viewer and a custom AI service.

IChatInferenceService Interface

The IChatInferenceService interface defines a simple contract for AI service integration:

using Syncfusion.Blazor.AI;

public interface IChatInferenceService
{
    Task<string> GenerateResponseAsync(ChatParameters options);
}

This interface enables:

  • Consistent communication between components and AI services.
  • Easy switching between different AI providers.

Implemented AI Services

The following examples demonstrate AI services integrated using the IChatInferenceService interface:

Service Documentation
DeepSeek DeepSeek Integration
Gemini Gemini Integration
Groq Groq Integration

Service Registration

Register the custom implementation in Program.cs:

using Syncfusion.Blazor.AI;
builder.Services.AddSingleton<IChatInferenceService, YourCustomService>();

Handling Errors in a Custom AI Service

Because a custom AI service operates independently of the built-in providers, error popups must be handled at the sample level. Capture errors with try-catch in the request/response flow. Propagate the message to the Smart PDF Viewer component, and display it in a dialog to mirror the built-in behavior. For production scenarios, surface user-friendly messages while logging technical details.

Capture Errors in the Custom Service

Use try-catch to capture exceptions during request creation or response handling. Assign the message to the DialogMessage property and raise OnDialogOpen to notify listening components to render the dialog. Consider mapping low-level exceptions to localized, user-friendly text.

Step 1: Create an ErrorDialogService

  1. Create a new class file named ErrorDialogService.cs in the project’s root folder.
  2. Add the following implementation:
public class ErrorDialogService
{
    public event Action OnDialogOpen;

    public string DialogMessage { get; set; }

    internal void RaiseDialogOpen()
    {
        OnDialogOpen?.Invoke();
    }
}

Step 2: Add the ErrorDialogService to the MyCustomService class

  1. Open the MyCustomService.cs file that implements IChatInferenceService. If you do not have one yet, see the Gemini or Groq examples for a full implementation.
  2. Add the ErrorDialogService dependency and update the GenerateResponseAsync method as shown:
private readonly ErrorDialogService _errorDialogService;

 public MyCustomService(IChatClient client,ErrorDialogService errorDialogService)
 {
    // initialize your chat client instance
    this._errorDialogService = errorDialogService ?? throw new ArgumentNullException(nameof(errorDialogService));
 }

 public async Task<string> GenerateResponseAsync(ChatParameters options)
    {
        //Add completion request
        try
        {
            // Add the request logic for the Custom AI service.
        }
        catch (Exception ex)
        {
            _errorDialogService.DialogMessage = ex.Message; // Set the value
            _errorDialogService.RaiseDialogOpen();
            return "";
        }
    }

Step 3: Configure the Dialog Service

Configure services in Program.cs to enable error display when a request or response to the custom AI service fails. This setup ensures any errors encountered during communication can be surfaced via a dialog component.

builder.Services.AddScoped<ErrorDialogService>();
builder.Services.AddScoped<SfDialogService>();
builder.Services.AddScoped<IChatInferenceService, MyCustomService>(sp =>
{
    ErrorDialogService errorDialogService = sp.GetRequiredService<ErrorDialogService>();
    return new MyCustomService( "YourChatclient" ,errorDialogService );
});

Step 4: Add the SfDialogProvider in ~Pages/Home.razor file.

Add @using Syncfusion.Blazor.Popups to ~/_Imports.razor so the dialog types resolve, then update ~/Pages/Home.razor:

@page "/"

<Syncfusion.Blazor.Popups.SfDialogProvider/>
@* Add Smart PDF Viewer Component *@

Step 5: Show the Error Dialog

In the Smart PDF Viewer, error messages are displayed using SfDialogService. The page subscribes to OnDialogOpen from the custom service. When the event fires, the OpenDialog method computes a dialog size based on message length and shows the alert. The subscription is disposed when the component is no longer in use.

  1. Create a new class file named Home.razor.cs by right-clicking the Pages folder, then selecting Add → Class.
  2. Add the following implementation:
using Microsoft.AspNetCore.Components;
using Syncfusion.Blazor.Popups;

public partial class Home : IDisposable
{
    [Inject]
    public ErrorDialogService? ErrorDialogService { get; set; }

    [Inject]
    public SfDialogService? DialogService { get; set; }

    private string? DialogText { get; set; }

    public async void OpenDialog()
    {
        DialogText = ErrorDialogService!.DialogMessage;
        int fontSize = 16; // px
        int charWidth = (int)(fontSize * 0.6); // Approximate width per character in px
        int baseWidth = 48; // Common addition to width
        int baseHeight = 140; // Additional height

        int textLength = DialogText?.Length ?? 0;
        int calculatedWidth = (textLength * charWidth) + baseWidth;
        int calculatedHeight = fontSize * 2 + baseHeight; // 2 lines minimum + base

        int minWidth = 400;
        int maxWidth = 500;

        string width = $"{Math.Clamp(calculatedWidth, minWidth, maxWidth)}px";
        string height = calculatedWidth > maxWidth ? $"{calculatedHeight + 19.2}px" : $"{calculatedHeight}px";

        await DialogService.AlertAsync(DialogText, "Custom service exception", new DialogOptions()
        {
            ShowCloseIcon = true,
            Width = width,
            Height = height
        });
    }

    protected override void OnInitialized()
    {
        ErrorDialogService!.OnDialogOpen += OpenDialog;
    }

    public void Dispose()
    {
        ErrorDialogService!.OnDialogOpen -= OpenDialog;
    }
}

NOTE

View sample in GitHub

See also