diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
index ea6a03d86..1592aa8f7 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/ConversationHookBase.cs
@@ -1,5 +1,3 @@
-using BotSharp.Abstraction.Functions.Models;
-
namespace BotSharp.Abstraction.Conversations;
public abstract class ConversationHookBase : IConversationHook
diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs b/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs
index 17ffeee44..1c4fc26bf 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs
@@ -17,13 +17,13 @@ public class MessageConfig : TruncateMessageRequest
///
/// The sampling temperature to use that controls the apparent creativity of generated completions.
///
- public float Temperature { get; set; } = 0.5f;
+ public float Temperature { get; set; } = 0f;
///
/// An alternative value to Temperature, called nucleus sampling, that causes
/// the model to consider the results of the tokens with probability mass.
///
- public float SamplingFactor { get; set; } = 0.5f;
+ public float SamplingFactor { get; set; } = 0f;
///
/// Conversation states from input
diff --git a/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs b/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs
index 62d5c3e0c..a5aef0f4b 100644
--- a/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs
+++ b/src/Infrastructure/BotSharp.Core/Templating/TemplateRender.cs
@@ -27,6 +27,7 @@ public TemplateRender(IServiceProvider services, ILogger logger)
_options.MemberAccessStrategy.Register();
_options.MemberAccessStrategy.Register();
_options.MemberAccessStrategy.Register();
+ _options.MemberAccessStrategy.Register();
}
public string Render(string template, Dictionary dict)
diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserIdentity.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserIdentity.cs
index 8e5852ccf..b8acdeeac 100644
--- a/src/Infrastructure/BotSharp.Core/Users/Services/UserIdentity.cs
+++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserIdentity.cs
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
+using System.Text.Json.Serialization;
namespace BotSharp.Core.Users.Services;
@@ -17,12 +18,14 @@ public UserIdentity(IHttpContextAccessor contextAccessor)
public string Id
=> _claims?.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value!;
+ [JsonPropertyName("user_name")]
public string UserName
=> _claims?.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value!;
public string Email
=> _claims?.FirstOrDefault(x => x.Type == ClaimTypes.Email)?.Value!;
+ [JsonPropertyName("first_name")]
public string FirstName
{
get
@@ -36,9 +39,21 @@ public string FirstName
}
}
+ [JsonPropertyName("last_name")]
public string LastName
=> _claims?.FirstOrDefault(x => x.Type == ClaimTypes.Surname)?.Value!;
+ [JsonPropertyName("full_name")]
public string FullName
- => $"{FirstName} {LastName}".Trim();
+ {
+ get
+ {
+ var fullName = _claims?.FirstOrDefault(x => x.Type == "full_name")?.Value;
+ if (!string.IsNullOrEmpty(fullName))
+ {
+ return fullName;
+ }
+ return $"{FirstName} {LastName}".Trim();
+ }
+ }
}
diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs
index 9b855af48..139db8087 100644
--- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/ChatCompletionProvider.cs
@@ -254,8 +254,8 @@ public async Task GetChatCompletionsStreamingAsync(Agent agent, List();
- var temperature = float.Parse(state.GetState("temperature", "0.5"));
- var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.5"));
+ var temperature = float.Parse(state.GetState("temperature", "0.0"));
+ var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.0"));
chatCompletionsOptions.Temperature = temperature;
chatCompletionsOptions.NucleusSamplingFactor = samplingFactor;
// chatCompletionsOptions.FrequencyPenalty = 0;
diff --git a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs
index 1078a36b5..f2ca51111 100644
--- a/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs
+++ b/src/Plugins/BotSharp.Plugin.AzureOpenAI/Providers/TextCompletionProvider.cs
@@ -63,8 +63,8 @@ public async Task GetCompletion(string text, string agentId, string mess
completionsOptions.StopSequences.Add($"{AgentRole.Assistant}:");
var state = _services.GetRequiredService();
- var temperature = float.Parse(state.GetState("temperature", "0.5"));
- var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.5"));
+ var temperature = float.Parse(state.GetState("temperature", "0.0"));
+ var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.0"));
completionsOptions.Temperature = temperature;
completionsOptions.NucleusSamplingFactor = samplingFactor;
completionsOptions.DeploymentName = _model;
diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs b/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs
index 7825f0f10..5bd9a8ced 100644
--- a/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs
+++ b/src/Plugins/BotSharp.Plugin.ChatHub/ChatHubPlugin.cs
@@ -19,8 +19,9 @@ public void RegisterDI(IServiceCollection services, IConfiguration config)
{
// Register hooks
services.AddScoped();
- services.AddScoped();
services.AddScoped();
+ services.AddScoped();
services.AddScoped();
+ services.AddScoped();
}
}
diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs
index 23c48ee39..187c2bf42 100644
--- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs
+++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/ChatHubConversationHook.cs
@@ -1,7 +1,5 @@
-using BotSharp.Abstraction.Messaging;
using BotSharp.Abstraction.Messaging.Enums;
using BotSharp.Abstraction.Messaging.JsonConverters;
-using BotSharp.Abstraction.Messaging.Models.RichContent;
using Microsoft.AspNetCore.SignalR;
namespace BotSharp.Plugin.ChatHub.Hooks;
@@ -31,42 +29,6 @@ public ChatHubConversationHook(IServiceProvider services,
};
}
- public override async Task OnUserAgentConnectedInitially(Conversation conversation)
- {
- var agentService = _services.GetRequiredService();
- var agent = await agentService.LoadAgent(conversation.AgentId);
-
- // Check if the Welcome template exists.
- var welcomeTemplate = agent.Templates?.FirstOrDefault(x => x.Name == ".welcome");
- if (welcomeTemplate != null)
- {
- var richContentService = _services.GetRequiredService();
- var messages = richContentService.ConvertToMessages(welcomeTemplate.Content);
-
- foreach (var message in messages)
- {
- var json = JsonSerializer.Serialize(new ChatResponseModel()
- {
- ConversationId = conversation.Id,
- Text = message.Text,
- RichContent = new RichContent(message),
- Sender = new UserViewModel()
- {
- FirstName = "AI",
- LastName = "Assistant",
- Role = AgentRole.Assistant
- }
- }, _serializerOptions);
-
- await Task.Delay(300);
-
- await _chatHub.Clients.User(_user.Id).SendAsync("OnMessageReceivedFromAssistant", json);
- }
- }
-
- await base.OnUserAgentConnectedInitially(conversation);
- }
-
public override async Task OnConversationInitialized(Conversation conversation)
{
var userService = _services.GetRequiredService();
diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs
index 3a166e2b6..f06020808 100644
--- a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs
+++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/StreamingLogHook.cs
@@ -233,7 +233,7 @@ public async Task OnAgentQueueEmptied(string agentId, string? reason = null)
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(input));
}
- public async Task OnRoutingInstructionRevised(FunctionCallFromLlm instruct, RoleDialogModel message)
+ public async Task OnRoutingInstructionReceived(FunctionCallFromLlm instruct, RoleDialogModel message)
{
var conversationId = _state.GetConversationId();
var agent = await _agentService.LoadAgent(message.CurrentAgentId);
@@ -249,6 +249,22 @@ public async Task OnRoutingInstructionRevised(FunctionCallFromLlm instruct, Role
};
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(input));
}
+
+ public async Task OnRoutingInstructionRevised(FunctionCallFromLlm instruct, RoleDialogModel message)
+ {
+ var conversationId = _state.GetConversationId();
+ var agent = await _agentService.LoadAgent(message.CurrentAgentId);
+ var log = $"Revised user goal agent to: {agent?.Name}";
+
+ var input = new ContentLogInputModel(conversationId, message)
+ {
+ Name = agent?.Name,
+ AgentId = agent?.Id,
+ Source = ContentLogSource.HardRule,
+ Log = log
+ };
+ await _chatHub.Clients.User(_user.Id).SendAsync("OnConversationContentLogGenerated", BuildContentLog(input));
+ }
#endregion
diff --git a/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/WelcomeHook.cs b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/WelcomeHook.cs
new file mode 100644
index 000000000..9c8237e7e
--- /dev/null
+++ b/src/Plugins/BotSharp.Plugin.ChatHub/Hooks/WelcomeHook.cs
@@ -0,0 +1,85 @@
+using BotSharp.Abstraction.Messaging.Models.RichContent;
+using BotSharp.Abstraction.Messaging;
+using BotSharp.Abstraction.Templating;
+using BotSharp.Abstraction.Messaging.JsonConverters;
+using Microsoft.AspNetCore.SignalR;
+
+namespace BotSharp.Plugin.ChatHub.Hooks;
+
+public class WelcomeHook : ConversationHookBase
+{
+ private readonly IServiceProvider _services;
+ private readonly IHubContext _chatHub;
+ private readonly IUserIdentity _user;
+ private readonly IConversationStorage _storage;
+ private readonly JsonSerializerOptions _serializerOptions;
+ public WelcomeHook(IServiceProvider services,
+ IHubContext chatHub,
+ IUserIdentity user,
+ IConversationStorage storage)
+ {
+ _services = services;
+ _chatHub = chatHub;
+ _user = user;
+ _storage = storage;
+
+ _serializerOptions = new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+ Converters =
+ {
+ new RichContentJsonConverter(),
+ new TemplateMessageJsonConverter(),
+ }
+ };
+ }
+
+ public override async Task OnUserAgentConnectedInitially(Conversation conversation)
+ {
+ var agentService = _services.GetRequiredService();
+ var agent = await agentService.LoadAgent(conversation.AgentId);
+
+ // Check if the Welcome template exists.
+ var welcomeTemplate = agent.Templates?.FirstOrDefault(x => x.Name == ".welcome");
+ if (welcomeTemplate != null)
+ {
+ // Render template
+ var templating = _services.GetRequiredService();
+ var user = _services.GetRequiredService();
+ var richContent = templating.Render(welcomeTemplate.Content, new Dictionary
+ {
+ { "user", user }
+ });
+ var richContentService = _services.GetRequiredService();
+ var messages = richContentService.ConvertToMessages(richContent);
+
+ foreach (var message in messages)
+ {
+ var json = JsonSerializer.Serialize(new ChatResponseModel()
+ {
+ ConversationId = conversation.Id,
+ Text = message.Text,
+ RichContent = new RichContent(message),
+ Sender = new UserViewModel()
+ {
+ FirstName = agent.Name,
+ LastName = "",
+ Role = AgentRole.Assistant
+ }
+ }, _serializerOptions);
+
+ await Task.Delay(300);
+
+ _storage.Append(conversation.Id, new RoleDialogModel(AgentRole.Assistant, message.Text)
+ {
+ MessageId = conversation.Id,
+ CurrentAgentId = agent.Id,
+ });
+
+ await _chatHub.Clients.User(_user.Id).SendAsync("OnMessageReceivedFromAssistant", json);
+ }
+ }
+
+ await base.OnUserAgentConnectedInitially(conversation);
+ }
+}