diff --git a/Program.cs b/Program.cs deleted file mode 100644 index 1a25475..0000000 --- a/Program.cs +++ /dev/null @@ -1,32 +0,0 @@ -// See https://aka.ms/new-console-template for more information -using Microsoft.Extensions.Configuration; -using Newtonsoft.Json; -using OpenAI.GPT3; -using OpenAI.GPT3.Managers; -using OpenAI.GPT3.ObjectModels; -using OpenAI.GPT3.ObjectModels.RequestModels; -using pinecone; -using pinecone.Models; -using System.Diagnostics; -using System.Security.AccessControl; -using Vector = pinecone.Models.Vector; - -namespace sharpagi; -public class Program -{ - - public static async Task Main(string[] args) - { - Console.WriteLine("Hello, World!"); - - - // Load environment variables from UserSecrets in Visual Studio - var builder = new ConfigurationBuilder() - .AddUserSecrets(); - var configuration = builder.Build(); - - Sharpagi sharpagi = new Sharpagi(); - await sharpagi.Main(configuration); - - } -} diff --git a/README.md b/README.md index 5bddfda..c93f4be 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,35 @@ SharpAGI is a C# library based on the BabyAGI project by [@yoheinakajima]. ## Quickstart -Use these settings in user secrets to run the code. +To create a Sharpagi client to run the agent in console application + +```csharp + Sharpagi sharpagi = new Sharpagi((output,consolecolor) => + { + if (consolecolor.HasValue) + { + Console.ForegroundColor = consolecolor.Value; + } + Console.WriteLine(output); + if (consolecolor.HasValue) + { + Console.ResetColor(); + } + }); + await sharpagi.Agent(configuration); +``` + +To cerate a Sharpagi client in other application types +```csharp + StringBuilder printOutput = new StringBuilder(); + Sharpagi sharpagi = new Sharpagi((output) => + { + printOutput.AppendLine(output); + }); + await sharpagi.Agent(configuration); +``` + +Use sharpagi_test console application to test the agi agent with this user secret ```csharp { @@ -23,8 +51,8 @@ Use these settings in user secrets to run the code. } ``` -License +## License This plugin is based on the BabyAGI project by @yoheinakajima (https://github.com/yoheinakajima). Please refer to their repository for licensing information. -Acknowledgments +## Acknowledgments This plugin is based on the BabyAGI project by [@yoheinakajima] A big thank you to the author for their original work. \ No newline at end of file diff --git a/sharpagi.sln b/sharpagi.sln index e75d196..862dd7e 100644 --- a/sharpagi.sln +++ b/sharpagi.sln @@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33530.505 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sharpagi", "sharpagi.csproj", "{4D2045ED-8623-41EC-9834-5ED038ED9EFF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sharpagi_test", "sharpagi_test\sharpagi_test.csproj", "{2E6C0B34-0CF8-4FEF-BAED-33B2DF419E2B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sharpagi", "sharpagi\sharpagi.csproj", "{7257BE27-97E9-4407-BB2E-5E13D7071005}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,10 +13,14 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4D2045ED-8623-41EC-9834-5ED038ED9EFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D2045ED-8623-41EC-9834-5ED038ED9EFF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D2045ED-8623-41EC-9834-5ED038ED9EFF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D2045ED-8623-41EC-9834-5ED038ED9EFF}.Release|Any CPU.Build.0 = Release|Any CPU + {2E6C0B34-0CF8-4FEF-BAED-33B2DF419E2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E6C0B34-0CF8-4FEF-BAED-33B2DF419E2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E6C0B34-0CF8-4FEF-BAED-33B2DF419E2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E6C0B34-0CF8-4FEF-BAED-33B2DF419E2B}.Release|Any CPU.Build.0 = Release|Any CPU + {7257BE27-97E9-4407-BB2E-5E13D7071005}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7257BE27-97E9-4407-BB2E-5E13D7071005}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7257BE27-97E9-4407-BB2E-5E13D7071005}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7257BE27-97E9-4407-BB2E-5E13D7071005}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sharpagi.cs b/sharpagi/sharpagi.cs similarity index 85% rename from sharpagi.cs rename to sharpagi/sharpagi.cs index a56e72d..106bcb6 100644 --- a/sharpagi.cs +++ b/sharpagi/sharpagi.cs @@ -12,6 +12,8 @@ namespace sharpagi { public class Sharpagi { + private readonly Action printOutput; + public string objective = string.Empty; public string openaiApiKey = string.Empty; public string openaiApiModel = string.Empty; @@ -23,12 +25,17 @@ public class Sharpagi public string initialTask = string.Empty; public string pineconeProjectName = string.Empty; - public Sharpagi() + public Sharpagi(Action outputCallback) { + printOutput = outputCallback; + } + public Sharpagi(Action outputCallback) + : this((output, color) => outputCallback(output)) + { } - public async Task Main(IConfiguration configuration) + public async Task Agent(IConfiguration configuration) { openaiApiKey = configuration["OPENAI_API_KEY"]; @@ -46,26 +53,18 @@ public async Task Main(IConfiguration configuration) } - // Check if we know what we are doing - Debug.Assert(!string.IsNullOrEmpty(openaiApiKey), "OPENAI_API_KEY environment variable is missing from UserSecrets"); - Debug.Assert(!string.IsNullOrEmpty(openaiApiModel), "OPENAI_API_MODEL environment variable is missing from UserSecrets"); + if(string.IsNullOrEmpty(openaiApiKey)) throw new ArgumentException("OPENAI_API_KEY environment variable is missing from UserSecrets"); + if(string.IsNullOrEmpty(openaiApiModel)) throw new ArgumentException("OPENAI_API_MODEL environment variable is missing from UserSecrets"); if (openaiApiModel.ToLower().Contains("gpt-4")) { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("*****USING GPT-4. POTENTIALLY EXPENSIVE. MONITOR YOUR COSTS*****"); - Console.ResetColor(); + printOutput("*****USING GPT-4. POTENTIALLY EXPENSIVE. MONITOR YOUR COSTS*****", ConsoleColor.Red); } // Print OBJECTIVE - Console.ForegroundColor = ConsoleColor.Blue; - Console.WriteLine("\n*****OBJECTIVE*****\n"); - Console.ResetColor(); - Console.WriteLine(objective); - - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine("\nInitial task: " + initialTask); - Console.ResetColor(); + printOutput("\n*****OBJECTIVE*****\n", ConsoleColor.Blue); + printOutput(objective, null); + printOutput("\nInitial task: " + initialTask, ConsoleColor.Yellow); // Create Pinecone index var indexes = await pinecone.ListIndexes(); @@ -98,28 +97,23 @@ await pinecone.CreateIndex(new CreateRequest if (taskList.Count > 0) { // Print the task list - Console.ForegroundColor = ConsoleColor.Magenta; - Console.WriteLine("\n*****TASK LIST*****\n"); - Console.ResetColor(); + printOutput("\n*****TASK LIST*****\n", ConsoleColor.Magenta); + foreach (var t in taskList) { - Console.WriteLine(t["task_id"] + ": " + t["task_name"]); + printOutput(t["task_id"] + ": " + t["task_name"], null); } // Step 1: Pull the first task var task = taskList.Dequeue(); - Console.ForegroundColor = ConsoleColor.Green; - Console.WriteLine("\n*****NEXT TASK*****\n"); - Console.ResetColor(); - Console.WriteLine(task["task_id"] + ": " + task["task_name"]); + printOutput("\n*****NEXT TASK*****\n", ConsoleColor.Green); + printOutput(task["task_id"] + ": " + task["task_name"], null); // Send to execution function to complete the task based on the context var result = await ExecutionAgent(objective, task["task_name"]); var thisTaskId = int.Parse(task["task_id"]); - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine("\n*****TASK RESULT*****\n"); - Console.ResetColor(); - Console.WriteLine(result); + printOutput("\n*****TASK RESULT*****\n", ConsoleColor.Yellow); + printOutput(result?.ToString(), null); // Step 2: Enrich result and store in Pinecone @@ -163,6 +157,7 @@ await pinecone.CreateIndex(new CreateRequest Thread.Sleep(1000); // Sleep before checking the task list again } } + public void AddTask(Dictionary task) { taskList.Enqueue(task); @@ -209,7 +204,7 @@ public async Task GetAdaEmbedding(object data) { throw new Exception("Unknown Error"); } - Console.WriteLine($"{embeddingResult.Error.Code}: {embeddingResult.Error.Message}"); + printOutput($"{embeddingResult.Error.Code}: {embeddingResult.Error.Message}", null); } return null; } @@ -264,15 +259,15 @@ public async Task openai_call(string prompt, string model = "gpt-3.5-tur return response.Choices.FirstOrDefault()?.Message.Content.Trim() ?? string.Empty; else { - if (response.Error.Message.Contains("ratelimit", StringComparison.OrdinalIgnoreCase)) - await Task.Delay(10000); + if (response.Error.Message.Contains("rate limit", StringComparison.OrdinalIgnoreCase)) + await Task.Delay(20000); } } } - catch (Exception ex) when (ex.Message.Contains("ratelimit")) + catch (Exception ex) when (ex.Message.Contains("rate limit")) { - Console.WriteLine("The OpenAI API rate limit has been exceeded. Waiting 10 seconds and trying again."); - await Task.Delay(10000); // Wait 10 seconds and try again + printOutput("The OpenAI API rate limit has been exceeded. Waiting 10 seconds and trying again.", null); + await Task.Delay(20000); // Wait 10 seconds and try again } } } @@ -290,7 +285,7 @@ public async Task PrioritizationAgent(int thisTaskId) Start the task list with number {nextTaskId}."; var response = await openai_call(prompt); var newTasks = response.Split('\n'); - taskList = new Queue>(newTasks.Select((t, index) => new Dictionary { { "task_id", (index + nextTaskId).ToString() }, { "task_name", (t.Trim().Length>=2)?t.Trim().Substring(2):t.Trim() } })); + taskList = new Queue>(newTasks.Select((t, index) => new Dictionary { { "task_id", (index + nextTaskId).ToString() }, { "task_name", (t.Trim().Length >= 2) ? t.Trim().Substring(2) : t.Trim() } })); } public async Task<(string stdout, string stderr)> RunCommandAsync(string command) diff --git a/sharpagi.csproj b/sharpagi/sharpagi.csproj similarity index 70% rename from sharpagi.csproj rename to sharpagi/sharpagi.csproj index f76b9ac..c4772e3 100644 --- a/sharpagi.csproj +++ b/sharpagi/sharpagi.csproj @@ -1,12 +1,21 @@ - Exe + Library net6.0 enable enable 50c01620-9aba-4847-9fa1-0f06066b9d14 + + + + + + + + + diff --git a/sharpagi_test/Program.cs b/sharpagi_test/Program.cs new file mode 100644 index 0000000..c6fa544 --- /dev/null +++ b/sharpagi_test/Program.cs @@ -0,0 +1,23 @@ +// See https://aka.ms/new-console-template for more information +using Microsoft.Extensions.Configuration; +using sharpagi; + +Console.WriteLine("Hello, World!"); +// Load environment variables from UserSecrets in Visual Studio +var builder = new ConfigurationBuilder() + .AddUserSecrets(); +var configuration = builder.Build(); + +Sharpagi sharpagi = new Sharpagi((output, consolecolor) => +{ + if (consolecolor.HasValue) + { + Console.ForegroundColor = consolecolor.Value; + } + Console.WriteLine(output); + if (consolecolor.HasValue) + { + Console.ResetColor(); + } +}); +await sharpagi.Agent(configuration); diff --git a/sharpagi_test/sharpagi_test.csproj b/sharpagi_test/sharpagi_test.csproj new file mode 100644 index 0000000..afcc85c --- /dev/null +++ b/sharpagi_test/sharpagi_test.csproj @@ -0,0 +1,23 @@ + + + + Exe + net6.0 + enable + enable + 79855906-63dd-4e12-b308-95501dab288a + + + + + + + + + + + + + + +