semantic-kernelsemantic-kernel-plugins

How to make Semantic Kernel look up information on website?


I know that I can use the WebSearchEnginePlugin to make Semantic Kernel look up general information by using Fx the Bing or Google Connector like this:

kernel.ImportPluginFromObject(new WebSearchEnginePlugin(new BingConnector("SECRET")));

But how can I make Semantic Kernel look up information on a specific website? Let's say I want it to go to fx a canteen website like this https://gn.foodbycoor.dk/lautrupbjerg-6/en/weekmenu so it can tell me what's for lunch tomorrow?

Maybe I should create a KernelFunction that does the lppkup and return the menu of the given day?

EDIT: My solution, inspired by jeb's answer https://stackoverflow.com/a/78705767/2787333. It gets all the data from html and json files and can answer what the menu is, when the canteen is open and who the staff is. I'll post it on GitHub soon.

kernel.ImportPluginFromType<GetCanteenPlugin>(); 
var settings = new OpenAIPromptExecutionSettings() {ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions}; 
var chatService = kernel.GetRequiredService<IChatCompletionService>();
var chatHistory = new ChatHistory();
while (true)
{
    Console.Write("Q: ");
    chatHistory.AddUserMessage(Console.ReadLine());
    var answer = await chatService.GetChatMessageContentAsync(chatHistory, settings, kernel);
    Console.WriteLine($"A: {answer}");
    chatHistory.Add(answer);
}

class GetCanteenPlugin
{
    [KernelFunction]
    public string GetMenu() {
        var htmlDoc = new HtmlDocument();
        htmlDoc.Load("CanteenWebsite/Menu.html");
        return htmlDoc.Text;
    }

    [KernelFunction]
    public string GetOpeningHours() {
        var htmlDoc = new HtmlDocument();
        htmlDoc.Load("CanteenWebsite/OpeningHours.html");
        return htmlDoc.Text;
    }
    
    [KernelFunction]
    public string GetStaff() {
        var staff = File.ReadAllText("CanteenWebsite/Staff.json");
        return staff;
    }
}

Solution

  • You can define a Plugin to get the information from the website an pass it to the LLM.

    var kernelBuilder = Kernel.CreateBuilder();
    var kernel = kernelBuilder
        .AddHuggingFaceChatCompletion(
            "phi3",
            new Uri("http://localhost:11434"),
            apiKey: null)
        .Build();
    
    kernel.Plugins.AddFromType<GetMenuPlugin>("MenuPlugin");
    
    var menu = await kernel.Plugins.GetFunction("MenuPlugin", "get_menu")
        .InvokeAsync(kernel);
    
    Console.WriteLine(menu);
    
    ChatHistory chatHistory = new ChatHistory("The menu is:\n" + menu);
    chatHistory.AddUserMessage("What is the menu for thursday? Make a short answer");
    
    IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
    var result = await chatCompletionService.GetChatMessageContentAsync(chatHistory);
    
    Console.WriteLine("Answer:");
    Console.WriteLine(result);
    

    Plugin:

    public class GetMenuPlugin
    {
        private readonly HttpClient _httpClient = new();
    
        [KernelFunction("get_menu")]
        [Description("Gets the menu for each day from the website")]
        [return: Description("website as string")]
        public async Task<string> GetMenuAsync()
        {
            var response = await _httpClient.GetStringAsync("https://gn.foodbycoor.dk/lautrupbjerg-6/en/weekmenu");
    
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(response);
    
            // Parse the HTML to find the div with id 'new-two-week-menu' using HtmlAgilityPack
            var menuNode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='new-two-week-menu']");
            if (menuNode != null)
            {
                return menuNode.InnerText.Replace("\t", "").Trim();
            }
    
            return "Menu not found";
        }
    }
    

    Packages used:

      <ItemGroup>
        <PackageReference Include="HtmlAgilityPack" Version="1.11.61" />
        <PackageReference Include="Microsoft.SemanticKernel" Version="1.15.1" />
        <PackageReference Include="Microsoft.SemanticKernel.Connectors.HuggingFace" Version="1.15.1-preview" />
      </ItemGroup>