mirror of
https://github.com/microsoft/autogen.git
synced 2026-04-20 03:02:16 -04:00
iterating toward dynmamic activities from skills
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -487,4 +487,7 @@ $RECYCLE.BIN/
|
||||
elsa.sqlite.*
|
||||
|
||||
# env files
|
||||
.env
|
||||
.env
|
||||
|
||||
# ignore local elsa-core src
|
||||
elsa-core/
|
||||
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Workflows.Core;
|
||||
using Elsa.Workflows.Core.Contracts;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
using Elsa.Workflows.Management.Extensions;
|
||||
using Elsa.Workflows.Core.Attributes;
|
||||
using Elsa.Workflows.Core.Models;
|
||||
using Elsa.Expressions.Models;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Connectors.Memory.Qdrant;
|
||||
using Microsoft.SemanticKernel.Connectors.AI.OpenAI.TextEmbedding;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
using Microsoft.SemanticKernel.Orchestration;
|
||||
using Microsoft.SemanticKernel.Reliability;
|
||||
using Microsoft.SKDevTeam;
|
||||
|
||||
namespace Elsa.SemanticKernel;
|
||||
|
||||
//<summary>
|
||||
// Loads the Semantic Kernel skills and then generates activites for each skill
|
||||
//</summary>
|
||||
public class SemanticKernelActivityProvider : IActivityProvider
|
||||
{
|
||||
private readonly IActivityFactory _activityFactory;
|
||||
private readonly IActivityDescriber _activityDescriber;
|
||||
|
||||
public SemanticKernelActivityProvider(IActivityFactory activityFactory, IActivityDescriber activityDescriber)
|
||||
{
|
||||
_activityFactory = activityFactory;
|
||||
_activityDescriber = activityDescriber;
|
||||
}
|
||||
public async ValueTask<IEnumerable<ActivityDescriptor>> GetDescriptorsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
//get a list of skills in the assembly
|
||||
var skills = await LoadSkillsFromAssemblyAsync("skills");
|
||||
var descriptors = new List<ActivityDescriptor>();
|
||||
foreach (var skill in skills)
|
||||
{
|
||||
//var descriptor = await CreateActivityDescriptors(skill, cancellationToken);
|
||||
// descriptors.Add(descriptor);
|
||||
}
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// Gets a list of the skills in the assembly
|
||||
///</summary>
|
||||
private async Task<IEnumerable<string>> LoadSkillsFromAssemblyAsync(string assemblyName)
|
||||
{
|
||||
var skills = new List<string>();
|
||||
var assembly = Assembly.Load(assemblyName);
|
||||
//IEnumerable<Type> skillTypes = GetTypesInNamespace(assembly, "skills");
|
||||
Type[] skillTypes = assembly.GetTypes().ToArray();
|
||||
foreach(Type skillType in skillTypes)
|
||||
{
|
||||
Console.WriteLine($"Found type: {assembly.FullName}.{skillType.Namespace}.{skillType.Name}");
|
||||
if(skillType.Namespace.Equals("Microsoft.SKDevTeam"))
|
||||
{
|
||||
skills.Add(skillType.Name);
|
||||
|
||||
Console.WriteLine($"Added skill: {skillType.Name}");
|
||||
}
|
||||
|
||||
}
|
||||
return skills;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private IEnumerable<Type> GetTypesInNamespace(Assembly assembly, string nameSpace)
|
||||
{
|
||||
return
|
||||
assembly.GetTypes()
|
||||
.Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,21 @@ using Microsoft.SemanticKernel.Connectors.AI.OpenAI.TextEmbedding;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
using Microsoft.SemanticKernel.Orchestration;
|
||||
using Microsoft.SemanticKernel.Reliability;
|
||||
namespace Elsa.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.SkillDefinition;
|
||||
using Microsoft.SKDevTeam;
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using skills;
|
||||
|
||||
|
||||
namespace Elsa.SemanticKernel;
|
||||
|
||||
/// <summary>
|
||||
/// Invoke a Semantic Kernel skill.
|
||||
@@ -53,11 +63,11 @@ public class SemanticKernelSkill : CodeActivity<string>
|
||||
DefaultValue = "ChatCompletion")]
|
||||
public Input<string> FunctionName { get; set; }
|
||||
|
||||
/* [Input(
|
||||
Description = "Mockup - don't actually call the AI, just output the prompts",
|
||||
UIHint = InputUIHints.Checkbox,
|
||||
DefaultValue = false)]
|
||||
public Input<bool> Mockup { get; set; } */
|
||||
/* [Input(
|
||||
Description = "Mockup - don't actually call the AI, just output the prompts",
|
||||
UIHint = InputUIHints.Checkbox,
|
||||
DefaultValue = false)]
|
||||
public Input<bool> Mockup { get; set; } */
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask ExecuteAsync(ActivityExecutionContext workflowContext)
|
||||
@@ -116,20 +126,95 @@ public class SemanticKernelSkill : CodeActivity<string>
|
||||
} */
|
||||
|
||||
var skillConfig = SemanticFunctionConfig.ForSkillAndFunction(skillName, functionName);
|
||||
var function = kernel.CreateSemanticFunction(skillConfig.PromptTemplate, skillConfig.Name, skillConfig.SkillName,
|
||||
skillConfig.Description, skillConfig.MaxTokens, skillConfig.Temperature,
|
||||
skillConfig.TopP, skillConfig.PPenalty, skillConfig.FPenalty);
|
||||
|
||||
var context = new ContextVariables();
|
||||
context.Set("input", prompt);
|
||||
|
||||
/* var function = kernel.CreateSemanticFunction(skillConfig.PromptTemplate, skillConfig.Name, skillConfig.SkillName,
|
||||
skillConfig.Description, skillConfig.MaxTokens, skillConfig.Temperature,
|
||||
skillConfig.TopP, skillConfig.PPenalty, skillConfig.FPenalty); */
|
||||
|
||||
var contextVars = new ContextVariables();
|
||||
contextVars.Set("input", prompt);
|
||||
SKContext context = kernel.CreateNewContext();
|
||||
|
||||
var theSkills = LoadSkillsFromAssemblyAsync("skills", kernel);
|
||||
var functionsAvailable = context.Skills.GetFunctionsView();
|
||||
|
||||
var list = new StringBuilder();
|
||||
foreach (KeyValuePair<string, List<FunctionView>> skill in functionsAvailable.SemanticFunctions)
|
||||
{
|
||||
Console.WriteLine($"Skill: {skill.Key}");
|
||||
foreach (FunctionView func in skill.Value)
|
||||
{
|
||||
// Function description
|
||||
if (func.Description != null)
|
||||
{
|
||||
list.AppendLine($"// {func.Description}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("{0}.{1} is missing a description", func.SkillName, func.Name);
|
||||
list.AppendLine($"// Function {func.SkillName}.{func.Name}.");
|
||||
}
|
||||
|
||||
// Function name
|
||||
list.AppendLine($"{func.SkillName}.{func.Name}");
|
||||
|
||||
// Function parameters
|
||||
foreach (var p in func.Parameters)
|
||||
{
|
||||
var description = string.IsNullOrEmpty(p.Description) ? p.Name : p.Description;
|
||||
var defaultValueString = string.IsNullOrEmpty(p.DefaultValue) ? string.Empty : $" (default value: {p.DefaultValue})";
|
||||
list.AppendLine($"Parameter \"{p.Name}\": {description} {defaultValueString}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"List of all skills ----- {list.ToString()}");
|
||||
|
||||
//context.Set("wafContext", wafContext);
|
||||
|
||||
SKContext answer = await kernel.RunAsync(context, function).ConfigureAwait(false);
|
||||
SKContext answer = await kernel.RunAsync(contextVars, function).ConfigureAwait(false);
|
||||
string result = answer.Result;
|
||||
|
||||
Console.WriteLine(info);
|
||||
|
||||
|
||||
workflowContext.SetResult(result);
|
||||
}
|
||||
}
|
||||
///<summary>
|
||||
/// Gets a list of the skills in the assembly
|
||||
///</summary>
|
||||
private IEnumerable<string> LoadSkillsFromAssemblyAsync(string assemblyName, IKernel kernel)
|
||||
{
|
||||
var skills = new List<string>();
|
||||
var assembly = Assembly.Load(assemblyName);
|
||||
Type[] skillTypes = assembly.GetTypes().ToArray();
|
||||
foreach (Type skillType in skillTypes)
|
||||
{
|
||||
if (skillType.Namespace.Equals("Microsoft.SKDevTeam"))
|
||||
{
|
||||
skills.Add(skillType.Name);
|
||||
var functions = skillType.GetFields();
|
||||
foreach (var function in functions)
|
||||
{
|
||||
string field = function.FieldType.ToString();
|
||||
if (field.Equals("Microsoft.SKDevTeam.SemanticFunctionConfig"))
|
||||
{
|
||||
var skillConfig = SemanticFunctionConfig.ForSkillAndFunction(skillType.Name, function.Name);
|
||||
var skfunc = kernel.CreateSemanticFunction(
|
||||
skillConfig.PromptTemplate,
|
||||
skillConfig.Name,
|
||||
skillConfig.SkillName,
|
||||
skillConfig.Description,
|
||||
skillConfig.MaxTokens,
|
||||
skillConfig.Temperature,
|
||||
skillConfig.TopP,
|
||||
skillConfig.PPenalty,
|
||||
skillConfig.FPenalty);
|
||||
|
||||
Console.WriteLine($"SK Added function: {skfunc.SkillName}.{skfunc.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return skills;
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,15 @@
|
||||
<Description>
|
||||
Activities for calling Semantic Kernel SDK
|
||||
</Description>
|
||||
<PackageTags>elsa module semantic kerne activities</PackageTags>
|
||||
<PackageTags>elsa module semantic kernel activities</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Elsa" Version="3.0.0-preview.541" />
|
||||
<PackageReference Include="Elsa" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Http" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Workflows.Api" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Workflows.Core" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Workflows.Management" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Elsa" Version="3.0.0-preview.541" />
|
||||
<PackageReference Include="Elsa.EntityFrameworkCore" Version="3.0.0-preview.541" />
|
||||
<PackageReference Include="Elsa.EntityFrameworkCore.Sqlite" Version="3.0.0-preview.541" />
|
||||
<PackageReference Include="Elsa.Http" Version="3.0.0-preview.541" />
|
||||
<PackageReference Include="Elsa.Identity" Version="3.0.0-preview.541" />
|
||||
<PackageReference Include="Elsa.Workflows.Api" Version="3.0.0-preview.541" />
|
||||
<PackageReference Include="Elsa.Workflows.Designer" Version="3.0.0-preview.541" /><!--
|
||||
<PackageReference Include="Elsa" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.EntityFrameworkCore" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.EntityFrameworkCore.Sqlite" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Http" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Identity" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Workflows.Api" Version="3.0.0-preview.552" />
|
||||
<PackageReference Include="Elsa.Workflows.Designer" Version="3.0.0-preview.552" /><!--
|
||||
<PackageReference Include="Elsa.EntityFrameworkCore" Version="3.0.0-rc1" />
|
||||
<PackageReference Include="Elsa.EntityFrameworkCore.Sqlite" Version="3.0.0-rc1" />
|
||||
<PackageReference Include="Elsa.Http" Version="3.0.0-rc1" />
|
||||
|
||||
@@ -7,7 +7,8 @@ using Microsoft.SemanticKernel.Connectors.Memory.Qdrant;
|
||||
using Microsoft.SemanticKernel.Memory;
|
||||
using Microsoft.SemanticKernel.Orchestration;
|
||||
using Microsoft.SemanticKernel.Reliability;
|
||||
using skills;
|
||||
using Microsoft.SKDevTeam;
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
@@ -34,7 +35,7 @@ class Program
|
||||
|
||||
var pmCommand = new Command("pm", "Commands for the PM team");
|
||||
var pmReadmeCommand = new Command("readme", "Produce a Readme for a given input");
|
||||
pmReadmeCommand.SetHandler(async (file, maxRetry) => await CallWithFile<string>(nameof(PM), PM.Readme , file.FullName, maxRetry), fileOption, maxRetryOption);
|
||||
pmReadmeCommand.SetHandler(async (file, maxRetry) => await CallWithFile<string>(nameof(PM), PM.Readme, file.FullName, maxRetry), fileOption, maxRetryOption);
|
||||
|
||||
var pmBootstrapCommand = new Command("bootstrap", "Bootstrap a project for a given input");
|
||||
pmBootstrapCommand.SetHandler(async (file, maxRetry) => await CallWithFile<string>(nameof(PM), PM.BootstrapProject, file.FullName, maxRetry), fileOption, maxRetryOption);
|
||||
@@ -51,7 +52,7 @@ class Program
|
||||
var devPlanCommand = new Command("plan", "Implement the module for a given input");
|
||||
devPlanCommand.SetHandler(async (file, maxRetry) => await CallWithFile<string>(nameof(Developer), Developer.Implement, file.FullName, maxRetry), fileOption, maxRetryOption);
|
||||
devCommand.AddCommand(devPlanCommand);
|
||||
|
||||
|
||||
rootCommand.AddCommand(pmCommand);
|
||||
rootCommand.AddCommand(devleadCommand);
|
||||
rootCommand.AddCommand(devCommand);
|
||||
@@ -67,7 +68,7 @@ class Program
|
||||
|
||||
Console.WriteLine($"Using output directory: {outputPath}");
|
||||
|
||||
var readme = await CallWithFile<string>(nameof(PM), PM.Readme , file, maxRetry);
|
||||
var readme = await CallWithFile<string>(nameof(PM), PM.Readme, file, maxRetry);
|
||||
string readmeFile = Path.Combine(outputPath.FullName, "README.md");
|
||||
await SaveToFile(readmeFile, readme);
|
||||
Console.WriteLine($"Saved README to {readmeFile}");
|
||||
@@ -83,12 +84,13 @@ class Program
|
||||
|
||||
var implementationTasks = plan.steps.SelectMany(
|
||||
(step) => step.subtasks.Select(
|
||||
async (subtask) => {
|
||||
async (subtask) =>
|
||||
{
|
||||
Console.WriteLine($"Implementing {step.step}-{subtask.subtask}");
|
||||
var implementationResult = string.Empty;
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
implementationResult = await CallFunction<string>(nameof(Developer), Developer.Implement, subtask.LLM_prompt, maxRetry);
|
||||
break;
|
||||
@@ -105,7 +107,8 @@ class Program
|
||||
}
|
||||
await sandboxSkill.RunInDotnetAlpineAsync(implementationResult);
|
||||
await SaveToFile(Path.Combine(outputPath.FullName, $"{step.step}-{subtask.subtask}.sh"), implementationResult);
|
||||
return implementationResult; }));
|
||||
return implementationResult;
|
||||
}));
|
||||
await Task.WhenAll(implementationTasks);
|
||||
}
|
||||
|
||||
@@ -115,8 +118,8 @@ class Program
|
||||
}
|
||||
|
||||
public static async Task<T> CallWithFile<T>(string skillName, string functionName, string filePath, int maxRetry)
|
||||
{
|
||||
if(!File.Exists(filePath))
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException($"File not found: {filePath}", filePath);
|
||||
var input = File.ReadAllText(filePath);
|
||||
return await CallFunction<T>(skillName, functionName, input, maxRetry);
|
||||
@@ -173,10 +176,11 @@ class Program
|
||||
var answer = await kernel.RunAsync(context, function).ConfigureAwait(false);
|
||||
var result = typeof(T) != typeof(string) ? JsonSerializer.Deserialize<T>(answer.ToString()) : (T)(object)answer.ToString();
|
||||
//Console.WriteLine(answer);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PM { public static string Readme = "Readme"; public static string BootstrapProject = "BootstrapProject"; }
|
||||
public static class DevLead { public static string Plan="Plan"; }
|
||||
public static class Developer { public static string Implement="Implement"; public static string Improve="Improve";}
|
||||
public static class DevLead { public static string Plan = "Plan"; }
|
||||
public static class Developer { public static string Implement = "Implement"; public static string Improve = "Improve"; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace skills;
|
||||
namespace Microsoft.SKDevTeam;
|
||||
public static class Chat
|
||||
{
|
||||
public static SemanticFunctionConfig ChatCompletion = new SemanticFunctionConfig
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace skills;
|
||||
namespace Microsoft.SKDevTeam;
|
||||
public static class DevLead {
|
||||
public static SemanticFunctionConfig Plan = new SemanticFunctionConfig
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace skills;
|
||||
namespace Microsoft.SKDevTeam;
|
||||
public static class Developer {
|
||||
public static SemanticFunctionConfig Implement = new SemanticFunctionConfig
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace skills;
|
||||
namespace Microsoft.SKDevTeam;
|
||||
public static class PM
|
||||
{
|
||||
public static SemanticFunctionConfig BootstrapProject = new SemanticFunctionConfig
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace skills;
|
||||
namespace Microsoft.SKDevTeam;
|
||||
|
||||
public class SemanticFunctionConfig
|
||||
{
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>skills</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user