diff --git a/docs/channels/components.md b/docs/channels/components.md
index 3754a1c3..89ab8cb4 100644
--- a/docs/channels/components.md
+++ b/docs/channels/components.md
@@ -1,6 +1,6 @@
# Messaging Components
-Conversations are a lot more than simple text messages when you are building a AI chatbot. In addition to text, the `BotSharp`` allows you to send rich-media, like audio, video, and images, and provides a set of structured messaging options in the form of message templates, quick replies, buttons and more. The UI rendering program can render components according to the returned data format.
+Conversations are a lot more than simple text messages when you are building a AI chatbot. In addition to text, the `BotSharp` allows you to send rich-media, like audio, video, and images, and provides a set of structured messaging options in the form of message templates, quick replies, buttons and more. The UI rendering program can render components according to the returned data format.
## Text Messages
@@ -75,7 +75,7 @@ Message templates are structured message formats used for various purposes to pr
...
}
]
- }
+ }
}
}
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs
index 98381559..903e5d0b 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/IncomingMessageModel.cs
@@ -1,36 +1,9 @@
+using BotSharp.Abstraction.Models;
+
namespace BotSharp.Abstraction.Conversations.Models;
-public class IncomingMessageModel
+public class IncomingMessageModel : MessageConfig
{
public string Text { get; set; } = string.Empty;
-
- public virtual string Channel { get; set; } = string.Empty;
-
- ///
- /// Completion Provider
- ///
- [JsonPropertyName("provider")]
- public virtual string? Provider { get; set; } = null;
-
- ///
- /// Model name
- ///
- [JsonPropertyName("model")]
- public virtual string? Model { get; set; } = null;
-
- ///
- /// The sampling temperature to use that controls the apparent creativity of generated completions.
- ///
- public float Temperature { get; set; } = 0.5f;
-
- ///
- /// 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;
-
- ///
- /// Conversation states from input
- ///
- public List States { get; set; } = new List();
+ public virtual string Channel { get; set; }
}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs
index ae798160..6b8624f9 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/RoleDialogModel.cs
@@ -1,7 +1,11 @@
+using BotSharp.Abstraction.Models;
+
namespace BotSharp.Abstraction.Conversations.Models;
-public class RoleDialogModel
+public class RoleDialogModel : ITrackableMessage
{
+ public string MessageId { get; set; }
+
///
/// user, system, assistant, function
///
@@ -34,10 +38,15 @@ public class RoleDialogModel
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
public bool StopCompletion { get; set; }
+ private RoleDialogModel()
+ {
+ }
+
public RoleDialogModel(string role, string text)
{
Role = role;
Content = text;
+ MessageId = Guid.NewGuid().ToString();
}
public override string ToString()
diff --git a/src/Infrastructure/BotSharp.Abstraction/Instructs/Models/InstructResult.cs b/src/Infrastructure/BotSharp.Abstraction/Instructs/Models/InstructResult.cs
index 10635152..67bd2039 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Instructs/Models/InstructResult.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Instructs/Models/InstructResult.cs
@@ -1,7 +1,10 @@
+using BotSharp.Abstraction.Models;
+
namespace BotSharp.Abstraction.Instructs.Models;
-public class InstructResult
+public class InstructResult : ITrackableMessage
{
+ public string MessageId { get; set; }
public string Text { get; set; }
public object Data { get; set; }
public ConversationState States { get; set; }
diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/ITrackableMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Models/ITrackableMessage.cs
new file mode 100644
index 00000000..5756cfd6
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Models/ITrackableMessage.cs
@@ -0,0 +1,9 @@
+namespace BotSharp.Abstraction.Models;
+
+///
+/// Define a message ID to extend message-level applications, such as model fees, token usage, and data collection
+///
+public interface ITrackableMessage
+{
+ string MessageId { get; set; }
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs b/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs
new file mode 100644
index 00000000..95d72492
--- /dev/null
+++ b/src/Infrastructure/BotSharp.Abstraction/Models/MessageConfig.cs
@@ -0,0 +1,32 @@
+namespace BotSharp.Abstraction.Models;
+
+public class MessageConfig
+{
+ ///
+ /// Completion Provider
+ ///
+ [JsonPropertyName("provider")]
+ public virtual string? Provider { get; set; } = null;
+
+ ///
+ /// Model name
+ ///
+ [JsonPropertyName("model")]
+ public virtual string? Model { get; set; } = null;
+
+ ///
+ /// The sampling temperature to use that controls the apparent creativity of generated completions.
+ ///
+ public float Temperature { get; set; } = 0.5f;
+
+ ///
+ /// 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;
+
+ ///
+ /// Conversation states from input
+ ///
+ public List States { get; set; } = new List();
+}
diff --git a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
index bca8018e..96e133d9 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs
@@ -1,7 +1,10 @@
namespace BotSharp.Abstraction.Routing.Models;
-public class RoutingArgs
+public class RoutingArgs : ITrackableMessage
{
+ [JsonPropertyName("message_id")]
+ public string MessageId { get; set; }
+
[JsonPropertyName("function")]
public string Function { get; set; }
diff --git a/src/Infrastructure/BotSharp.Abstraction/Using.cs b/src/Infrastructure/BotSharp.Abstraction/Using.cs
index 87d42791..39ececfe 100644
--- a/src/Infrastructure/BotSharp.Abstraction/Using.cs
+++ b/src/Infrastructure/BotSharp.Abstraction/Using.cs
@@ -7,4 +7,5 @@ global using System.ComponentModel.DataAnnotations;
global using System.Text.Json.Serialization;
global using BotSharp.Abstraction.Agents.Models;
global using BotSharp.Abstraction.Conversations.Models;
-global using BotSharp.Abstraction.Agents.Enums;
\ No newline at end of file
+global using BotSharp.Abstraction.Agents.Enums;
+global using BotSharp.Abstraction.Models;
\ No newline at end of file
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
index efcb9cf9..db6fc90a 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs
@@ -78,11 +78,11 @@ public partial class ConversationService : IConversationService
throw new NotImplementedException();
}
- public List GetDialogHistory(int lastCount = 20)
+ public List GetDialogHistory(int lastCount = 50)
{
var dialogs = _storage.GetDialogs(_conversationId);
return dialogs
- .Where(x => x.CreatedAt > DateTime.UtcNow.AddHours(-8))
+ .Where(x => x.CreatedAt > DateTime.UtcNow.AddHours(-24))
.TakeLast(lastCount)
.ToList();
}
diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs
index 2d8af0ad..3d8b3085 100644
--- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs
+++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationStorage.cs
@@ -6,19 +6,13 @@ namespace BotSharp.Core.Conversations.Services;
public class ConversationStorage : IConversationStorage
{
private readonly BotSharpDatabaseSettings _dbSettings;
- private readonly AgentSettings _agentSettings;
private readonly IServiceProvider _services;
- private readonly IUserIdentity _user;
public ConversationStorage(
BotSharpDatabaseSettings dbSettings,
- AgentSettings agentSettings,
- IServiceProvider services,
- IUserIdentity user)
+ IServiceProvider services)
{
_dbSettings = dbSettings;
- _agentSettings = agentSettings;
_services = services;
- _user = user;
}
public void Append(string conversationId, RoleDialogModel dialog)
@@ -32,7 +26,7 @@ public class ConversationStorage : IConversationStorage
{
var args = dialog.FunctionArgs.Replace("\r", " ").Replace("\n", " ").Trim();
- sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.FunctionName}|{args}");
+ sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.MessageId}");
var content = dialog.Content;
content = content.Replace("\r", " ").Replace("\n", " ").Trim();
@@ -44,9 +38,7 @@ public class ConversationStorage : IConversationStorage
}
else
{
- var agentName = db.GetAgent(agentId)?.Name;
-
- sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{agentName}|");
+ sb.AppendLine($"{dialog.CreatedAt}|{dialog.Role}|{agentId}|{dialog.MessageId}");
var content = dialog.Content.Replace("\r", " ").Replace("\n", " ").Trim();
if (string.IsNullOrEmpty(content))
{
@@ -73,15 +65,13 @@ public class ConversationStorage : IConversationStorage
var createdAt = DateTime.Parse(meta.Split('|')[0]);
var role = meta.Split('|')[1];
var currentAgentId = meta.Split('|')[2];
- var funcName = meta.Split('|')[3];
- var funcArgs= meta.Split('|')[4];
+ var messageId = meta.Split('|')[3];
var text = dialog.Substring(4);
results.Add(new RoleDialogModel(role, text)
{
CurrentAgentId = currentAgentId,
- FunctionName = funcName,
- FunctionArgs = funcArgs,
+ MessageId = messageId,
Content = text,
CreatedAt = createdAt
});
diff --git a/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs b/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs
index bb328753..8ee49eac 100644
--- a/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs
+++ b/src/Infrastructure/BotSharp.Core/Instructs/InstructService.cs
@@ -33,6 +33,7 @@ public partial class InstructService : IInstructService
{
return new InstructResult
{
+ MessageId = message.MessageId,
Text = message.Content
};
}
@@ -42,6 +43,7 @@ public partial class InstructService : IInstructService
var result = await completer.GetCompletion(agent.Instruction);
var response = new InstructResult
{
+ MessageId = message.MessageId,
Text = result
};
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs
index 984651f0..8e167855 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ContinueExecuteTaskRoutingHandler.cs
@@ -33,6 +33,7 @@ public class ContinueExecuteTaskRoutingHandler : RoutingHandlerBase, IRoutingHan
var result = new RoleDialogModel(AgentRole.Function, inst.Question)
{
+ MessageId = inst.MessageId,
FunctionName = inst.Function,
FunctionArgs = JsonSerializer.Serialize(inst.Arguments),
CurrentAgentId = record.Id
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs
index 44563f42..69a5c9f7 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ConversationEndRoutingHandler.cs
@@ -28,6 +28,7 @@ public class ConversationEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
{
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
{
+ MessageId = inst.MessageId,
CurrentAgentId = _settings.RouterId,
FunctionName = inst.Function,
Data = inst
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs
index 62247445..1ebf9c43 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/HumanInterventionNeededHandler.cs
@@ -29,6 +29,7 @@ public class HumanInterventionNeededHandler : RoutingHandlerBase, IRoutingHandle
{
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
{
+ MessageId = inst.MessageId,
CurrentAgentId = _settings.RouterId,
FunctionName = inst.Function,
Data = inst
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs
index 096f9d61..c62102e2 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/InterruptTaskExecutionRoutingHandler.cs
@@ -28,6 +28,7 @@ public class InterruptTaskExecutionRoutingHandler : RoutingHandlerBase, IRouting
{
var result = new RoleDialogModel(AgentRole.User, inst.Reason)
{
+ MessageId = inst.MessageId,
FunctionName = inst.Function,
StopCompletion = true
};
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
index ec1c5bcf..9da370b8 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/ResponseToUserRoutingHandler.cs
@@ -28,6 +28,7 @@ public class ResponseToUserRoutingHandler : RoutingHandlerBase, IRoutingHandler
{
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
{
+ MessageId = inst.MessageId,
CurrentAgentId = _settings.RouterId,
FunctionName = inst.Function,
Data = inst,
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs
index d4492d2b..04d78bdb 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RetrieveDataFromAgentRoutingHandler.cs
@@ -45,6 +45,7 @@ public class RetrieveDataFromAgentRoutingHandler : RoutingHandlerBase, IRoutingH
/*_dialogs.Add(new RoleDialogModel(AgentRole.Function, inst.Parameters.Answer)
{
+ MessageId = inst.MessageId,
FunctionName = inst.Function,
FunctionArgs = JsonSerializer.Serialize(inst.Parameters.Arguments),
ExecutionResult = inst.Parameters.Answer,
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs
index d4fba5ff..52766548 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs
@@ -35,6 +35,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
var function = _services.GetServices().FirstOrDefault(x => x.Name == inst.Function);
var message = new RoleDialogModel(AgentRole.Function, inst.Question)
{
+ MessageId = inst.MessageId,
FunctionName = inst.Function,
FunctionArgs = JsonSerializer.Serialize(inst),
CurrentAgentId = context.GetCurrentAgentId(),
@@ -46,6 +47,7 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
// Keep last message data for debug
result.Data = result.Data ?? message.Data;
result.FunctionName = result.FunctionName ?? message.FunctionName;
+
return result;
}
}
diff --git a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs
index 9190bba5..ba7f2e2c 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/Handlers/TaskEndRoutingHandler.cs
@@ -27,6 +27,7 @@ public class TaskEndRoutingHandler : RoutingHandlerBase, IRoutingHandler
{
var result = new RoleDialogModel(AgentRole.Assistant, inst.Response)
{
+ MessageId = inst.MessageId,
CurrentAgentId = _settings.RouterId,
FunctionName = inst.Function,
Data = inst
diff --git a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
index 9159434d..ba4f8f1b 100644
--- a/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
+++ b/src/Infrastructure/BotSharp.Core/Routing/RoutingService.cs
@@ -76,7 +76,7 @@ public partial class RoutingService : IRoutingService
CurrentAgentId = router.Id
};
- var message = Dialogs.Last().Content;
+ var inputMsg = Dialogs.Last();
var handlers = _services.GetServices();
@@ -87,7 +87,8 @@ public partial class RoutingService : IRoutingService
loopCount++;
var inst = await GetNextInstruction();
- inst.Question = inst.Question ?? message;
+ inst.MessageId = inputMsg.MessageId;
+ inst.Question = inst.Question ?? inputMsg.Content;
var handler = handlers.FirstOrDefault(x => x.Name == inst.Function);
if (handler == null)
@@ -99,6 +100,7 @@ public partial class RoutingService : IRoutingService
handler.SetDialogs(Dialogs);
result = await handler.Handle(this, inst);
+ result.MessageId = inputMsg.MessageId;
stop = !_settings.EnableReasoning;
}
diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs
index 3ca6ca9c..4fd4be21 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs
@@ -1,5 +1,6 @@
using BotSharp.Abstraction.ApiAdapters;
using BotSharp.Abstraction.Conversations.Models;
+using BotSharp.Abstraction.Models;
using BotSharp.OpenAPI.ViewModels.Conversations;
namespace BotSharp.OpenAPI.Controllers;
@@ -19,15 +20,17 @@ public class ConversationController : ControllerBase, IApiAdapter
}
[HttpPost("/conversation/{agentId}")]
- public async Task NewConversation([FromRoute] string agentId)
+ public async Task NewConversation([FromRoute] string agentId, [FromBody] MessageConfig config)
{
var service = _services.GetRequiredService();
- var sess = new Conversation
+ var conv = new Conversation
{
AgentId = agentId
};
- sess = await service.NewConversation(sess);
- return ConversationViewModel.FromSession(sess);
+ conv = await service.NewConversation(conv);
+ config.States.ForEach(x => conv.States[x.Split('=')[0]] = x.Split('=')[1]);
+
+ return ConversationViewModel.FromSession(conv);
}
[HttpDelete("/conversation/{agentId}/{conversationId}")]
@@ -51,9 +54,8 @@ public class ConversationController : ControllerBase, IApiAdapter
var response = new MessageResponseModel();
var stackMsg = new List();
-
- await conv.SendMessage(agentId,
- new RoleDialogModel("user", input.Text),
+ var inputMsg = new RoleDialogModel("user", input.Text);
+ await conv.SendMessage(agentId, inputMsg,
async msg =>
{
stackMsg.Add(msg);
@@ -71,6 +73,7 @@ public class ConversationController : ControllerBase, IApiAdapter
response.Text = string.Join("\r\n", stackMsg.Select(x => x.Content));
response.Data = response.Data ?? stackMsg.Last().Data;
response.Function = stackMsg.Last().FunctionName;
+ response.MessageId = inputMsg.MessageId;
return response;
}
diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs
index 5f7241c0..dc88faaf 100644
--- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs
+++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/MessageResponseModel.cs
@@ -1,7 +1,10 @@
+using BotSharp.Abstraction.Models;
+
namespace BotSharp.OpenAPI.ViewModels.Conversations;
-public class MessageResponseModel
+public class MessageResponseModel : ITrackableMessage
{
+ public string MessageId { get; set; }
public string Text { get; set; }
public string Function { get; set; }
public object Data { get; set; }