Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve code consistency, CancellationToken support, and add skonsole.sln solution file #22

Merged
merged 2 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ dotnet_diagnostic.CA1508.severity = warning # Avoid dead conditional code
dotnet_diagnostic.CA1852.severity = warning # Sealed classes
dotnet_diagnostic.CA1859.severity = warning # Use concrete types when possible for improved performance
dotnet_diagnostic.CA1860.severity = warning # Prefer comparing 'Count' to 0 rather than using 'Any()', both for clarity and for performance
dotnet_diagnostic.CA2016.severity = warning # Forward the 'CancellationToken' parameter to methods that take one
dotnet_diagnostic.CA2000.severity = warning # Call System.IDisposable.Dispose on object before all references to it are out of scope

dotnet_diagnostic.IDE0001.severity = warning # Simplify name
Expand Down
4 changes: 2 additions & 2 deletions apps/SKonsole/Commands/PromptChatCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private static async Task RunPromptChat(CancellationToken token, ILogger logger)
{
var kernel = KernelProvider.Instance.Get();

const string skPrompt = @"
const string SkPrompt = @"
You are a prompt generation robot. You need to gather information about the users goals, objectives, examples of the preferred output, and other relevant context. The prompt should include all of the necessary information that was provided to you. Ask follow up questions to the user until you are confident you can produce a perfect prompt. Your return should be formatted clearly and optimized for GPT models. Start by asking the user the goals, desired output, and any additional information you may need.

{{$history}}
Expand All @@ -56,7 +56,7 @@ private static async Task RunPromptChat(CancellationToken token, ILogger logger)
StopSequences = new List<string> { "Human:", "AI:" },
}
};
var promptTemplate = new PromptTemplate(skPrompt, promptConfig, kernel);
var promptTemplate = new PromptTemplate(SkPrompt, promptConfig, kernel);
var functionConfig = new SemanticFunctionConfig(promptConfig, promptTemplate);
var chatFunction = kernel.RegisterSemanticFunction("PromptBot", "Chat", functionConfig);
await RunChat(kernel, logger, chatFunction);
Expand Down
10 changes: 5 additions & 5 deletions apps/SKonsole/ConfigurationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace SKonsole;
public class ConfigurationProvider
{
public static ConfigurationProvider Instance = new();
private const string _file = ".skonsole";
private const string File = ".skonsole";

private readonly string _path;
private IConfiguration _configuration;
Expand All @@ -16,11 +16,11 @@ public class ConfigurationProvider
public ConfigurationProvider()
{
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
this._path = Path.Combine(userProfile, _file);
this._path = Path.Combine(userProfile, File);

if (File.Exists(this._path))
if (System.IO.File.Exists(this._path))
{
this._config = FromJson<Dictionary<string, string?>>(File.ReadAllText(this._path)) ?? new();
this._config = FromJson<Dictionary<string, string?>>(System.IO.File.ReadAllText(this._path)) ?? new();
}

this.LoadConfig();
Expand Down Expand Up @@ -67,7 +67,7 @@ public async Task SaveConfig(string key, string value)
{
this._config[key] = value;

await File.WriteAllTextAsync(this._path, ToJson(this._config));
await System.IO.File.WriteAllTextAsync(this._path, ToJson<Dictionary<string, string?>>(this._config));

this.LoadConfig();
}
Expand Down
6 changes: 4 additions & 2 deletions apps/SKonsole/Skills/EmailSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ public static Task<SKContext> SendEmail(
string input,
[Description("The email address to send email to.")]
string email_address,
SKContext context)
SKContext context,
CancellationToken cancellationToken = default)
{
context.Variables.Update($"Sent email to: {email_address}.\n\n{input}");
return Task.FromResult(context);
}

[SKFunction, Description("Given a name, find email address")]
public static Task<SKContext> GetEmailAddress([Description("The name of the person to email.")] string input, SKContext context)
public static Task<SKContext> GetEmailAddress([Description("The name of the person to email.")] string input, SKContext context,
CancellationToken cancellationToken = default)
{
context.Logger().LogDebug("Returning hard coded email for {input}", input);
context.Variables.Update("[email protected]");
Expand Down
5 changes: 3 additions & 2 deletions apps/SKonsole/Skills/GitSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ namespace SKonsole.Skills;
internal sealed class GitSkill
{
[SKFunction, Description("Run 'git diff --staged' and return it's output.")]
public static async Task<SKContext> GitDiffStaged(SKContext context)
public static async Task<SKContext> GitDiffStaged(SKContext context,
CancellationToken cancellationToken = default)
{
using var process = new Process
{
Expand All @@ -24,7 +25,7 @@ public static async Task<SKContext> GitDiffStaged(SKContext context)
};
process.Start();

string output = await process.StandardOutput.ReadToEndAsync();
string output = await process.StandardOutput.ReadToEndAsync(cancellationToken);
context.Variables.Update(output);
return context;
}
Expand Down
4 changes: 2 additions & 2 deletions apps/SKonsole/Skills/WriterSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ internal sealed class WriterSkill
{
private const int MaxTokens = 1024;

private readonly ISKFunction funnyPoemFunction;
private readonly ISKFunction _funnyPoemFunction;

public WriterSkill(IKernel kernel)
{
this.funnyPoemFunction = kernel.CreateSemanticFunction(
this._funnyPoemFunction = kernel.CreateSemanticFunction(
FunnyPoemDefinition,
skillName: nameof(WriterSkill),
description: "Given a input topic or description or list, write a funny poem.",
Expand Down
7 changes: 4 additions & 3 deletions skills/CondenseSkill/CondenseSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public async Task<SKContext> Condense(
[Description("String of text that contains multiple chunks of similar formatting, style, and tone.")]
string input,
[Description("Separator to use between chunks.")]
string separator = "")
string separator = "",
CancellationToken cancellationToken = default)
{
var condenser = context.Skills.GetFunction(SEMANTIC_FUNCTION_PATH, "Condenser");

Expand All @@ -49,7 +50,7 @@ public async Task<SKContext> Condense(
foreach (var paragraph in paragraphs)
{
context.Variables.Update(paragraph + separator);
context = await condenser.InvokeAsync(context);
context = await condenser.InvokeAsync(context, cancellationToken: cancellationToken);
condenseResult.Add(context.Result);
}

Expand All @@ -60,7 +61,7 @@ public async Task<SKContext> Condense(

// update memory with serialized list of results and call condense again
this._logger.LogWarning($"Condensing {paragraphs.Count} paragraphs");
return await this.Condense(context, string.Join("\n", condenseResult), RESULTS_SEPARATOR);
return await this.Condense(context, string.Join("\n", condenseResult), RESULTS_SEPARATOR, cancellationToken);
}

private static string CondenseSkillPath()
Expand Down
21 changes: 12 additions & 9 deletions skills/PRSkill/PullRequestSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public class PullRequestSkill
public const string SEMANTIC_FUNCTION_PATH = "PRSkill";
private const int CHUNK_SIZE = 8000; // Eventually this should come from the kernel

private readonly CondenseSkill condenseSkill;
private readonly CondenseSkill _condenseSkill;

private readonly IKernel _kernel;
private readonly ILogger _logger;
Expand All @@ -83,7 +83,7 @@ public PullRequestSkill(IKernel kernel)
// Load semantic skill defined with prompt templates
var folder = PRSkillsPath();
var PRSkill = kernel.ImportSemanticSkillFromDirectory(folder, SEMANTIC_FUNCTION_PATH);
this.condenseSkill = new CondenseSkill(kernel);
this._condenseSkill = new CondenseSkill(kernel);

this._kernel = Kernel.Builder
.WithAIService<ITextCompletion>(null, new RedirectTextCompletion(), true)
Expand Down Expand Up @@ -115,24 +115,26 @@ public async Task<SKContext> GeneratePullRequestFeedback(
public async Task<SKContext> GenerateCommitMessage(
[Description("Output of a `git diff` command.")]
string input,
SKContext context)
SKContext context,
CancellationToken cancellationToken = default)
{
this._logger.LogTrace("GenerateCommitMessage called");

var commitGenerator = context.Skills.GetFunction(SEMANTIC_FUNCTION_PATH, "CommitMessageGenerator");

var commitGeneratorCapture = this._kernel.Skills.GetFunction(SEMANTIC_FUNCTION_PATH, "CommitMessageGenerator");
var prompt = (await commitGeneratorCapture.InvokeAsync()).Result;
var prompt = (await commitGeneratorCapture.InvokeAsync(cancellationToken: cancellationToken)).Result;

var chunkedInput = CommitChunker.ChunkCommitInfo(input, CHUNK_SIZE);
return await commitGenerator.CondenseChunkProcess(this.condenseSkill, chunkedInput, prompt, context, "CommitMessageResult");
return await commitGenerator.CondenseChunkProcess(this._condenseSkill, chunkedInput, prompt, context, "CommitMessageResult");
}

[SKFunction, Description("Generate a pull request description based on a git diff or git show file output using a rolling query mechanism.")]
public async Task<SKContext> GeneratePR_Rolling(
[Description("Output of a `git diff` or `git show` command.")]
string input,
SKContext context)
SKContext context,
CancellationToken cancellationToken = default)
{
var prGenerator_Rolling = context.Skills.GetFunction(SEMANTIC_FUNCTION_PATH, "PullRequestDescriptionGenerator_Rolling");
var chunkedInput = CommitChunker.ChunkCommitInfo(input, CHUNK_SIZE);
Expand All @@ -143,17 +145,18 @@ public async Task<SKContext> GeneratePR_Rolling(
public async Task<SKContext> GeneratePR(
[Description("Output of a `git diff` or `git show` command.")]
string input,
SKContext context)
SKContext context,
CancellationToken cancellationToken = default)
{
var prGenerator = context.Skills.GetFunction(SEMANTIC_FUNCTION_PATH, "PullRequestDescriptionGenerator");

var prGeneratorCapture = this._kernel.Skills.GetFunction(SEMANTIC_FUNCTION_PATH, "PullRequestDescriptionGenerator");
var contextVariablesWithoutInput = context.Variables.Clone();
contextVariablesWithoutInput.Set("input", "");
var prompt = (await prGeneratorCapture.InvokeAsync(contextVariablesWithoutInput)).Result;
var prompt = (await prGeneratorCapture.InvokeAsync(variables: contextVariablesWithoutInput, cancellationToken: cancellationToken)).Result;

var chunkedInput = CommitChunker.ChunkCommitInfo(input, CHUNK_SIZE);
return await prGenerator.CondenseChunkProcess(this.condenseSkill, chunkedInput, prompt, context, "PullRequestDescriptionResult");
return await prGenerator.CondenseChunkProcess(this._condenseSkill, chunkedInput, prompt, context, "PullRequestDescriptionResult");
}

#region MISC
Expand Down
55 changes: 55 additions & 0 deletions skonsole.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "apps", "apps", "{AF700D54-33BE-47F1-A8BF-A7A5F414F6AC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SKonsole", "apps\SKonsole\SKonsole.csproj", "{374F7AE0-DBD5-46E5-AA32-676D26C4F06A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "skills", "skills", "{A772B0DB-6D53-4DE7-8CB5-ABA07DA0AE7E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CondenseSkill", "skills\CondenseSkill\CondenseSkill.csproj", "{F812ABEF-5853-4DED-9897-2F599998E7CA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PRSkill", "skills\PRSkill\PRSkill.csproj", "{E2F9A912-EBC2-4608-9946-8E377F3C03DB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{450292C8-5ED2-4CBB-8624-F1F05EC12625}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
Directory.Packages.props = Directory.Packages.props
README.md = README.md
nuget.config = nuget.config
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{374F7AE0-DBD5-46E5-AA32-676D26C4F06A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{374F7AE0-DBD5-46E5-AA32-676D26C4F06A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{374F7AE0-DBD5-46E5-AA32-676D26C4F06A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{374F7AE0-DBD5-46E5-AA32-676D26C4F06A}.Release|Any CPU.Build.0 = Release|Any CPU
{F812ABEF-5853-4DED-9897-2F599998E7CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F812ABEF-5853-4DED-9897-2F599998E7CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F812ABEF-5853-4DED-9897-2F599998E7CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F812ABEF-5853-4DED-9897-2F599998E7CA}.Release|Any CPU.Build.0 = Release|Any CPU
{E2F9A912-EBC2-4608-9946-8E377F3C03DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2F9A912-EBC2-4608-9946-8E377F3C03DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2F9A912-EBC2-4608-9946-8E377F3C03DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2F9A912-EBC2-4608-9946-8E377F3C03DB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{374F7AE0-DBD5-46E5-AA32-676D26C4F06A} = {AF700D54-33BE-47F1-A8BF-A7A5F414F6AC}
{F812ABEF-5853-4DED-9897-2F599998E7CA} = {A772B0DB-6D53-4DE7-8CB5-ABA07DA0AE7E}
{E2F9A912-EBC2-4608-9946-8E377F3C03DB} = {A772B0DB-6D53-4DE7-8CB5-ABA07DA0AE7E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {09EB533F-20DE-42E2-991E-9A45C2FF5E5A}
EndGlobalSection
EndGlobal
Loading