Skgen 0.0.10

dotnet add package Skgen --version 0.0.10
                    
NuGet\Install-Package Skgen -Version 0.0.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Skgen" Version="0.0.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Skgen" Version="0.0.10" />
                    
Directory.Packages.props
<PackageReference Include="Skgen" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Skgen --version 0.0.10
                    
#r "nuget: Skgen, 0.0.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Skgen@0.0.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Skgen&version=0.0.10
                    
Install as a Cake Addin
#tool nuget:?package=Skgen&version=0.0.10
                    
Install as a Cake Tool

What this package does

This is a source generator which finds Semantic Kernel plugins and generates helper static extension methods for calling them with all the right inputs.

Semantic Kernel plugins

Semantic Kernel plugins are stringly-typed, and it's easy to forget a variable or two when calling them:

A typical Semantic Kernel project defines its prompt-based plugins in a folder called Plugins:

.
├── Plugins/
│   ├── Summarize/
│   │   └── SummarizeText/
│   │       ├── config.json
│   │       └── skprompt.txt
│   └── Assistant/
│       └── GetResponse/
│           ├── config.json
│           └── skprompt.txt
└── Program.cs

A typical config.json file looks like this:

{
  "schema": 1,
  "type": "completion",
  "description": "Gives helpful responses using snippets of relevant information",
  "completion": {
    "max_tokens": 500,
    "temperature": 0.5,
    "top_p": 0.0,
    "presence_penalty": 0.0,
    "frequency_penalty": 0.0
  },
  "input": {
    "parameters": [
      {
        "name": "prompt",
        "description": "The user's prompt",
        "defaultValue": ""
      },
      {
        "name": "snippet0",
        "description": "The most relevant snippet found from documents",
        "defaultValue": ""
      },
      {
        "name": "snippet1",
        "description": "The second most relevant snippet found from documents",
        "defaultValue": ""
      },
      {
        "name": "snippet2",
        "description": "The third most relevant snippet found from documents",
        "defaultValue": ""
      }
    ]
  }
}

This source generator goes through and finds every file called config.json and generates static extension methods for Microsoft.SemanticKernel.Kernel that look like this:

// <auto-generated/>
using System;
using Microsoft.SemanticKernel;

namespace Skgen;

public static partial class KernelExtensionMethods
{
    
    public static async Task<FunctionResult> AssistantGetResponseAsync(this Kernel kernel, string prompt = "", string snippet0 = "", string snippet1 = "", string snippet2 = "", CancellationToken cancellationToken = default(CancellationToken))
    {
        var arguments = new KernelArguments();
        arguments["prompt"] = prompt;
		arguments["snippet0"] = snippet0;
		arguments["snippet1"] = snippet1;
		arguments["snippet2"] = snippet2;
    
        var answer = await kernel.InvokeAsync("Assistant", "GetResponse", arguments, cancellationToken);
        return answer;
    }

    public static async Task<FunctionResult> SummarizeSummarizeWithContextAsync(this Kernel kernel, string input = "", string fact1 = "", string fact2 = "", string fact3 = "", CancellationToken cancellationToken = default(CancellationToken))
    {
        var arguments = new KernelArguments();
        arguments["input"] = input;
		arguments["fact1"] = fact1;
		arguments["fact2"] = fact2;
		arguments["fact3"] = fact3;
    
        var answer = await kernel.InvokeAsync("Summarize", "SummarizeWithContext", arguments, cancellationToken);
        return answer;
    }
}

Getting started

Install the package

dotnet add package Skgen

Adjust your package's csproj

By default, the source generated code is not persisted to disk. In order to persist it to a file called Generated, you can add this to your csproj:

<PropertyGroup>
        <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
        <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
    <Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
</ItemGroup>

Thank you to Andrew Lock for describing this solution!

Reasoning

The point of <Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" /> is to avoid compiling the source generated files after they have been spit out to disk and hence double compiling the same thing and hitting errors like this `Error CS0111: Type 'KernelExtensionMethods' already defines a member called '' with the same parameters.

Error CS0111: Type 'KernelExtensionMethods' already defines a member called '' with the same parameters

Drawbacks

Despite my best effort, I haven't gotten intellisense in Rider, Visual Studio or Visual Studio code to respect these new extension methods without removing <Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" /> and hence breaking compilation when you build the second time😔. If you figure this out, please let me know!

Intellisense shows red squiggles on the new methods even though they work

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.10 226 1/28/2024
0.0.9 154 1/28/2024
0.0.8 211 1/28/2024