diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Settings/RateLimitSetting.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Settings/RateLimitSetting.cs
index 0c9a7436..566f7bef 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Settings/RateLimitSetting.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Settings/RateLimitSetting.cs
@@ -3,6 +3,6 @@ namespace BotSharp.Abstraction.Conversations.Settings;
public class RateLimitSetting
{
public int MaxConversationPerDay { get; set; } = 100;
- public int MaxInputLengthPerRequest { get; set; } = 256;
+ public int MaxInputLengthPerRequest { get; set; } = 512;
public int MinTimeSecondsBetweenMessages { get; set; } = 2;
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs
index ce8a5a93..647ebc98 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ButtonTemplateMessage.cs
@@ -14,6 +14,7 @@ public class ButtonTemplateMessage : IRichMessage, ITemplateMessage
[JsonPropertyName("text")]
[JsonProperty("text")]
+ [Translate]
public string Text { get; set; } = string.Empty;
[JsonPropertyName("template_type")]
diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
index 105c0c57..f68b7231 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
@@ -3,7 +3,7 @@ namespace BotSharp.Abstraction.Routing.Models;
public class RoutingArgs
{
[JsonPropertyName("function")]
- public string Function { get; set; }
+ public string Function { get; set; } = string.Empty;
///
/// The reason why you select this function or agent
@@ -30,32 +30,29 @@ public class RoutingArgs
///
[JsonPropertyName("response")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public string Response { get; set; }
+ public string Response { get; set; } = string.Empty;
///
/// Agent for next action based on user latest response
///
[JsonPropertyName("next_action_agent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public string AgentName { get; set; }
+ public string AgentName { get; set; } = string.Empty;
///
/// Agent who can achieve user original goal
///
[JsonPropertyName("user_goal_agent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public string OriginalAgent { get; set; }
+ public string OriginalAgent { get; set; } = string.Empty;
[JsonPropertyName("user_goal_description")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- public string UserGoal { get; set; }
+ public string UserGoal { get; set; } = string.Empty;
[JsonPropertyName("language")]
public string Language { get; set; } = LanguageType.ENGLISH;
- [JsonPropertyName("lastest_message_translated_to_english")]
- public string UserMessageInEnglish { get; set; }
-
public override string ToString()
{
var route = string.IsNullOrEmpty(AgentName) ? "" : $"";
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
index 92a3b137..00c8c616 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
@@ -22,9 +22,7 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler
type: "boolean"),
new ParameterPropertyDef("language",
"User preferred language, considering the whole conversation. Language could be English, Spanish or Chinese.",
- required: true),
- new ParameterPropertyDef("lastest_message_translated_to_english",
- "Translate user lastest message in [CONVERSATION] to English"),
+ required: true)
};
public ResponseToUserRoutingHandler(IServiceProvider services, ILogger logger, RoutingSettings settings)
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs
index 5c08d679..59561461 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs
@@ -31,9 +31,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
type: "boolean"),
new ParameterPropertyDef("language",
"User preferred language, considering the whole conversation. Language could be English, Spanish or Chinese.",
- required: true),
- new ParameterPropertyDef("lastest_message_translated_to_english",
- "Translate lastest user message in [CONVERSATION] to English"),
+ required: true)
};
public RouteToAgentRoutingHandler(IServiceProvider services, ILogger logger, RoutingSettings settings)
diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs
index bd883314..5825a2c0 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.GetConversationContent.cs
@@ -16,7 +16,7 @@ public partial class RoutingService
role = agent.Name;
}
- conversation += $"{role}: {dialog.Content}\r\n";
+ conversation += $"{role}: {dialog.SecondaryContent ?? dialog.Content}\r\n";
}
return conversation;
diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
index 36fb21be..c139ceab 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
@@ -100,11 +100,17 @@ public partial class RoutingService : IRoutingService
var inst = await planner.GetNextInstruction(_router, message.MessageId, dialogs);
// Handle multi-language for input
+ var translator = _services.GetRequiredService();
- if (inst.Language != LanguageType.UNKNOWN && inst.Language != LanguageType.ENGLISH)
+ var language = states.GetState("language", inst.Language);
+ if (language != LanguageType.UNKNOWN && language != LanguageType.ENGLISH)
{
- message.Content = inst.UserMessageInEnglish;
+ 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;
@@ -150,22 +156,26 @@ public partial class RoutingService : IRoutingService
}
// Handle multi-language for output
- if (inst.Language != LanguageType.UNKNOWN && inst.Language != LanguageType.ENGLISH)
+ if (language != LanguageType.UNKNOWN && language != LanguageType.ENGLISH)
{
- var translator = _services.GetRequiredService();
if (response.RichContent != null)
{
- response.RichContent.Message = await translator.Translate(_router,
+ if (string.IsNullOrEmpty(response.RichContent.Message.Text))
+ {
+ response.RichContent.Message.Text = response.Content;
+ }
+
+ response.SecondaryRichContent = await translator.Translate(_router,
message.MessageId,
- response.RichContent.Message,
- language: inst.Language);
+ response.RichContent,
+ language: language);
}
else
{
response.SecondaryContent = await translator.Translate(_router,
message.MessageId,
response.Content,
- language: inst.Language);
+ language: language);
}
}
diff --git a/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs b/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs
index 815b2dc9..0e44e3e2 100644
--- a/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs
+++ b/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs
@@ -1,8 +1,10 @@
+using BotSharp.Abstraction.MLTasks;
using BotSharp.Abstraction.Options;
using BotSharp.Abstraction.Templating;
using BotSharp.Abstraction.Translation.Attributes;
using Newtonsoft.Json;
using System.Collections;
+using System.Collections.Generic;
using System.Reflection;
namespace BotSharp.Core.Translation;
@@ -14,6 +16,7 @@ public class TranslationService : ITranslationService
private readonly BotSharpOptions _options;
private Agent _router;
private string _messageId;
+ private IChatCompletion _completion;
public TranslationService(IServiceProvider services,
ILogger logger,
@@ -31,7 +34,7 @@ public class TranslationService : ITranslationService
var unique = new HashSet();
Collect(data, ref unique);
- if (unique.Count == 0)
+ if (unique.IsNullOrEmpty())
{
return data;
}
@@ -42,8 +45,31 @@ public class TranslationService : ITranslationService
cloned = Clone(data);
}
- var map = await InnerTranslate(unique, language);
- cloned = Assign(cloned, map);
+ // chat completion
+ _completion = CompletionProvider.GetChatCompletion(_services,
+ provider: _router?.LlmConfig?.Provider,
+ model: _router?.LlmConfig?.Model);
+ var template = _router.Templates.First(x => x.Name == "translation_prompt").Content;
+
+ var texts = unique.ToArray();
+ var translatedStringList = await InnerTranslate(JsonConvert.SerializeObject(texts), language, template);
+
+ try
+ {
+ var translatedTexts = translatedStringList.JsonArrayContent();
+ var map = new Dictionary();
+
+ for (var i = 0; i < texts.Length; i++)
+ {
+ map.Add(texts[i], translatedTexts[i]);
+ }
+
+ cloned = Assign(cloned, map);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex.Message);
+ }
return cloned;
}
@@ -68,23 +94,21 @@ public class TranslationService : ITranslationService
if (data == null) return;
var dataType = data.GetType();
- if (dataType == typeof(string))
+ if (IsStringType(dataType))
{
res.Add(data.ToString());
return;
}
- var interfaces = dataType.GetTypeInfo().ImplementedInterfaces;
- if (interfaces.Any(x => x.Name == typeof(IDictionary<,>).Name))
+ if (IsDictionaryType(dataType))
{
return;
}
- var isList = interfaces.Any(x => x.Name == typeof(IEnumerable).Name);
- if (dataType.IsArray || isList)
+ if (IsListType(dataType))
{
var elementType = dataType.IsArray ? dataType.GetElementType() : dataType.GetGenericArguments().FirstOrDefault();
- if (elementType == typeof(string))
+ if (IsStringType(elementType))
{
foreach (var item in (data as IEnumerable))
{
@@ -92,7 +116,7 @@ public class TranslationService : ITranslationService
res.Add(item);
}
}
- else if (elementType != null && (elementType.IsClass || elementType.IsInterface))
+ else if (IsTrackToNextLevel(elementType))
{
foreach (var item in (data as IEnumerable