BotSharp/src/Infrastructure/BotSharp.Core/Routing/Reasoning/HFReasoner.cs

124 lines
4.3 KiB
C#
Raw Normal View History

2024-11-26 00:06:26 +00:00
/*****************************************************************************
Copyright 2024 Written by Haiping Chen. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/
using BotSharp.Abstraction.Routing.Reasoning;
2023-10-28 20:59:26 +00:00
using BotSharp.Abstraction.Templating;
2024-11-26 00:06:26 +00:00
namespace BotSharp.Core.Routing.Reasoning;
2023-10-28 20:59:26 +00:00
2023-10-30 16:48:18 +00:00
/// <summary>
2024-11-26 00:06:26 +00:00
/// Human feedback based reasoner
2023-10-30 16:48:18 +00:00
/// </summary>
2024-11-26 00:06:26 +00:00
public class HFReasoner : IRoutingReasoner
2023-10-28 20:59:26 +00:00
{
private readonly IServiceProvider _services;
private readonly ILogger _logger;
2024-11-26 00:06:26 +00:00
public HFReasoner(IServiceProvider services, ILogger<HFReasoner> logger)
2023-10-28 20:59:26 +00:00
{
_services = services;
_logger = logger;
}
2024-02-02 04:16:57 +00:00
public async Task<FunctionCallFromLlm> GetNextInstruction(Agent router, string messageId, List<RoleDialogModel> dialogs)
2023-10-28 20:59:26 +00:00
{
var next = GetNextStepPrompt(router);
RoleDialogModel response = default;
var inst = new FunctionCallFromLlm();
var completion = CompletionProvider.GetChatCompletion(_services,
2023-12-13 18:12:25 +00:00
provider: router?.LlmConfig?.Provider,
model: router?.LlmConfig?.Model);
2023-10-28 20:59:26 +00:00
int retryCount = 0;
while (retryCount < 3)
{
try
{
2024-02-02 04:16:57 +00:00
dialogs = new List<RoleDialogModel>
2023-10-28 20:59:26 +00:00
{
2023-10-29 01:54:10 +00:00
new RoleDialogModel(AgentRole.User, next)
2023-10-30 16:48:18 +00:00
{
2024-11-26 00:06:26 +00:00
FunctionName = nameof(HFReasoner),
2023-10-30 16:48:18 +00:00
MessageId = messageId
}
2023-11-01 01:48:12 +00:00
};
2024-01-14 04:48:26 +00:00
response = await completion.GetChatCompletions(router, dialogs);
2023-10-28 20:59:26 +00:00
inst = response.Content.JsonContent<FunctionCallFromLlm>();
break;
}
catch (Exception ex)
{
_logger.LogError($"{ex.Message}: {response.Content}");
inst.Function = "response_to_user";
inst.Response = ex.Message;
inst.AgentName = "Router";
}
finally
{
retryCount++;
}
}
2024-07-11 21:43:03 +00:00
// Fix LLM malformed response
2024-11-26 00:06:26 +00:00
ReasonerHelper.FixMalformedResponse(_services, inst);
2024-07-11 21:43:03 +00:00
2023-10-28 20:59:26 +00:00
return inst;
}
2024-02-19 22:55:41 +00:00
public async Task<bool> AgentExecuting(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
2023-10-29 01:54:10 +00:00
{
2023-10-30 16:48:18 +00:00
if (!string.IsNullOrEmpty(inst.AgentName))
{
var db = _services.GetRequiredService<IBotSharpRepository>();
2023-11-27 22:20:49 +00:00
var filter = new AgentFilter { AgentName = inst.AgentName };
var agent = db.GetAgents(filter).FirstOrDefault();
2023-10-29 01:54:10 +00:00
2024-02-28 16:21:14 +00:00
var context = _services.GetRequiredService<IRoutingContext>();
2024-07-11 21:43:03 +00:00
context.Push(agent.Id, reason: inst.NextActionReason);
// Set user content as Planner's question
message.FunctionName = inst.Function;
message.FunctionArgs = inst.Arguments == null ? "{}" : JsonSerializer.Serialize(inst.Arguments);
2023-10-30 16:48:18 +00:00
}
2023-10-29 01:54:10 +00:00
return true;
}
2024-02-19 22:55:41 +00:00
public async Task<bool> AgentExecuted(Agent router, FunctionCallFromLlm inst, RoleDialogModel message, List<RoleDialogModel> dialogs)
2023-10-28 20:59:26 +00:00
{
2024-02-28 16:21:14 +00:00
var context = _services.GetRequiredService<IRoutingContext>();
2024-11-26 00:06:26 +00:00
context.Empty(reason: $"Agent queue is cleared by {nameof(HFReasoner)}");
2023-10-28 20:59:26 +00:00
return true;
}
private string GetNextStepPrompt(Agent router)
{
2024-11-26 00:06:26 +00:00
var template = router.Templates.First(x => x.Name == "reasoner.hf").Content;
2023-10-28 20:59:26 +00:00
var render = _services.GetRequiredService<ITemplateRender>();
// update states
var conv = _services.GetRequiredService<IConversationService>();
foreach (var t in conv.States.GetStates())
{
router.TemplateDict[t.Key] = t.Value;
}
2023-11-01 01:48:12 +00:00
var prompt = render.Render(template, router.TemplateDict);
return prompt.Trim();
2023-10-28 20:59:26 +00:00
}
}