Merge branch 'master' of https://github.com/SciSharp/BotSharp into bugfix/fix-log-order
This commit is contained in:
commit
3dbdcb595d
|
|
@ -37,6 +37,13 @@ public interface IAgentService
|
|||
|
||||
Task<bool> DeleteAgent(string id);
|
||||
Task UpdateAgent(Agent agent, AgentField updateField);
|
||||
|
||||
/// <summary>
|
||||
/// Path existing templates of agent, cannot create new or delete templates
|
||||
/// </summary>
|
||||
/// <param name="agent"></param>
|
||||
/// <returns></returns>
|
||||
Task<string> PatchAgentTemplate(Agent agent);
|
||||
Task<string> UpdateAgentFromFile(string id);
|
||||
string GetDataDir();
|
||||
string GetAgentDataDir(string agentId);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ public class AgentSettings
|
|||
public string DataDir { get; set; } = string.Empty;
|
||||
public string TemplateFormat { get; set; } = "liquid";
|
||||
public string HostAgentId { get; set; } = string.Empty;
|
||||
public bool EnableTranslator { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// This is the default LLM config for agent
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Repositories.Models;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
|
|
@ -35,6 +34,7 @@ public interface IBotSharpRepository
|
|||
bool DeleteAgent(string agentId);
|
||||
List<string> GetAgentResponses(string agentId, string prefix, string intent);
|
||||
string GetAgentTemplate(string agentId, string templateName);
|
||||
bool PatchAgentTemplate(string agentId, AgentTemplate template);
|
||||
#endregion
|
||||
|
||||
#region Agent Task
|
||||
|
|
|
|||
|
|
@ -50,9 +50,6 @@ public class RoutingArgs
|
|||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string UserGoal { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("language")]
|
||||
public string Language { get; set; } = LanguageType.ENGLISH;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var route = string.IsNullOrEmpty(AgentName) ? "" : $"<Route to {AgentName.ToUpper()} because {NextActionReason}>";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
namespace BotSharp.Abstraction.Translation.Models;
|
||||
|
||||
public class TranslationOutput
|
||||
{
|
||||
[JsonPropertyName("input_lang")]
|
||||
public string InputLanguage { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("output_lang")]
|
||||
public string OutputLanguage { get; set; } = LanguageType.ENGLISH;
|
||||
|
||||
[JsonPropertyName("texts")]
|
||||
public string[] Texts { get; set; } = Array.Empty<string>();
|
||||
}
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Enums;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using System.IO;
|
||||
|
|
@ -106,6 +103,59 @@ public partial class AgentService
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> PatchAgentTemplate(Agent agent)
|
||||
{
|
||||
var patchResult = string.Empty;
|
||||
if (agent == null || agent.Templates.IsNullOrEmpty())
|
||||
{
|
||||
patchResult = $"Null agent instance or empty input templates";
|
||||
_logger.LogWarning(patchResult);
|
||||
return patchResult;
|
||||
}
|
||||
|
||||
var record = _db.GetAgent(agent.Id);
|
||||
if (record == null)
|
||||
{
|
||||
patchResult = $"Cannot find agent {agent.Id}";
|
||||
_logger.LogWarning(patchResult);
|
||||
return patchResult;
|
||||
}
|
||||
|
||||
var successTemplates = new List<string>();
|
||||
var failTemplates = new List<string>();
|
||||
foreach (var template in agent.Templates)
|
||||
{
|
||||
if (template == null) continue;
|
||||
|
||||
var result = _db.PatchAgentTemplate(agent.Id, template);
|
||||
if (result)
|
||||
{
|
||||
successTemplates.Add(template.Name);
|
||||
_logger.LogInformation($"Template {template.Name} is updated successfully!");
|
||||
}
|
||||
else
|
||||
{
|
||||
failTemplates.Add(template.Name);
|
||||
_logger.LogWarning($"Template {template.Name} is failed to be updated!");
|
||||
}
|
||||
}
|
||||
|
||||
Utilities.ClearCache();
|
||||
|
||||
if (!successTemplates.IsNullOrEmpty())
|
||||
{
|
||||
patchResult += $"Success templates:\n{string.Join('\n', successTemplates)}\n\n";
|
||||
}
|
||||
|
||||
if (!failTemplates.IsNullOrEmpty())
|
||||
{
|
||||
patchResult += $"Failed templates:\n{string.Join('\n', failTemplates)}";
|
||||
}
|
||||
|
||||
return patchResult;
|
||||
}
|
||||
|
||||
private Agent? FetchAgentFileById(string agentId, string filePath)
|
||||
{
|
||||
if (!Directory.Exists(filePath)) return null;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
public string GetAgentTemplate(string agentId, string templateName)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public bool PatchAgentTemplate(string agentId, AgentTemplate template)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public List<string> GetAgentResponses(string agentId, string prefix, string intent)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
|
|
|
|||
|
|
@ -401,6 +401,25 @@ namespace BotSharp.Core.Repository
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
public bool PatchAgentTemplate(string agentId, AgentTemplate template)
|
||||
{
|
||||
if (string.IsNullOrEmpty(agentId) || template == null) return false;
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId, "templates");
|
||||
if (!Directory.Exists(dir)) return false;
|
||||
|
||||
var foundTemplate = Directory.GetFiles(dir).FirstOrDefault(f =>
|
||||
{
|
||||
var fileName = Path.GetFileNameWithoutExtension(f);
|
||||
var extension = Path.GetExtension(f).Substring(1);
|
||||
return fileName.IsEqualTo(template.Name) && extension.IsEqualTo(_agentSettings.TemplateFormat);
|
||||
});
|
||||
|
||||
if (foundTemplate == null) return false;
|
||||
|
||||
File.WriteAllText(foundTemplate, template.Content);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void BulkInsertAgents(List<Agent> agents)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,10 +28,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
|
|||
required: true),
|
||||
new ParameterPropertyDef("is_new_task",
|
||||
"whether the user is requesting a new task that is different from the previous topic.",
|
||||
type: "boolean"),
|
||||
new ParameterPropertyDef("language",
|
||||
"User preferred language, considering the whole conversation. Language could be English, Spanish or Chinese.",
|
||||
required: true)
|
||||
type: "boolean")
|
||||
};
|
||||
|
||||
public RouteToAgentRoutingHandler(IServiceProvider services, ILogger<RouteToAgentRoutingHandler> logger, RoutingSettings settings)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public partial class RoutingService
|
|||
role = agent.Name;
|
||||
}
|
||||
|
||||
conversation += $"{role}: {dialog.Payload ?? dialog.SecondaryContent ?? dialog.Content}\r\n";
|
||||
conversation += $"{role}: {dialog.Payload ?? dialog.Content}\r\n";
|
||||
}
|
||||
|
||||
return conversation;
|
||||
|
|
|
|||
|
|
@ -82,26 +82,29 @@ public partial class RoutingService : IRoutingService
|
|||
|
||||
_context.Push(_router.Id);
|
||||
|
||||
// Handle multi-language for input
|
||||
var agentSettings = _services.GetRequiredService<AgentSettings>();
|
||||
if (agentSettings.EnableTranslator)
|
||||
{
|
||||
var translator = _services.GetRequiredService<ITranslationService>();
|
||||
|
||||
var language = states.GetState("language", LanguageType.UNKNOWN);
|
||||
if (language != LanguageType.ENGLISH)
|
||||
{
|
||||
message.SecondaryContent = message.Content;
|
||||
message.Content = await translator.Translate(_router, message.MessageId, message.Content,
|
||||
language: LanguageType.ENGLISH,
|
||||
clone: false);
|
||||
}
|
||||
}
|
||||
|
||||
dialogs.Add(message);
|
||||
storage.Append(convService.ConversationId, message);
|
||||
|
||||
// Get first instruction
|
||||
_router.TemplateDict["conversation"] = await GetConversationContent(dialogs);
|
||||
var inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs);
|
||||
|
||||
// Handle multi-language for input
|
||||
var translator = _services.GetRequiredService<ITranslationService>();
|
||||
|
||||
var language = states.GetState("language", inst.Language);
|
||||
if (language != LanguageType.UNKNOWN && language != LanguageType.ENGLISH)
|
||||
{
|
||||
message.SecondaryContent = message.Content;
|
||||
message.Content = await translator.Translate(_router, message.MessageId, message.Content,
|
||||
language: LanguageType.ENGLISH,
|
||||
clone: false);
|
||||
}
|
||||
|
||||
storage.Append(convService.ConversationId, message);
|
||||
|
||||
int loopCount = 1;
|
||||
while (true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@ namespace BotSharp.Logger.Hooks
|
|||
}
|
||||
public override async Task OnResponseGenerated(RoleDialogModel message)
|
||||
{
|
||||
var agentSettings = _services.GetRequiredService<AgentSettings>();
|
||||
if (!agentSettings.EnableTranslator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle multi-language for output
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var router = await agentService.LoadAgent(AIAssistant);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using BotSharp.Abstraction.Infrastructures.Enums;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using BotSharp.Abstraction.Options;
|
||||
using BotSharp.Abstraction.Templating;
|
||||
using BotSharp.Abstraction.Translation.Models;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
|
|
@ -57,7 +59,13 @@ public class TranslationService : ITranslationService
|
|||
|
||||
try
|
||||
{
|
||||
var translatedTexts = translatedStringList.JsonArrayContent<string>();
|
||||
// Override language if it's Unknown, it's used to output the corresponding language.
|
||||
var states = _services.GetRequiredService<IConversationStateService>();
|
||||
var inputLanguage = string.IsNullOrEmpty(translatedStringList.InputLanguage) ? LanguageType.ENGLISH : translatedStringList.InputLanguage;
|
||||
var languageState = states.GetState("language", inputLanguage);
|
||||
states.SetState("language", languageState, activeRounds: 1);
|
||||
|
||||
var translatedTexts = translatedStringList.Texts;
|
||||
var map = new Dictionary<string, string>();
|
||||
|
||||
for (var i = 0; i < texts.Length; i++)
|
||||
|
|
@ -283,7 +291,7 @@ public class TranslationService : ITranslationService
|
|||
/// <param name="list"></param>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> InnerTranslate(string texts, string language, string template)
|
||||
private async Task<TranslationOutput> InnerTranslate(string texts, string language, string template)
|
||||
{
|
||||
var translator = new Agent
|
||||
{
|
||||
|
|
@ -308,7 +316,7 @@ public class TranslationService : ITranslationService
|
|||
}
|
||||
};
|
||||
var response = await _completion.GetChatCompletions(translator, translationDialogs);
|
||||
return response.Content;
|
||||
return response.Content.JsonContent<TranslationOutput>();
|
||||
}
|
||||
|
||||
#region Type methods
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{{ text_list }}
|
||||
|
||||
=====
|
||||
Translate the above sentences in the list into {{ language }}, output the translated text in JSON array [""].
|
||||
Translate the above sentences in the list into {{ language }}.
|
||||
Output the translated text in JSON {"input_lang":"", "output_lang":"{{ language }}", "texts":[""]}, input_lang is based on the original sentences.
|
||||
|
|
@ -110,4 +110,12 @@ public class AgentController : ControllerBase
|
|||
model.Id = agentId;
|
||||
await _agentService.UpdateAgent(model, field);
|
||||
}
|
||||
|
||||
[HttpPatch("/agent/{agentId}/templates")]
|
||||
public async Task<string> PatchAgentTemplates([FromRoute] string agentId, [FromBody] AgentTemplatePatchModel agent)
|
||||
{
|
||||
var model = agent.ToAgent();
|
||||
model.Id = agentId;
|
||||
return await _agentService.PatchAgentTemplate(model);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.ViewModels.Agents;
|
||||
|
||||
public class AgentTemplatePatchModel
|
||||
{
|
||||
public List<AgentTemplate>? Templates { get; set; }
|
||||
|
||||
public AgentTemplatePatchModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Agent ToAgent()
|
||||
{
|
||||
var agent = new Agent()
|
||||
{
|
||||
Templates = Templates ?? new List<AgentTemplate>(),
|
||||
};
|
||||
|
||||
return agent;
|
||||
}
|
||||
}
|
||||
|
|
@ -332,6 +332,23 @@ public partial class MongoRepository
|
|||
return agent.Templates?.FirstOrDefault(x => x.Name == templateName.ToLower())?.Content ?? string.Empty;
|
||||
}
|
||||
|
||||
public bool PatchAgentTemplate(string agentId, AgentTemplate template)
|
||||
{
|
||||
if (string.IsNullOrEmpty(agentId) || template == null) return false;
|
||||
|
||||
var filter = Builders<AgentDocument>.Filter.Eq(x => x.Id, agentId);
|
||||
var agent = _dc.Agents.Find(filter).FirstOrDefault();
|
||||
if (agent == null || agent.Templates.IsNullOrEmpty()) return false;
|
||||
|
||||
var foundTemplate = agent.Templates.FirstOrDefault(x => x.Name.IsEqualTo(template.Name));
|
||||
if (foundTemplate == null) return false;
|
||||
|
||||
foundTemplate.Content = template.Content;
|
||||
var update = Builders<AgentDocument>.Update.Set(x => x.Templates, agent.Templates);
|
||||
_dc.Agents.UpdateOne(filter, update);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void BulkInsertAgents(List<Agent> agents)
|
||||
{
|
||||
if (agents.IsNullOrEmpty()) return;
|
||||
|
|
|
|||
Loading…
Reference in a new issue