0

I'm trying out Microsoft's Semantic Kernel for chat completion in a Blazor app. I added a service that uses EF Core:

public interface ISearchService
{
    Task<string?> GetCustomerAsync(string surname);
}

This is the interface. The implementation is straightforward. I then created a plugin class:

[Description("Representats customer data")]
public class SearchPlugin(ISearchService searchService)
{
    [KernelFunction("GetCustomer"), Description("Get customer details by their surname")]
    [return: Description("Customer details")]
    public async Task<string?> GetCustomer([Description("Customer surname")] string surname)
        => await searchService.GetCustomerAsync(surname);
}

I register the service as Scoped:

services.AddScoped<ISearchService, SearchService>();

And register the kernel:

services.AddSemanticKernel(configuration)
    .Plugins.AddFromType<SearchPlugin>();

Where AddSemanticKernel is an extension method:

public static IKernelBuilder AddSemanticKernel(this IServiceCollection services, IConfiguration configuration)
{
    var modelId = "llama3.2:3b";
    var endpoint = new Uri("http://localhost:11424");

    services.AddOllamaChatCompletion(modelId, endpoint);

    return services.AddKernel();
}

However, when I start the app, I get the following exception:

System.InvalidOperationException: Cannot resolve scoped service 'MyApp.Services.Interfaces.ISearchService' from root provider.

What am I doing wrong?

2
  • provide serviceProvider directly, I have something like: kernel.Plugins.AddFromType<TesterTools>(pluginName: "Tester", serviceProvider: sp) Commented Aug 24 at 16:44
  • 1
    i think it's services.AddKernel().AddOllamaChatCompletion() Commented Aug 25 at 10:02

2 Answers 2

0

Unforutnately, plugins and Kernel have own DI system, separated from the application one.

So you need to actually register types you want to use in plugins with KernelBuilder:

var kernel = services.AddKernel();
kernel.Services.AddScoped<ISearchService, SearchService>();
return kernel;

Here's related GitHub discussion

There's another GitHub issue, suggesting you could create Kernel with application's service provider:

services.AddSingleton<Kernel>(serviceProvider =>
{
    Kernel k = new(serviceProvider);
    k.Plugins.AddFromType<SearchPlugin>();
    return k;
});
Sign up to request clarification or add additional context in comments.

Comments

0

As pointed by @Michał Turczyn, the Kernel has own DI collection, but combining them easy to do for example with AddKernel method:

using var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // Model & key
        var openAiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");

        // Register Semantic Kernel via IServiceCollection
        var kernelBuilder = services.AddKernel();
        kernelBuilder.AddOpenAIChatCompletion(modelId: "gpt-4o-mini", apiKey: openAiKey);
        kernelBuilder.Plugins.AddFromType<CodeGenTool>(); // expose your tool
        // use a regular DI
        services.AddScoped<ISearchService, MockSearchService>();
    })
    .Build();

since AddKernel provides regular DI collection as argument to KernelBuilder:

public static IKernelBuilder AddKernel(this IServiceCollection services)
{
    services.AddTransient<KernelPluginCollection>();
    services.AddTransient<Kernel>();
    return new KernelBuilder(services);
}

where CodeGenTool is:

public class CodeGenTool(ISearchService searchService)
...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.