diff --git a/src/apps/WorkflowsApp/Program.cs b/src/apps/WorkflowsApp/Program.cs index 05c965e0f3dc..378a6f6c27b4 100644 --- a/src/apps/WorkflowsApp/Program.cs +++ b/src/apps/WorkflowsApp/Program.cs @@ -2,8 +2,6 @@ using Elsa.EntityFrameworkCore.Modules.Management; using Elsa.EntityFrameworkCore.Modules.Runtime; using Elsa.Extensions; -using Elsa.Workflows.Core.Models; -using Elsa.Identity.Features; using Elsa.SemanticKernel; var builder = WebApplication.CreateBuilder(args); diff --git a/src/apps/WorkflowsApp/WorkflowsApp.csproj b/src/apps/WorkflowsApp/WorkflowsApp.csproj index 91a86e335327..7b6f0aa51552 100644 --- a/src/apps/WorkflowsApp/WorkflowsApp.csproj +++ b/src/apps/WorkflowsApp/WorkflowsApp.csproj @@ -7,19 +7,10 @@ - - - - - - - + + + + diff --git a/src/apps/gh-flow/Program.cs b/src/apps/gh-flow/Program.cs index f0528ae688cf..02b9c379aec8 100644 --- a/src/apps/gh-flow/Program.cs +++ b/src/apps/gh-flow/Program.cs @@ -4,20 +4,17 @@ using Microsoft.AI.DevTeam; using Microsoft.Extensions.Options; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Connectors.AI.OpenAI; -using Microsoft.SemanticKernel.Connectors.Memory.Qdrant; -using Microsoft.SemanticKernel.Memory; -using Microsoft.SemanticKernel.Plugins.Memory; -using Microsoft.SemanticKernel.Reliability.Basic; using Octokit.Webhooks; using Octokit.Webhooks.AspNetCore; using Azure.Identity; using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Http.Resilience; +using Microsoft.KernelMemory; var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton(); builder.Services.AddTransient(CreateKernel); -builder.Services.AddTransient(CreateMemory); +builder.Services.AddSingleton(CreateMemory); builder.Services.AddHttpClient(); builder.Services.AddSingleton(s => @@ -99,48 +96,46 @@ app.Run(); -static ISemanticTextMemory CreateMemory(IServiceProvider provider) +static IKernelMemory CreateMemory(IServiceProvider provider) { - var openAiConfig = provider.GetService>().Value; var qdrantConfig = provider.GetService>().Value; - - var loggerFactory = LoggerFactory.Create(builder => - { - builder - .SetMinimumLevel(LogLevel.Debug) - .AddConsole() - .AddDebug(); - }); - - var memoryBuilder = new MemoryBuilder(); - return memoryBuilder.WithLoggerFactory(loggerFactory) - .WithQdrantMemoryStore(qdrantConfig.Endpoint, qdrantConfig.VectorSize) - .WithAzureTextEmbeddingGenerationService(openAiConfig.EmbeddingDeploymentOrModelId, openAiConfig.Endpoint, openAiConfig.ApiKey) - .Build(); + var openAiConfig = provider.GetService>().Value; + return new KernelMemoryBuilder() + .WithQdrantMemoryDb(qdrantConfig.Endpoint) + .WithAzureOpenAITextGeneration(new AzureOpenAIConfig + { + APIType = AzureOpenAIConfig.APITypes.ChatCompletion, + Endpoint = openAiConfig.Endpoint, + Deployment = openAiConfig.DeploymentOrModelId, + Auth = AzureOpenAIConfig.AuthTypes.APIKey, + APIKey = openAiConfig.ApiKey + }) + .WithAzureOpenAITextEmbeddingGeneration(new AzureOpenAIConfig + { + APIType = AzureOpenAIConfig.APITypes.EmbeddingGeneration, + Endpoint = openAiConfig.Endpoint, + Deployment =openAiConfig.EmbeddingDeploymentOrModelId, + Auth = AzureOpenAIConfig.AuthTypes.APIKey, + APIKey = openAiConfig.ApiKey + }) + .Build(); } -static IKernel CreateKernel(IServiceProvider provider) +static Kernel CreateKernel(IServiceProvider provider) { var openAiConfig = provider.GetService>().Value; - - var loggerFactory = LoggerFactory.Create(builder => - { - builder - .SetMinimumLevel(LogLevel.Debug) - .AddConsole() - .AddDebug(); - }); - var clientOptions = new OpenAIClientOptions(); clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5); var openAIClient = new OpenAIClient(new Uri(openAiConfig.Endpoint), new AzureKeyCredential(openAiConfig.ApiKey), clientOptions); - - return new KernelBuilder() - .WithLoggerFactory(loggerFactory) - .WithAzureChatCompletionService(openAiConfig.DeploymentOrModelId, openAIClient) - .WithRetryBasic(new BasicRetryConfig - { - MaxRetryCount = 5, - UseExponentialBackoff = true - }).Build(); + var builder = Kernel.CreateBuilder(); + builder.Services.AddLogging( c=> c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug)); + builder.Services.AddAzureOpenAIChatCompletion(openAiConfig.DeploymentOrModelId, openAIClient); + builder.Services.ConfigureHttpClientDefaults(c=> + { + c.AddStandardResilienceHandler().Configure( o=> { + o.Retry.MaxRetryAttempts = 5; + o.Retry.BackoffType = Polly.DelayBackoffType.Exponential; + }); + }); + return builder.Build(); } \ No newline at end of file diff --git a/src/apps/gh-flow/gh-flow.csproj b/src/apps/gh-flow/gh-flow.csproj index a907c5294c38..03a8723a69de 100644 --- a/src/apps/gh-flow/gh-flow.csproj +++ b/src/apps/gh-flow/gh-flow.csproj @@ -11,11 +11,13 @@ true true c073c86e-8483-4956-942f-331fd09172d4 + All - + + @@ -25,6 +27,9 @@ + + + diff --git a/src/apps/seed-memory/Program.cs b/src/apps/seed-memory/Program.cs index 79e11cb59cf8..7f1385ffbb57 100644 --- a/src/apps/seed-memory/Program.cs +++ b/src/apps/seed-memory/Program.cs @@ -1,12 +1,5 @@ -using UglyToad.PdfPig; -using UglyToad.PdfPig.DocumentLayoutAnalysis.TextExtractor; -using Microsoft.SemanticKernel; -using Microsoft.Extensions.Logging; -using Microsoft.SemanticKernel.Connectors.Memory.Qdrant; -using Microsoft.SemanticKernel.Memory; -using System.Reflection; -using Microsoft.SemanticKernel.Plugins.Memory; -using Microsoft.SemanticKernel.Connectors.AI.OpenAI; +using Microsoft.Extensions.Logging; +using Microsoft.KernelMemory; class Program { @@ -22,37 +15,34 @@ static async Task Main(string[] args) .AddConsole() .AddDebug(); }); - - var memoryBuilder = new MemoryBuilder(); - var memory = memoryBuilder.WithLoggerFactory(loggerFactory) - .WithQdrantMemoryStore(kernelSettings.QdrantEndpoint, 1536) - .WithAzureTextEmbeddingGenerationService(kernelSettings.EmbeddingDeploymentOrModelId, kernelSettings.Endpoint, kernelSettings.ApiKey) - .Build(); + + var memory = new KernelMemoryBuilder() + .WithQdrantMemoryDb(kernelSettings.QdrantEndpoint) + .WithAzureOpenAITextGeneration(new AzureOpenAIConfig + { + APIType = AzureOpenAIConfig.APITypes.ChatCompletion, + Endpoint =kernelSettings.Endpoint, + Deployment = kernelSettings.DeploymentOrModelId, + Auth = AzureOpenAIConfig.AuthTypes.APIKey, + APIKey = kernelSettings.ApiKey + }) + .WithAzureOpenAITextEmbeddingGeneration(new AzureOpenAIConfig + { + APIType = AzureOpenAIConfig.APITypes.EmbeddingGeneration, + Endpoint = kernelSettings.Endpoint, + Deployment =kernelSettings.EmbeddingDeploymentOrModelId, + Auth = AzureOpenAIConfig.AuthTypes.APIKey, + APIKey = kernelSettings.ApiKey + }) + .Build(); await ImportDocumentAsync(memory, WafFileName); } - public static async Task ImportDocumentAsync(ISemanticTextMemory memory, string filename) + public static async Task ImportDocumentAsync(IKernelMemory memory, string filename) { - var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var filePath = Path.Combine(currentDirectory, filename); - using var pdfDocument = PdfDocument.Open(File.OpenRead(filePath)); - var pages = pdfDocument.GetPages(); - foreach (var page in pages) - { - try - { - var text = ContentOrderTextExtractor.GetText(page); - var descr = text.Take(100); - await memory.SaveInformationAsync( - collection: "waf-pages", - text: text, - id: $"{Guid.NewGuid()}", - description: $"Document: {descr}"); - } - catch(Exception ex) - { - Console.WriteLine(ex.Message); - } - } + await memory.ImportDocumentAsync(new Document("wafdoc") + .AddFiles([ + filename + ]), index: "waf"); } } \ No newline at end of file diff --git a/src/apps/seed-memory/seed-memory.csproj b/src/apps/seed-memory/seed-memory.csproj index fd33f7cca5c5..47642e49d861 100644 --- a/src/apps/seed-memory/seed-memory.csproj +++ b/src/apps/seed-memory/seed-memory.csproj @@ -9,13 +9,10 @@ - - - - - - + + + diff --git a/src/libs/Elsa.SemanticKernel/Activities/ActivityProviders/SemanticKernelSkillActivityProvider.cs b/src/libs/Elsa.SemanticKernel/Activities/ActivityProviders/SemanticKernelSkillActivityProvider.cs index df2e562352a7..a40f504d6f82 100644 --- a/src/libs/Elsa.SemanticKernel/Activities/ActivityProviders/SemanticKernelSkillActivityProvider.cs +++ b/src/libs/Elsa.SemanticKernel/Activities/ActivityProviders/SemanticKernelSkillActivityProvider.cs @@ -4,15 +4,19 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Azure; +using Azure.AI.OpenAI; using Elsa.Extensions; -using Elsa.Workflows.Core; -using Elsa.Workflows.Core.Contracts; -using Elsa.Workflows.Core.Models; +using Elsa.Workflows; +using Elsa.Workflows.Contracts; +using Elsa.Workflows.Models; +using Elsa.Workflows.UIHints; using Microsoft.AI.DevTeam.Skills; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Http.Resilience; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Connectors.AI.OpenAI; -using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.Connectors.OpenAI; namespace Elsa.SemanticKernel; @@ -36,9 +40,8 @@ public async ValueTask> GetDescriptorsAsync(Canc // get a list of skills in the assembly var skills = LoadSkillsFromAssemblyAsync("skills", kernel); - SKContext context = kernel.CreateNewContext(); - var functionsAvailable = context.Functions.GetFunctionViews(); - + var functionsAvailable = kernel.Plugins.GetFunctionsMetadata(); + // create activity descriptors for each skilland function var activities = new List(); foreach (var function in functionsAvailable) @@ -56,7 +59,7 @@ public async ValueTask> GetDescriptorsAsync(Canc /// The semantic kernel function /// An optional cancellation token. /// An activity descriptor. - private ActivityDescriptor CreateActivityDescriptorFromSkillAndFunction(FunctionView function, CancellationToken cancellationToken = default) + private ActivityDescriptor CreateActivityDescriptorFromSkillAndFunction(KernelFunctionMetadata function, CancellationToken cancellationToken = default) { // Create a fully qualified type name for the activity var thisNamespace = GetType().Namespace; @@ -128,12 +131,12 @@ private InputDescriptor CreateInputDescriptor(Type inputType, string name, Objec /// /// The function parameter. /// An input descriptor. - private InputDescriptor CreateInputDescriptorFromSKParameter(ParameterView parameter) + private InputDescriptor CreateInputDescriptorFromSKParameter(KernelParameterMetadata parameter) { var inputDescriptor = new InputDescriptor { Description = string.IsNullOrEmpty(parameter.Description) ? parameter.Name : parameter.Description, - DefaultValue = string.IsNullOrEmpty(parameter.DefaultValue) ? string.Empty : parameter.DefaultValue, + DefaultValue = parameter.DefaultValue == null ? string.Empty : parameter.DefaultValue, Type = typeof(string), Name = parameter.Name, DisplayName = parameter.Name, @@ -150,7 +153,7 @@ private InputDescriptor CreateInputDescriptorFromSKParameter(ParameterView param /// /// Gets a list of the skills in the assembly /// - private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, IKernel kernel) + private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, Kernel kernel) { var skills = new List(); var assembly = Assembly.Load(assemblyName); @@ -167,10 +170,10 @@ private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, IKe if (field.Equals("Microsoft.SKDevTeam.SemanticFunctionConfig")) { var promptTemplate = Skills.ForSkillAndFunction(skillType.Name, function.Name); - var skfunc = kernel.CreateSemanticFunction( - promptTemplate, new OpenAIRequestSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 }); + var skfunc = kernel.CreateFunctionFromPrompt( + promptTemplate, new OpenAIPromptExecutionSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 }); - Console.WriteLine($"SKActivityProvider Added SK function: {skfunc.PluginName}.{skfunc.Name}"); + Console.WriteLine($"SKActivityProvider Added SK function: {skfunc.Metadata.PluginName}.{skfunc.Name}"); } } } @@ -182,22 +185,24 @@ private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, IKe /// Gets a semantic kernel instance /// /// Microsoft.SemanticKernel.IKernel - private IKernel KernelBuilder() + private Kernel KernelBuilder() { var kernelSettings = KernelSettings.LoadSettings(); - using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => + var clientOptions = new OpenAIClientOptions(); + clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5); + var openAIClient = new OpenAIClient(new Uri(kernelSettings.Endpoint), new AzureKeyCredential(kernelSettings.ApiKey), clientOptions); + var builder = Kernel.CreateBuilder(); + builder.Services.AddLogging( c=> c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug)); + builder.Services.AddAzureOpenAIChatCompletion(kernelSettings.DeploymentOrModelId, openAIClient); + builder.Services.ConfigureHttpClientDefaults(c=> { - builder.SetMinimumLevel(kernelSettings.LogLevel ?? LogLevel.Warning); + c.AddStandardResilienceHandler().Configure( o=> { + o.Retry.MaxRetryAttempts = 5; + o.Retry.BackoffType = Polly.DelayBackoffType.Exponential; + }); }); - - var kernel = new KernelBuilder() - .WithLoggerFactory(loggerFactory) - .WithAzureChatCompletionService(kernelSettings.DeploymentOrModelId, kernelSettings.Endpoint, kernelSettings.ApiKey, true, kernelSettings.ServiceId, true) - .Build(); - - return kernel; + return builder.Build(); } - } diff --git a/src/libs/Elsa.SemanticKernel/Activities/SemanticKernel.cs b/src/libs/Elsa.SemanticKernel/Activities/SemanticKernel.cs index e81da076baea..338dc7d2e512 100644 --- a/src/libs/Elsa.SemanticKernel/Activities/SemanticKernel.cs +++ b/src/libs/Elsa.SemanticKernel/Activities/SemanticKernel.cs @@ -1,11 +1,7 @@ using Elsa.Extensions; -using Elsa.Workflows.Core; -using Elsa.Workflows.Core.Attributes; -using Elsa.Workflows.Core.Models; using JetBrains.Annotations; using Microsoft.Extensions.Logging; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Orchestration; using System; using System.Text; @@ -14,7 +10,15 @@ using System.Reflection; using System.Threading.Tasks; using Microsoft.AI.DevTeam.Skills; -using Microsoft.SemanticKernel.Connectors.AI.OpenAI; +using Elsa.Workflows; +using Elsa.Workflows.Attributes; +using Elsa.Workflows.UIHints; +using Elsa.Workflows.Models; +using Azure.AI.OpenAI; +using Azure; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Http.Resilience; +using Microsoft.SemanticKernel.Connectors.OpenAI; namespace Elsa.SemanticKernel; @@ -88,23 +92,14 @@ protected override async ValueTask ExecuteAsync(ActivityExecutionContext workflo // load the skill var promptTemplate = Skills.ForSkillAndFunction(skillName, functionName); - var function = kernel.CreateSemanticFunction(promptTemplate, new OpenAIRequestSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 }); + var function = kernel.CreateFunctionFromPrompt(promptTemplate, new OpenAIPromptExecutionSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 }); // set the context (our prompt) - var contextVars = new ContextVariables(); - contextVars.Set("input", prompt); + var arguments = new KernelArguments{ + ["input"] = prompt + }; - /* var interestingMemories = kernel.Memory.SearchAsync("ImportedMemories", prompt, 2); - var wafContext = "Consider the following contextual snippets:"; - await foreach (var memory in interestingMemories) - { - wafContext += $"\n {memory.Metadata.Text}"; - } */ - - - //context.Set("wafContext", wafContext); - - var answer = await kernel.RunAsync(contextVars, function); + var answer = await kernel.InvokeAsync(function, arguments); workflowContext.SetResult(answer); } } @@ -112,12 +107,11 @@ protected override async ValueTask ExecuteAsync(ActivityExecutionContext workflo /// /// Load the skills into the kernel /// - private string ListSkillsInKernel(IKernel kernel) + private string ListSkillsInKernel(Kernel kernel) { var theSkills = LoadSkillsFromAssemblyAsync("skills", kernel); - SKContext context = kernel.CreateNewContext(); - var functionsAvailable = context.Functions.GetFunctionViews(); + var functionsAvailable = kernel.Plugins.GetFunctionsMetadata(); var list = new StringBuilder(); foreach (var function in functionsAvailable) @@ -142,7 +136,7 @@ private string ListSkillsInKernel(IKernel kernel) foreach (var p in function.Parameters) { var description = string.IsNullOrEmpty(p.Description) ? p.Name : p.Description; - var defaultValueString = string.IsNullOrEmpty(p.DefaultValue) ? string.Empty : $" (default value: {p.DefaultValue})"; + var defaultValueString = p.DefaultValue == null ? string.Empty : $" (default value: {p.DefaultValue})"; list.AppendLine($"Parameter \"{p.Name}\": {description} {defaultValueString}"); } } @@ -155,34 +149,30 @@ private string ListSkillsInKernel(IKernel kernel) /// Gets a semantic kernel instance /// /// Microsoft.SemanticKernel.IKernel - private IKernel KernelBuilder() + private Kernel KernelBuilder() { var kernelSettings = KernelSettings.LoadSettings(); - using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => + var clientOptions = new OpenAIClientOptions(); + clientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(5); + var openAIClient = new OpenAIClient(new Uri(kernelSettings.Endpoint), new AzureKeyCredential(kernelSettings.ApiKey), clientOptions); + var builder = Kernel.CreateBuilder(); + builder.Services.AddLogging( c=> c.AddConsole().AddDebug().SetMinimumLevel(LogLevel.Debug)); + builder.Services.AddAzureOpenAIChatCompletion(kernelSettings.DeploymentOrModelId, openAIClient); + builder.Services.ConfigureHttpClientDefaults(c=> { - builder.SetMinimumLevel(kernelSettings.LogLevel ?? LogLevel.Warning); + c.AddStandardResilienceHandler().Configure( o=> { + o.Retry.MaxRetryAttempts = 5; + o.Retry.BackoffType = Polly.DelayBackoffType.Exponential; + }); }); - - /* - var memoryStore = new QdrantMemoryStore(new QdrantVectorDbClient("http://qdrant", 1536, port: 6333)); - var embedingGeneration = new AzureTextEmbeddingGeneration(kernelSettings.EmbeddingDeploymentOrModelId, kernelSettings.Endpoint, kernelSettings.ApiKey); - var semanticTextMemory = new SemanticTextMemory(memoryStore, embedingGeneration); - */ - - var kernel = new KernelBuilder() - .WithLoggerFactory(loggerFactory) - .WithAzureChatCompletionService(kernelSettings.DeploymentOrModelId, kernelSettings.Endpoint, kernelSettings.ApiKey, true, kernelSettings.ServiceId, true) - //.WithMemory(semanticTextMemory) - .Build(); - - return kernel; + return builder.Build(); } /// /// Gets a list of the skills in the assembly /// - private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, IKernel kernel) + private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, Kernel kernel) { var skills = new List(); var assembly = Assembly.Load(assemblyName); @@ -199,10 +189,10 @@ private IEnumerable LoadSkillsFromAssemblyAsync(string assemblyName, IKe if (field.Equals("Microsoft.SKDevTeam.SemanticFunctionConfig")) { var prompt = Skills.ForSkillAndFunction(skillType.Name, function.Name); - var skfunc = kernel.CreateSemanticFunction( - prompt, new OpenAIRequestSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 }); + var skfunc = kernel.CreateFunctionFromPrompt( + prompt, new OpenAIPromptExecutionSettings { MaxTokens = 8000, Temperature = 0.4, TopP = 1 }); - Console.WriteLine($"SK Added function: {skfunc.SkillName}.{skfunc.Name}"); + Console.WriteLine($"SK Added function: {skfunc.Metadata.PluginName}.{skfunc.Metadata.Name}"); } } } diff --git a/src/libs/Elsa.SemanticKernel/Elsa.SemanticKernel.csproj b/src/libs/Elsa.SemanticKernel/Elsa.SemanticKernel.csproj index c74693d35321..4360013c74f6 100644 --- a/src/libs/Elsa.SemanticKernel/Elsa.SemanticKernel.csproj +++ b/src/libs/Elsa.SemanticKernel/Elsa.SemanticKernel.csproj @@ -9,20 +9,21 @@ - - - - - - - - - + + + + + + + + + - - - - + + + + + diff --git a/src/libs/Microsoft.AI.DevTeam.Skills/Microsoft.AI.DevTeam.Skills.csproj b/src/libs/Microsoft.AI.DevTeam.Skills/Microsoft.AI.DevTeam.Skills.csproj index d54d803d5bd6..3d82e22fa28c 100644 --- a/src/libs/Microsoft.AI.DevTeam.Skills/Microsoft.AI.DevTeam.Skills.csproj +++ b/src/libs/Microsoft.AI.DevTeam.Skills/Microsoft.AI.DevTeam.Skills.csproj @@ -7,6 +7,6 @@ - + diff --git a/src/libs/Microsoft.AI.DevTeam/Agents/AiAgent.cs b/src/libs/Microsoft.AI.DevTeam/Agents/AiAgent.cs index f4e9bf661055..e5b969e9f7e0 100644 --- a/src/libs/Microsoft.AI.DevTeam/Agents/AiAgent.cs +++ b/src/libs/Microsoft.AI.DevTeam/Agents/AiAgent.cs @@ -1,31 +1,29 @@ using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Connectors.AI.OpenAI; -using Microsoft.SemanticKernel.Memory; -using Microsoft.SemanticKernel.Orchestration; +using Microsoft.SemanticKernel.Connectors.OpenAI; using Orleans.Runtime; +using Microsoft.KernelMemory; namespace Microsoft.AI.DevTeam; public abstract class AiAgent : Agent { public AiAgent( - [PersistentState("state", "messages")] IPersistentState state) + [PersistentState("state", "messages")] IPersistentState state, IKernelMemory memory) { _state = state; + _memory = memory; } protected readonly IPersistentState _state; - protected async Task CreateWafContext(ISemanticTextMemory memory, string ask) + private readonly IKernelMemory _memory; + + protected async Task CreateWafContext(IKernelMemory memory, string ask) { - var context = new ContextVariables(); - var interestingMemories = memory.SearchAsync("waf-pages", ask, 2); - var wafContext = "Consider the following architectural guidelines:"; - await foreach (var m in interestingMemories) - { - wafContext += $"\n {m.Metadata.Text}"; - } - context.Set("input", ask); - context.Set("wafContext", wafContext); - return context; + var waf = await memory.AskAsync(ask, index:"waf"); + + return new KernelArguments{ + ["input"] = ask, + ["wafContext"] = $"Consider the following architectural guidelines: ${waf}" + }; } protected void AddToHistory(string message, ChatUserType userType) @@ -44,13 +42,13 @@ protected string GetChatHistory() return string.Join("\n",_state.State.History.Select(message=> $"{message.UserType}: {message.Message}")); } - protected async Task CallFunction(string template, string ask, IKernel kernel, ISemanticTextMemory memory) + protected async Task CallFunction(string template, string ask, Kernel kernel) { - var function = kernel.CreateSemanticFunction(template, new OpenAIRequestSettings { MaxTokens = 15000, Temperature = 0.8, TopP = 1 }); + var function = kernel.CreateFunctionFromPrompt(template, new OpenAIPromptExecutionSettings { MaxTokens = 15000, Temperature = 0.8, TopP = 1 }); AddToHistory(ask, ChatUserType.User); var history = GetChatHistory(); - var context = await CreateWafContext(memory, history); - var result = (await kernel.RunAsync(context, function)).ToString(); + var context = await CreateWafContext(_memory, history); + var result = (await kernel.InvokeAsync(function, context)).ToString(); AddToHistory(result, ChatUserType.Agent); await _state.WriteStateAsync(); diff --git a/src/libs/Microsoft.AI.DevTeam/Agents/Developer.cs b/src/libs/Microsoft.AI.DevTeam/Agents/Developer.cs index c0a221116112..bdf85c6707a6 100644 --- a/src/libs/Microsoft.AI.DevTeam/Agents/Developer.cs +++ b/src/libs/Microsoft.AI.DevTeam/Agents/Developer.cs @@ -1,9 +1,8 @@ using Microsoft.AI.DevTeam.Skills; using Microsoft.Extensions.Logging; +using Microsoft.KernelMemory; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Connectors.AI.OpenAI; using Microsoft.SemanticKernel.Memory; -using Microsoft.SemanticKernel.Orchestration; using Orleans.Runtime; using Orleans.Streams; @@ -12,14 +11,13 @@ namespace Microsoft.AI.DevTeam; [ImplicitStreamSubscription(Consts.MainNamespace)] public class Dev : AiAgent, IDevelopApps { - private readonly IKernel _kernel; - private readonly ISemanticTextMemory _memory; + private readonly Kernel _kernel; private readonly ILogger _logger; - public Dev([PersistentState("state", "messages")] IPersistentState state, IKernel kernel, ISemanticTextMemory memory, ILogger logger) : base(state) + public Dev([PersistentState("state", "messages")] IPersistentState state, Kernel kernel, IKernelMemory memory, ILogger logger) + : base(state, memory) { _kernel = kernel; - _memory = memory; _logger = logger; } @@ -63,7 +61,7 @@ public async Task GenerateCode(string ask) { try { - return await CallFunction(Developer.Implement, ask, _kernel, _memory); + return await CallFunction(Developer.Implement, ask, _kernel); } catch (Exception ex) { @@ -72,39 +70,39 @@ public async Task GenerateCode(string ask) } } - public async Task BuildUnderstanding(string content) - { - try - { - var explainFunction = _kernel.CreateSemanticFunction(Developer.Explain, new OpenAIRequestSettings { MaxTokens = 15000, Temperature = 0.8, TopP = 1 }); - var consolidateFunction = _kernel.CreateSemanticFunction(Developer.ConsolidateUnderstanding, new OpenAIRequestSettings { MaxTokens = 15000, Temperature = 0.8, TopP = 1 }); - var explainContext = new ContextVariables(); - explainContext.Set("input", content); - var explainResult = await _kernel.RunAsync(explainContext, explainFunction); - var explainMesage = explainResult.ToString(); + // public async Task BuildUnderstanding(string content) + // { + // try + // { + // var explainFunction = _kernel.CreateSemanticFunction(Developer.Explain, new OpenAIRequestSettings { MaxTokens = 15000, Temperature = 0.8, TopP = 1 }); + // var consolidateFunction = _kernel.CreateSemanticFunction(Developer.ConsolidateUnderstanding, new OpenAIRequestSettings { MaxTokens = 15000, Temperature = 0.8, TopP = 1 }); + // var explainContext = new ContextVariables(); + // explainContext.Set("input", content); + // var explainResult = await _kernel.RunAsync(explainContext, explainFunction); + // var explainMesage = explainResult.ToString(); - var consolidateContext = new ContextVariables(); - consolidateContext.Set("input", _state.State.Understanding); - consolidateContext.Set("newUnderstanding", explainMesage); + // var consolidateContext = new ContextVariables(); + // consolidateContext.Set("input", _state.State.Understanding); + // consolidateContext.Set("newUnderstanding", explainMesage); - var consolidateResult = await _kernel.RunAsync(consolidateContext, consolidateFunction); - var consolidateMessage = consolidateResult.ToString(); + // var consolidateResult = await _kernel.RunAsync(consolidateContext, consolidateFunction); + // var consolidateMessage = consolidateResult.ToString(); - _state.State.Understanding = consolidateMessage; - await _state.WriteStateAsync(); + // _state.State.Understanding = consolidateMessage; + // await _state.WriteStateAsync(); - return new UnderstandingResult - { - NewUnderstanding = consolidateMessage, - Explanation = explainMesage - }; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error building understanding"); - return default; - } - } + // return new UnderstandingResult + // { + // NewUnderstanding = consolidateMessage, + // Explanation = explainMesage + // }; + // } + // catch (Exception ex) + // { + // _logger.LogError(ex, "Error building understanding"); + // return default; + // } + // } } public interface IDevelopApps diff --git a/src/libs/Microsoft.AI.DevTeam/Agents/DeveloperLead.cs b/src/libs/Microsoft.AI.DevTeam/Agents/DeveloperLead.cs index 32c7a84ab9d7..8de180905e40 100644 --- a/src/libs/Microsoft.AI.DevTeam/Agents/DeveloperLead.cs +++ b/src/libs/Microsoft.AI.DevTeam/Agents/DeveloperLead.cs @@ -1,25 +1,23 @@ using Microsoft.AI.DevTeam.Skills; using Microsoft.Extensions.Logging; +using Microsoft.KernelMemory; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Memory; using Orleans.Runtime; using Orleans.Streams; -using System.Text.Json; namespace Microsoft.AI.DevTeam; [ImplicitStreamSubscription(Consts.MainNamespace)] public class DeveloperLead : AiAgent, ILeadDevelopers { - private readonly IKernel _kernel; - private readonly ISemanticTextMemory _memory; + private readonly Kernel _kernel; private readonly ILogger _logger; private readonly IManageGithub _ghService; - public DeveloperLead([PersistentState("state", "messages")] IPersistentState state, IKernel kernel, ISemanticTextMemory memory, ILogger logger, IManageGithub ghService) : base(state) + public DeveloperLead([PersistentState("state", "messages")] IPersistentState state, Kernel kernel, IKernelMemory memory, ILogger logger, IManageGithub ghService) + : base(state, memory) { _kernel = kernel; - _memory = memory; _logger = logger; _ghService = ghService; } @@ -65,7 +63,7 @@ public async Task CreatePlan(string ask) { try { - return await CallFunction(DevLead.Plan, ask, _kernel, _memory); + return await CallFunction(DevLead.Plan, ask, _kernel); } catch (Exception ex) { diff --git a/src/libs/Microsoft.AI.DevTeam/Agents/ProductManager.cs b/src/libs/Microsoft.AI.DevTeam/Agents/ProductManager.cs index fe9a82f6c8ee..758d0b2f3a67 100644 --- a/src/libs/Microsoft.AI.DevTeam/Agents/ProductManager.cs +++ b/src/libs/Microsoft.AI.DevTeam/Agents/ProductManager.cs @@ -1,7 +1,7 @@ using Microsoft.AI.DevTeam.Skills; using Microsoft.Extensions.Logging; +using Microsoft.KernelMemory; using Microsoft.SemanticKernel; -using Microsoft.SemanticKernel.Memory; using Orleans.Runtime; using Orleans.Streams; @@ -10,14 +10,14 @@ namespace Microsoft.AI.DevTeam; [ImplicitStreamSubscription(Consts.MainNamespace)] public class ProductManager : AiAgent, IManageProducts { - private readonly IKernel _kernel; - private readonly ISemanticTextMemory _memory; + private readonly Kernel _kernel; private readonly ILogger _logger; - public ProductManager([PersistentState("state", "messages")] IPersistentState state, IKernel kernel, ISemanticTextMemory memory, ILogger logger) : base(state) + public ProductManager([PersistentState("state", "messages")] IPersistentState state, Kernel kernel, IKernelMemory memory, ILogger logger) + : base(state, memory) { _kernel = kernel; - _memory = memory; + //_memory = memory; _logger = logger; } @@ -61,7 +61,7 @@ public async Task CreateReadme(string ask) { try { - return await CallFunction(PM.Readme, ask, _kernel, _memory); + return await CallFunction(PM.Readme, ask, _kernel); } catch (Exception ex) { diff --git a/src/libs/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj b/src/libs/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj index 33faeee860c9..b11f3669d38f 100644 --- a/src/libs/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj +++ b/src/libs/Microsoft.AI.DevTeam/Microsoft.AI.DevTeam.csproj @@ -4,21 +4,22 @@ net8.0 enable enable + All - - + - + + diff --git a/src/libs/Microsoft.AI.DevTeam/Services/CodeAnalyzer.cs b/src/libs/Microsoft.AI.DevTeam/Services/CodeAnalyzer.cs index 3e8cb3371ba2..eddb7801a409 100644 --- a/src/libs/Microsoft.AI.DevTeam/Services/CodeAnalyzer.cs +++ b/src/libs/Microsoft.AI.DevTeam/Services/CodeAnalyzer.cs @@ -1,9 +1,7 @@ -using System.Net.Http.Json; using System.Text; using System.Text.Json; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Octokit.Internal; namespace Microsoft.AI.DevTeam; diff --git a/src/libs/Microsoft.AI.DevTeam/Services/GithubAuthService.cs b/src/libs/Microsoft.AI.DevTeam/Services/GithubAuthService.cs index ae0b1b5f8758..5a0a110fc6a8 100644 --- a/src/libs/Microsoft.AI.DevTeam/Services/GithubAuthService.cs +++ b/src/libs/Microsoft.AI.DevTeam/Services/GithubAuthService.cs @@ -1,5 +1,9 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Security.Cryptography; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; using Octokit; namespace Microsoft.AI.DevTeam; @@ -13,21 +17,39 @@ public GithubAuthService(IOptions ghOptions, ILogger GetGitHubClient() { try { - // Use GitHubJwt library to create the GitHubApp Jwt Token using our private certificate PEM file - var generator = new GitHubJwt.GitHubJwtFactory( - new GitHubJwt.StringPrivateKeySource(_githubSettings.AppKey), - new GitHubJwt.GitHubJwtFactoryOptions - { - AppIntegrationId = _githubSettings.AppId, // The GitHub App Id - ExpirationSeconds = 600 // 10 minutes is the maximum time allowed - } - ); - - var jwtToken = generator.CreateEncodedJwtToken(); + var jwtToken = GenerateJwtToken(_githubSettings.AppId.ToString(), _githubSettings.AppKey, 10); var appClient = new GitHubClient(new ProductHeaderValue("SK-DEV-APP")) { Credentials = new Credentials(jwtToken, AuthenticationType.Bearer) diff --git a/src/libs/Microsoft.AI.DevTeam/Services/GithubService.cs b/src/libs/Microsoft.AI.DevTeam/Services/GithubService.cs index 384c07c4a146..78ab0f76a485 100644 --- a/src/libs/Microsoft.AI.DevTeam/Services/GithubService.cs +++ b/src/libs/Microsoft.AI.DevTeam/Services/GithubService.cs @@ -15,7 +15,7 @@ public class GithubService : IManageGithub private readonly ILogger _logger; private readonly HttpClient _httpClient; - public GithubService(GitHubClient ghClient, IOptions azOptions, ILogger logger, HttpClient httpClient) + public GithubService(IOptions azOptions, GitHubClient ghClient, ILogger logger, HttpClient httpClient) { _ghClient = ghClient; _azSettings = azOptions.Value; @@ -139,21 +139,6 @@ public async Task CreatePR(string org, string repo, long number, string branch) } } - public async Task MarkTaskComplete(string org, string repo, int commentId) - { - try - { - var comment = await _ghClient.Issue.Comment.Get(org, repo, commentId); - var updatedComment = comment.Body.Replace("[ ]", "[x]"); - await _ghClient.Issue.Comment.Update(org, repo, commentId, updatedComment); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error marking task complete"); - throw; - } - } - public async Task PostComment(string org, string repo, long issueNumber, string comment) { try @@ -222,8 +207,6 @@ public class FileResponse public interface IManageGithub { Task CreateIssue(string org, string repo, string input, string function, long parentNumber); - Task MarkTaskComplete(string org, string repo, int commentId); - Task CreatePR(string org, string repo, long number, string branch); Task CreateBranch(string org, string repo, string branch); Task CommitToBranch(string org, string repo, long parentNumber, long issueNumber, string rootDir, string branch);