Merge pull request #509 from iceljc/features/add-file-upload-endpoint

refine message files
This commit is contained in:
C. Oceania 2024-06-20 09:24:56 -05:00 committed by GitHub
commit bca845e572
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 53 additions and 50 deletions

View file

@ -56,4 +56,6 @@ public interface IConversationService
Task UpdateBreakpoint(bool resetStates = false, string? reason = null, params string[] excludedStates); Task UpdateBreakpoint(bool resetStates = false, string? reason = null, params string[] excludedStates);
Task<string> GetConversationSummary(IEnumerable<string> conversationId); Task<string> GetConversationSummary(IEnumerable<string> conversationId);
Task<Conversation> GetConversationRecordOrCreateNew(string agentId);
} }

View file

@ -5,6 +5,9 @@ public class IncomingMessageModel : MessageConfig
public string Text { get; set; } = string.Empty; public string Text { get; set; } = string.Empty;
public virtual string Channel { get; set; } = string.Empty; public virtual string Channel { get; set; } = string.Empty;
[JsonPropertyName("input_message_id")]
public string? InputMessageId { get; set; }
/// <summary> /// <summary>
/// Postback message /// Postback message
/// </summary> /// </summary>

View file

@ -2,5 +2,6 @@ namespace BotSharp.Abstraction.Conversations.Models;
public class TruncateMessageRequest public class TruncateMessageRequest
{ {
public string? TruncateMessageId { get; set; } [JsonPropertyName("is_new_message")]
public bool isNewMessage { get; set; }
} }

View file

@ -1,6 +1,6 @@
namespace BotSharp.Abstraction.Models; namespace BotSharp.Abstraction.Models;
public class MessageConfig : TruncateMessageRequest public class MessageConfig
{ {
/// <summary> /// <summary>
/// Completion Provider /// Completion Provider

View file

@ -14,13 +14,7 @@ public partial class ConversationService
Func<RoleDialogModel, Task> onFunctionExecuting, Func<RoleDialogModel, Task> onFunctionExecuting,
Func<RoleDialogModel, Task> onFunctionExecuted) Func<RoleDialogModel, Task> onFunctionExecuted)
{ {
var conversation = await GetConversationRecord(agentId); var conversation = await GetConversationRecordOrCreateNew(agentId);
// Save message files
var fileService = _services.GetRequiredService<IBotSharpFileService>();
fileService.SaveMessageFiles(_conversationId, message.MessageId, FileSourceType.User, message.Files);
message.Files?.Clear();
var agentService = _services.GetRequiredService<IAgentService>(); var agentService = _services.GetRequiredService<IAgentService>();
Agent agent = await agentService.LoadAgent(agentId); Agent agent = await agentService.LoadAgent(agentId);
@ -99,27 +93,6 @@ public partial class ConversationService
return true; return true;
} }
private async Task<Conversation> GetConversationRecord(string agentId)
{
var converation = await GetConversation(_conversationId);
// Create conversation if this conversation does not exist
if (converation == null)
{
var state = _services.GetRequiredService<IConversationStateService>();
var channel = state.GetState("channel");
var sess = new Conversation
{
Id = _conversationId,
Channel = channel,
AgentId = agentId
};
converation = await NewConversation(sess);
}
return converation;
}
private async Task HandleAssistantMessage(RoleDialogModel response, Func<RoleDialogModel, Task> onResponseReceived) private async Task HandleAssistantMessage(RoleDialogModel response, Func<RoleDialogModel, Task> onResponseReceived)
{ {
var agentService = _services.GetRequiredService<IAgentService>(); var agentService = _services.GetRequiredService<IAgentService>();

View file

@ -140,4 +140,25 @@ public partial class ConversationService : IConversationService
_state.Load(_conversationId); _state.Load(_conversationId);
states.ForEach(x => _state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External)); states.ForEach(x => _state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External));
} }
public async Task<Conversation> GetConversationRecordOrCreateNew(string agentId)
{
var converation = await GetConversation(_conversationId);
// Create conversation if this conversation does not exist
if (converation == null)
{
var state = _services.GetRequiredService<IConversationStateService>();
var channel = state.GetState("channel");
var sess = new Conversation
{
Id = _conversationId,
Channel = channel,
AgentId = agentId
};
converation = await NewConversation(sess);
}
return converation;
}
} }

View file

@ -230,7 +230,6 @@ public partial class BotSharpFileService
using var fs = new FileStream(Path.Combine(subDir, file.FileName), FileMode.Create); using var fs = new FileStream(Path.Combine(subDir, file.FileName), FileMode.Create);
fs.Write(bytes, 0, bytes.Length); fs.Write(bytes, 0, bytes.Length);
fs.Flush(true); fs.Flush(true);
Thread.Sleep(2000);
} }
return true; return true;

View file

@ -1,3 +1,4 @@
using BotSharp.Abstraction.Files.Enums;
using BotSharp.Abstraction.Options; using BotSharp.Abstraction.Options;
using BotSharp.Abstraction.Routing; using BotSharp.Abstraction.Routing;
using BotSharp.Abstraction.Users.Enums; using BotSharp.Abstraction.Users.Enums;
@ -142,7 +143,7 @@ public class ConversationController : ControllerBase
{ {
return null; return null;
} }
var result = ConversationViewModel.FromSession(conversations.Items.First()); var result = ConversationViewModel.FromSession(conversations.Items.First());
var state = _services.GetRequiredService<IConversationStateService>(); var state = _services.GetRequiredService<IConversationStateService>();
result.States = state.Load(conversationId, isReadOnly: true); result.States = state.Load(conversationId, isReadOnly: true);
@ -211,11 +212,12 @@ public class ConversationController : ControllerBase
} }
[HttpDelete("/conversation/{conversationId}/message/{messageId}")] [HttpDelete("/conversation/{conversationId}/message/{messageId}")]
public async Task<bool> DeleteConversationMessage([FromRoute] string conversationId, [FromRoute] string messageId) public async Task<string?> DeleteConversationMessage([FromRoute] string conversationId, [FromRoute] string messageId, [FromBody] TruncateMessageRequest request)
{ {
var conversationService = _services.GetRequiredService<IConversationService>(); var conversationService = _services.GetRequiredService<IConversationService>();
var response = await conversationService.TruncateConversation(conversationId, messageId); var newMessageId = request.isNewMessage ? Guid.NewGuid().ToString() : null;
return response; var isSuccess = await conversationService.TruncateConversation(conversationId, messageId, newMessageId);
return isSuccess ? newMessageId : string.Empty;
} }
#region Send message #region Send message
@ -227,15 +229,10 @@ public class ConversationController : ControllerBase
var conv = _services.GetRequiredService<IConversationService>(); var conv = _services.GetRequiredService<IConversationService>();
var inputMsg = new RoleDialogModel(AgentRole.User, input.Text) var inputMsg = new RoleDialogModel(AgentRole.User, input.Text)
{ {
Files = input.Files, MessageId = !string.IsNullOrWhiteSpace(input.InputMessageId) ? input.InputMessageId : Guid.NewGuid().ToString(),
CreatedAt = DateTime.UtcNow CreatedAt = DateTime.UtcNow
}; };
if (!string.IsNullOrEmpty(input.TruncateMessageId))
{
await conv.TruncateConversation(conversationId, input.TruncateMessageId, inputMsg.MessageId);
}
var routing = _services.GetRequiredService<IRoutingService>(); var routing = _services.GetRequiredService<IRoutingService>();
routing.Context.SetMessageId(conversationId, inputMsg.MessageId); routing.Context.SetMessageId(conversationId, inputMsg.MessageId);
@ -243,7 +240,7 @@ public class ConversationController : ControllerBase
SetStates(conv, input); SetStates(conv, input);
var response = new ChatResponseModel(); var response = new ChatResponseModel();
await conv.SendMessage(agentId, inputMsg, await conv.SendMessage(agentId, inputMsg,
replyMessage: input.Postback, replyMessage: input.Postback,
async msg => async msg =>
@ -273,15 +270,10 @@ public class ConversationController : ControllerBase
var conv = _services.GetRequiredService<IConversationService>(); var conv = _services.GetRequiredService<IConversationService>();
var inputMsg = new RoleDialogModel(AgentRole.User, input.Text) var inputMsg = new RoleDialogModel(AgentRole.User, input.Text)
{ {
Files = input.Files, MessageId = !string.IsNullOrWhiteSpace(input.InputMessageId) ? input.InputMessageId : Guid.NewGuid().ToString(),
CreatedAt = DateTime.UtcNow CreatedAt = DateTime.UtcNow
}; };
if (!string.IsNullOrEmpty(input.TruncateMessageId))
{
await conv.TruncateConversation(conversationId, input.TruncateMessageId, inputMsg.MessageId);
}
var state = _services.GetRequiredService<IConversationStateService>(); var state = _services.GetRequiredService<IConversationStateService>();
var routing = _services.GetRequiredService<IRoutingService>(); var routing = _services.GetRequiredService<IRoutingService>();
@ -322,7 +314,7 @@ public class ConversationController : ControllerBase
{ {
ConversationId = conversationId, ConversationId = conversationId,
MessageId = msg.MessageId, MessageId = msg.MessageId,
Text = msg.Indication, Text = msg.Indication,
Function = "indicating", Function = "indicating",
Instruction = msg.Instruction, Instruction = msg.Instruction,
States = new Dictionary<string, string>() States = new Dictionary<string, string>()
@ -370,8 +362,20 @@ public class ConversationController : ControllerBase
return BadRequest(new { message = "Invalid file." }); return BadRequest(new { message = "Invalid file." });
} }
[HttpPost("/agent/{agentId}/conversation/{conversationId}/upload")]
public async Task<string> UploadConversationMessageFiles([FromRoute] string agentId, [FromRoute] string conversationId, [FromBody] NewMessageModel input)
{
var convService = _services.GetRequiredService<IConversationService>();
convService.SetConversationId(conversationId, input.States);
var conv = await convService.GetConversationRecordOrCreateNew(agentId);
var fileService = _services.GetRequiredService<IBotSharpFileService>();
var messageId = Guid.NewGuid().ToString();
var isSaved = fileService.SaveMessageFiles(conv.Id, messageId, FileSourceType.User, input.Files);
return isSaved ? messageId : string.Empty;
}
[HttpGet("/conversation/{conversationId}/files/{messageId}/{source}")] [HttpGet("/conversation/{conversationId}/files/{messageId}/{source}")]
public IEnumerable<MessageFileViewModel> GetMessageFiles([FromRoute] string conversationId, [FromRoute] string messageId, [FromRoute] string source) public IEnumerable<MessageFileViewModel> GetConversationMessageFiles([FromRoute] string conversationId, [FromRoute] string messageId, [FromRoute] string source)
{ {
var fileService = _services.GetRequiredService<IBotSharpFileService>(); var fileService = _services.GetRequiredService<IBotSharpFileService>();
var files = fileService.GetMessageFiles(conversationId, new List<string> { messageId }, source, imageOnly: false); var files = fileService.GetMessageFiles(conversationId, new List<string> { messageId }, source, imageOnly: false);