clean code

This commit is contained in:
Haiping Chen 2024-09-05 14:11:05 -05:00
parent fc146d2225
commit 10e626ab8a
8 changed files with 28 additions and 366 deletions

View file

@ -17,6 +17,18 @@ public class UserRole
/// </summary>
public const string Client = "client";
/// <summary>
/// Back office operations
/// </summary>
public const string Operation = "operation";
public const string Technician = "technician";
/// <summary>
/// Software Developers, Data Engineer, Business Analyst
/// </summary>
public const string Engineer = "engineer";
/// <summary>
/// AI Assistant
/// </summary>

View file

@ -1,82 +0,0 @@
using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Templating;
namespace BotSharp.Core.Routing.Planning;
public partial class TwoStagePlanner
{
private async Task<FirstStagePlan[]> GetFirstStagePlanAsync(Agent router, string messageId, List<RoleDialogModel> dialogs)
{
var firstStagePlanPrompt = await GetFirstStagePlanPrompt(router);
var plan = new FirstStagePlan[0];
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
var provider = router.LlmConfig.Provider ?? "openai";
var model = llmProviderService.GetProviderModel(provider, router.LlmConfig.Model ?? "gpt-4o");
// chat completion
var completion = CompletionProvider.GetChatCompletion(_services,
provider: provider,
model: model.Name);
string text = string.Empty;
try
{
var response = await completion.GetChatCompletions(new Agent
{
Id = router.Id,
Name = nameof(TwoStagePlanner),
Instruction = firstStagePlanPrompt
}, dialogs);
text = response.Content;
plan = response.Content.JsonArrayContent<FirstStagePlan>();
}
catch (Exception ex)
{
_logger.LogError($"{ex.Message}: {text}");
}
return plan;
}
private async Task<string> GetFirstStagePlanPrompt(Agent router)
{
var template = router.Templates.First(x => x.Name == "two_stage.1st.plan").Content;
var responseFormat = JsonSerializer.Serialize(new FirstStagePlan
{
Parameters = new JsonDocument[]{ JsonDocument.Parse("{}") },
Results = new string[] { "" }
});
var relevantKnowledges = new List<string>();
var hooks = _services.GetServices<IKnowledgeHook>();
foreach (var hook in hooks)
{
var k = await hook.GetRelevantKnowledges();
relevantKnowledges.AddRange(k);
}
var render = _services.GetRequiredService<ITemplateRender>();
return render.Render(template, new Dictionary<string, object>
{
{ "response_format", responseFormat },
{ "relevant_knowledges", relevantKnowledges.ToArray() }
});
}
private string GetFirstStageNextPrompt(Agent router)
{
var template = router.Templates.First(x => x.Name == "first_stage.next").Content;
var responseFormat = JsonSerializer.Serialize(new FirstStagePlan
{
});
var render = _services.GetRequiredService<ITemplateRender>();
return render.Render(template, new Dictionary<string, object>
{
{ "response_format", responseFormat },
});
}
}

View file

@ -1,14 +0,0 @@
namespace BotSharp.Core.Routing.Planning;
public partial class TwoStagePlanner
{
public string GetContext()
{
var content = "";
foreach (var c in _executionContext)
{
content += $"* {c}\r\n";
}
return content;
}
}

View file

@ -1,83 +0,0 @@
using BotSharp.Abstraction.Agents.Models;
using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Templating;
namespace BotSharp.Core.Routing.Planning;
public partial class TwoStagePlanner
{
private async Task<SecondStagePlan[]> GetSecondStagePlanAsync(Agent router, string messageId, FirstStagePlan plan1st, List<RoleDialogModel> dialogs)
{
var secondStagePrompt = GetSecondStagePlanPrompt(router, plan1st);
var firstStageSystemPrompt = await GetFirstStagePlanPrompt(router);
var plan = new SecondStagePlan[0];
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
var model = llmProviderService.GetProviderModel("azure-openai", "gpt-4");
// chat completion
var completion = CompletionProvider.GetChatCompletion(_services,
provider: "azure-openai",
model: model.Name);
string text = string.Empty;
var conversations = dialogs.Where(x => x.Role != AgentRole.Function).ToList();
conversations.Add(new RoleDialogModel(AgentRole.User, secondStagePrompt)
{
CurrentAgentId = router.Id,
MessageId = messageId,
});
try
{
var response = await completion.GetChatCompletions(new Agent
{
Id = router.Id,
Name = nameof(TwoStagePlanner),
Instruction = firstStageSystemPrompt
}, conversations);
text = response.Content;
plan = response.Content.JsonArrayContent<SecondStagePlan>();
}
catch (Exception ex)
{
_logger.LogError($"{ex.Message}: {text}");
}
return plan;
}
private string GetSecondStageTaskPrompt(Agent router, SecondStagePlan plan)
{
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.2nd.task").Content;
var render = _services.GetRequiredService<ITemplateRender>();
return render.Render(template, new Dictionary<string, object>
{
{ "task_description", plan.Description },
{ "related_tables", plan.Tables },
{ "input_arguments", JsonSerializer.Serialize(plan.Parameters) },
{ "output_results", JsonSerializer.Serialize(plan.Results) },
});
}
private string GetSecondStagePlanPrompt(Agent router, FirstStagePlan plan)
{
var template = router.Templates.First(x => x.Name == "planner_prompt.two_stage.2nd.plan").Content;
var responseFormat = JsonSerializer.Serialize(new SecondStagePlan
{
Tool = "tool name if task solution provided",
Parameters = new JsonDocument[] { JsonDocument.Parse("{}") },
Results = new string[] { "" }
});
var context = GetContext();
var render = _services.GetRequiredService<ITemplateRender>();
return render.Render(template, new Dictionary<string, object>
{
{ "task_description", plan.Task },
{ "response_format", responseFormat }
});
}
}

View file

@ -1,136 +0,0 @@
using BotSharp.Abstraction.Routing.Planning;
namespace BotSharp.Core.Routing.Planning;
public partial class TwoStagePlanner : IRoutingPlaner
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public int MaxLoopCount => 100;
private bool _isTaskCompleted;
private string _md5;
private Queue<FirstStagePlan> _plan1st = new Queue<FirstStagePlan>();
private Queue<SecondStagePlan> _plan2nd = new Queue<SecondStagePlan>();
private List<string> _executionContext = new List<string>();
public TwoStagePlanner(IServiceProvider services, ILogger<TwoStagePlanner> logger)
{
_services = services;
_logger = logger;
}
public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs)
{
if (_plan1st.IsNullOrEmpty() && _plan2nd.IsNullOrEmpty())
{
FirstStagePlan[] items = await GetFirstStagePlanAsync(router, messageId, dialogs);
foreach (var item in items)
{
_plan1st.Enqueue(item);
};
}
// Get Second Stage Plan
if (_plan2nd.IsNullOrEmpty())
{
var plan1 = _plan1st.Dequeue();
if (plan1.ContainMultipleSteps)
{
SecondStagePlan[] items = await GetSecondStagePlanAsync(router, messageId, plan1, dialogs);
foreach (var item in items)
{
_plan2nd.Enqueue(item);
}
}
else
{
_plan2nd.Enqueue(new SecondStagePlan
{
Description = plan1.Task,
Tables = plan1.Tables,
Parameters = plan1.Parameters,
Results = plan1.Results,
});
}
}
var plan2 = _plan2nd.Dequeue();
var secondStagePrompt = GetSecondStageTaskPrompt(router, plan2);
var inst = new FunctionCallFromLlm
{
AgentName = "SQL Driver",
Response = secondStagePrompt,
Function = "route_to_agent"
};
inst.HandleDialogsByPlanner = true;
_isTaskCompleted = _plan1st.IsNullOrEmpty() && _plan2nd.IsNullOrEmpty();
return inst;
}
public List<RoleDialogModel> BeforeHandleContext(FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
{
var question = inst.Response;
if (_executionContext.Count > 0)
{
var content = GetContext();
question = $"CONTEXT:\r\n{content}\r\n" + inst.Response;
}
else
{
question = $"CONTEXT:\r\n{question}";
}
var taskAgentDialogs = new List<RoleDialogModel>
{
new RoleDialogModel(AgentRole.User, question)
{
MessageId = message.MessageId,
}
};
return taskAgentDialogs;
}
public bool AfterHandleContext(List<RoleDialogModel> dialogs, List<RoleDialogModel> taskAgentDialogs)
{
dialogs.AddRange(taskAgentDialogs.Skip(1));
// Keep execution context
_executionContext.Add(taskAgentDialogs.Last().Content);
return true;
}
public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
{
dialogs.Add(new RoleDialogModel(AgentRole.User, inst.Response)
{
MessageId = message.MessageId,
CurrentAgentId = router.Id
});
return true;
}
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
{
var context = _services.GetRequiredService<IRoutingContext>();
if (message.StopCompletion || _isTaskCompleted)
{
context.Empty(reason: $"Agent queue is cleared by {nameof(TwoStagePlanner)}");
return false;
}
var routing = _services.GetRequiredService<IRoutingService>();
routing.ResetRecursiveCounter();
return true;
}
}

View file

@ -1,6 +1,7 @@
using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Routing.Planning;
using BotSharp.Core.Routing.Planning;
using Microsoft.EntityFrameworkCore;
namespace BotSharp.Plugin.Planner.TwoStaging;
@ -8,7 +9,7 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
public int MaxLoopCount => 100;
public int MaxLoopCount => 10;
private bool _isTaskCompleted;
private Queue<FirstStagePlan> _plan1st = new Queue<FirstStagePlan>();
@ -16,7 +17,7 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
private List<string> _executionContext = new List<string>();
public TwoStageTaskPlanner(IServiceProvider services, ILogger<TwoStagePlanner> logger)
public TwoStageTaskPlanner(IServiceProvider services, ILogger<TwoStageTaskPlanner> logger)
{
_services = services;
_logger = logger;
@ -27,15 +28,14 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
// push agent to routing context
var routing = _services.GetRequiredService<IRoutingService>();
routing.Context.Push(BuiltInAgentId.Planner, "Make plan in TwoStage planner");
return new FunctionCallFromLlm
{
AgentName = "Planner",
UserGoal = "",
Response = "",
AgentName = router.Name,
Response = dialogs.Last().Content,
Function = "route_to_agent"
};
/*FirstStagePlan[] items = await GetFirstStagePlanAsync(router, messageId, dialogs);
foreach (var item in items)
@ -130,7 +130,13 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
if (message.StopCompletion || _isTaskCompleted)
{
context.Empty(reason: $"Agent queue is cleared by {nameof(TwoStagePlanner)}");
context.Empty(reason: $"Agent queue is cleared by {nameof(TwoStageTaskPlanner)}");
return false;
}
if (dialogs.Last().Role == AgentRole.Assistant)
{
context.Empty();
return false;
}
@ -149,47 +155,6 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
return content;
}
private async Task<FirstStagePlan[]> GetFirstStagePlanAsync(Agent router, string messageId, List<RoleDialogModel> dialogs)
{
/*var fn = _services.GetRequiredService<IRoutingService>();
await fn.InvokeFunction("plan_primary_stage", message);
var items = message.Content.JsonArrayContent<SecondStagePlan>();*/
var firstStagePlanPrompt = await GetFirstStagePlanPrompt(router);
var plan = new FirstStagePlan[0];
var llmProviderService = _services.GetRequiredService<ILlmProviderService>();
var provider = router.LlmConfig.Provider ?? "openai";
var model = llmProviderService.GetProviderModel(provider, router.LlmConfig.Model ?? "gpt-4o");
// chat completion
var completion = CompletionProvider.GetChatCompletion(_services,
provider: provider,
model: model.Name);
string text = string.Empty;
try
{
var response = await completion.GetChatCompletions(new Agent
{
Id = router.Id,
Name = nameof(TwoStagePlanner),
Instruction = firstStagePlanPrompt
}, dialogs);
text = response.Content;
plan = response.Content.JsonArrayContent<FirstStagePlan>();
}
catch (Exception ex)
{
_logger.LogError($"{ex.Message}: {text}");
}
return plan;
}
private async Task<string> GetFirstStagePlanPrompt(Agent router)
{
var template = router.Templates.First(x => x.Name == "two_stage.1st.plan").Content;
@ -257,7 +222,7 @@ public partial class TwoStageTaskPlanner : IRoutingPlaner
var response = await completion.GetChatCompletions(new Agent
{
Id = router.Id,
Name = nameof(TwoStagePlanner),
Name = nameof(TwoStageTaskPlanner),
Instruction = firstStageSystemPrompt
}, conversations);

View file

@ -8,7 +8,7 @@
"iconUrl": "https://e7.pngegg.com/pngimages/775/350/png-clipart-action-plan-computer-icons-plan-miscellaneous-text-thumbnail.png",
"disabled": false,
"isPublic": true,
"profiles": [ "tool" ],
"profiles": [ "planning" ],
"utilities": [ "two-stage-planner" ],
"llmConfig": {
"provider": "openai",

View file

@ -7,7 +7,7 @@
"updatedDateTime": "2023-11-15T13:49:00Z",
"disabled": false,
"isPublic": true,
"profiles": [ "tool", "sql" ],
"profiles": [ "database" ],
"llmConfig": {
"model": "gpt-4-0125",
"model3": "gpt-35-turbo-1106",