split dialog and state

This commit is contained in:
Jicheng Lu 2023-09-05 23:41:49 -05:00
parent 1981b0f000
commit 9d6a7ba690
17 changed files with 140 additions and 86 deletions

View file

@ -6,10 +6,9 @@ public class Conversation
public string AgentId { get; set; } = string.Empty;
public string UserId { get; set; } = string.Empty;
public string Title { get; set; } = string.Empty;
public string Dialog { get; set; }
public string Dialog { get; set; } = string.Empty;
public ConversationState State { get; set; }
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
public ConversationState State { get; set; }
}

View file

@ -25,7 +25,7 @@ public class UserRecord : RecordBase
public string Password { get; set; } = string.Empty;
[MaxLength(36)]
public string ExternalId { get; set; }
public string? ExternalId { get; set; }
[Required]
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;

View file

@ -1,8 +1,8 @@
namespace BotSharp.Abstraction.Utilities;
public static class ListExtenstion
public static class ListExtenstions
{
public static bool IsEmpty<T>(this IEnumerable<T> strList)
public static bool IsNullOrEmpty<T>(this IEnumerable<T> strList)
{
return strList == null || !strList.Any();
}

View file

@ -29,7 +29,7 @@ public partial class AgentService
hook.OnInstructionLoaded(agent.Instruction, templateDict);
}
if (!agent.Functions.IsEmpty())
if (!agent.Functions.IsNullOrEmpty())
{
var functions = agent.Functions;
hook.OnFunctionsLoaded(ref functions);

View file

@ -27,10 +27,10 @@ public partial class AgentService
if (!string.IsNullOrEmpty(agent.Instruction))
record.Instruction = agent.Instruction;
if (!agent.Functions.IsEmpty())
if (!agent.Functions.IsNullOrEmpty())
record.Functions = agent.Functions;
if (!agent.Responses.IsEmpty())
if (!agent.Responses.IsNullOrEmpty())
record.Responses = agent.Responses;
db.UpdateAgent(record);

View file

@ -39,11 +39,6 @@ public partial class ConversationService : IConversationService
public async Task<Conversation> GetConversation(string id)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
//var query = from sess in db.Conversation
// where sess.Id == id
// orderby sess.CreatedTime descending
// select sess.ToConversation();
var conversation = db.GetConversation(id);
return conversation?.ToConversation();
}
@ -51,11 +46,6 @@ public partial class ConversationService : IConversationService
public async Task<List<Conversation>> GetConversations()
{
var db = _services.GetRequiredService<IBotSharpRepository>();
//var query = from sess in db.Conversation
// where sess.UserId == _user.Id
// orderby sess.CreatedTime descending
// select sess.ToConversation();
var user = db.User.FirstOrDefault(x => x.ExternalId == _user.Id);
var conversations = db.GetConversations(user?.Id);
return conversations.Select(x => x.ToConversation()).OrderByDescending(x => x.CreatedTime).ToList();

View file

@ -311,7 +311,7 @@ public class FileRepository : IBotSharpRepository
File.WriteAllText(instructionFile, agent.Instruction);
}
if (!agent.Functions.IsEmpty())
if (!agent.Functions.IsNullOrEmpty())
{
var functionFile = Path.Combine(dir, "functions.json");
var functions = new List<string>();

View file

@ -36,7 +36,7 @@ public class Router : IAgentRouting
var records = db.RoutingItem.Select(x => x.ToRoutingItem()).ToArray();
var profiles = db.RoutingProfile.ToList();
if (!profiles.IsEmpty())
if (!profiles.IsNullOrEmpty())
{
var state = _services.GetRequiredService<IConversationStateService>();
var name = state.GetState("channel");

View file

@ -16,7 +16,7 @@ public class RoutingController : ControllerBase, IApiAdapter
_routingService = routingService;
}
[HttpPost("/routing-items")]
[HttpPost("/routing/items")]
public async Task<List<RoutingItemViewModel>> CreateRoutingItems(List<RoutingItemCreationModel> routingItems)
{
var items = routingItems?.Select(x => x.ToRoutingItem())?.ToList() ?? new List<RoutingItem>();
@ -24,7 +24,7 @@ public class RoutingController : ControllerBase, IApiAdapter
return savedItems.Select(x => RoutingItemViewModel.FromRoutingItem(x)).ToList();
}
[HttpPost("/routing-profiles")]
[HttpPost("/routing/profiles")]
public async Task<List<RoutingProfileViewModel>> CreateRoutingProfiles(List<RoutingProfileCreationModel> routingProfiles)
{
var profiles = routingProfiles?.Select(x => x.ToRoutingProfile())?.ToList() ?? new List<RoutingProfile>();
@ -32,13 +32,13 @@ public class RoutingController : ControllerBase, IApiAdapter
return savedProfiles.Select(x => RoutingProfileViewModel.FromRoutingProfile(x)).ToList();
}
[HttpDelete("/routing-items")]
[HttpDelete("/routing/items")]
public async Task RemoveRoutingItems()
{
await _routingService.DeleteRoutingItems();
}
[HttpDelete("/routing-profiles")]
[HttpDelete("/routing/profiles")]
public async Task RemoveRoutingProfiles()
{
await _routingService.DeleteRoutingProfiles();

View file

@ -43,10 +43,10 @@ public class AgentUpdateModel
if (Samples != null)
agent.Samples = Samples;
if (!Functions.IsEmpty())
if (!Functions.IsNullOrEmpty())
agent.Functions = Functions;
if (!Responses.IsEmpty())
if (!Responses.IsNullOrEmpty())
agent.Responses = Responses;
return agent;

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0-preview.7.23375.6" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="MongoDB.Driver" Version="2.19.2" />
</ItemGroup>

View file

@ -7,8 +7,6 @@ public class ConversationCollection : MongoBase
public Guid AgentId { get; set; }
public Guid UserId { get; set; }
public string Title { get; set; }
public string Dialog { get; set; }
public List<KeyValueModel> State { get; set; }
public DateTime CreatedTime { get; set; }
public DateTime UpdatedTime { get; set; }

View file

@ -0,0 +1,9 @@
namespace BotSharp.Plugin.MongoStorage.Collections;
public class ConversationDialogCollection : MongoBase
{
public Guid ConversationId { get; set; }
public string Dialog { get; set; }
public DateTime CreatedTime { get; set; }
public DateTime UpdatedTime { get; set; }
}

View file

@ -0,0 +1,11 @@
using BotSharp.Abstraction.Repositories.Models;
namespace BotSharp.Plugin.MongoStorage.Collections;
public class ConversationStatesCollection : MongoBase
{
public Guid ConversationId { get; set; }
public List<KeyValueModel> State { get; set; }
public DateTime CreatedTime { get; set; }
public DateTime UpdatedTime { get; set; }
}

View file

@ -7,7 +7,7 @@ public class UserCollection : MongoBase
public string Email { get; set; }
public string Salt { get; set; }
public string Password { get; set; }
public string ExternalId { get; set; }
public string? ExternalId { get; set; }
public DateTime CreatedTime { get; set; }
public DateTime UpdatedTime { get; set; }

View file

@ -31,6 +31,12 @@ public class MongoDbContext
public IMongoCollection<ConversationCollection> Conversations
=> Database.GetCollection<ConversationCollection>("OneBrainConversations");
public IMongoCollection<ConversationDialogCollection> ConversationDialogs
=> Database.GetCollection<ConversationDialogCollection>("OneBrainConversationDialogs");
public IMongoCollection<ConversationStatesCollection> ConversationStates
=> Database.GetCollection<ConversationStatesCollection>("OneBrainConversationStates");
public IMongoCollection<UserCollection> Users
=> Database.GetCollection<UserCollection>("OneBrainUsers");

View file

@ -111,16 +111,26 @@ public class MongoRepository : IBotSharpRepository
return _conversations.AsQueryable();
}
_conversations = new List<ConversationRecord>();
var conversationDocs = _dc.Conversations?.AsQueryable()?.ToList() ?? new List<ConversationCollection>();
_conversations = conversationDocs.Select(x => new ConversationRecord
foreach (var conv in conversationDocs)
{
Id = x.Id.ToString(),
AgentId = x.AgentId.ToString(),
UserId = x.UserId.ToString(),
Title = x.Title,
CreatedTime = x.CreatedTime,
UpdatedTime = x.UpdatedTime
}).ToList();
var convId = conv.Id.ToString();
var dialog = GetConversationDialog(convId);
var states = GetConversationState(convId);
_conversations.Add(new ConversationRecord
{
Id = convId,
AgentId = conv.AgentId.ToString(),
UserId = conv.UserId.ToString(),
Title = conv.Title,
Dialog = dialog,
State = states,
CreatedTime = conv.CreatedTime,
UpdatedTime = conv.UpdatedTime
});
}
return _conversations.AsQueryable();
}
@ -214,8 +224,6 @@ public class MongoRepository : IBotSharpRepository
AgentId = Guid.Parse(x.AgentId),
UserId = Guid.Parse(x.UserId),
Title = x.Title,
Dialog = x.Dialog,
State = x.State,
CreatedTime = x.CreatedTime,
UpdatedTime = x.UpdatedTime
}).ToList();
@ -227,8 +235,6 @@ public class MongoRepository : IBotSharpRepository
.Set(x => x.AgentId, conversation.AgentId)
.Set(x => x.UserId, conversation.UserId)
.Set(x => x.Title, conversation.Title)
.Set(x => x.Dialog, conversation.Dialog)
.Set(x => x.State, conversation.State)
.Set(x => x.CreatedTime, conversation.CreatedTime)
.Set(x => x.UpdatedTime, conversation.UpdatedTime);
_dc.Conversations.UpdateOne(filter, update, _options);
@ -461,45 +467,63 @@ public class MongoRepository : IBotSharpRepository
{
if (conversation == null) return;
var collection = new ConversationCollection
var conv = new ConversationCollection
{
Id = Guid.Parse(conversation.Id),
AgentId = Guid.Parse(conversation.AgentId),
UserId = Guid.Parse(conversation.UserId),
Title = conversation.Title,
CreatedTime = DateTime.UtcNow,
UpdatedTime = DateTime.UtcNow,
};
var dialog = new ConversationDialogCollection
{
Id = Guid.NewGuid(),
ConversationId = conv.Id,
Dialog = string.Empty,
CreatedTime = DateTime.UtcNow,
UpdatedTime = DateTime.UtcNow,
};
var states = new ConversationStatesCollection
{
Id = Guid.NewGuid(),
ConversationId = conv.Id,
State = new List<KeyValueModel>(),
CreatedTime = DateTime.UtcNow,
UpdatedTime = DateTime.UtcNow,
};
_dc.Conversations.InsertOne(collection);
_dc.Conversations.InsertOne(conv);
_dc.ConversationDialogs.InsertOne(dialog);
_dc.ConversationStates.InsertOne(states);
}
public string GetConversationDialog(string conversationId)
{
if (string.IsNullOrEmpty(conversationId)) return string.Empty;
var filterById = Builders<ConversationCollection>.Filter.Eq(x => x.Id, Guid.Parse(conversationId));
var foundConversation = _dc.Conversations.Find(filterById).FirstOrDefault();
if (foundConversation == null) return string.Empty;
var filter = Builders<ConversationDialogCollection>.Filter.Eq(x => x.ConversationId, Guid.Parse(conversationId));
var foundDialog = _dc.ConversationDialogs.Find(filter).FirstOrDefault();
if (foundDialog == null) return string.Empty;
return foundConversation.Dialog;
return foundDialog.Dialog;
}
public void UpdateConversationDialog(string conversationId, string dialogs)
{
if (string.IsNullOrEmpty(conversationId)) return;
var filterById = Builders<ConversationCollection>.Filter.Eq(x => x.Id, Guid.Parse(conversationId));
var foundConversation = _dc.Conversations.Find(filterById).FirstOrDefault();
if (foundConversation == null) return;
var filter = Builders<ConversationDialogCollection>.Filter.Eq(x => x.ConversationId, Guid.Parse(conversationId));
var foundDialog = _dc.ConversationDialogs.Find(filter).FirstOrDefault();
if (foundDialog == null) return;
var update = Builders<ConversationCollection>.Update
var update = Builders<ConversationDialogCollection>.Update
.Set(x => x.Dialog, dialogs)
.Set(x => x.UpdatedTime, DateTime.UtcNow);
_dc.Conversations.UpdateOne(filterById, update);
_dc.ConversationDialogs.UpdateOne(filter, update);
}
public List<KeyValueModel> GetConversationState(string conversationId)
@ -507,11 +531,11 @@ public class MongoRepository : IBotSharpRepository
var states = new List<KeyValueModel>();
if (string.IsNullOrEmpty(conversationId)) return states;
var filterById = Builders<ConversationCollection>.Filter.Eq(x => x.Id, Guid.Parse(conversationId));
var foundConversation = _dc.Conversations.Find(filterById).FirstOrDefault();
if (foundConversation == null) return states;
var filter = Builders<ConversationStatesCollection>.Filter.Eq(x => x.ConversationId, Guid.Parse(conversationId));
var foundStates = _dc.ConversationStates.Find(filter).FirstOrDefault();
if (foundStates == null) return states;
var savedStates = foundConversation.State ?? new List<KeyValueModel>();
var savedStates = foundStates.State ?? new List<KeyValueModel>();
return savedStates;
}
@ -519,15 +543,15 @@ public class MongoRepository : IBotSharpRepository
{
if (string.IsNullOrEmpty(conversationId)) return;
var filterById = Builders<ConversationCollection>.Filter.Eq(x => x.Id, Guid.Parse(conversationId));
var foundConversation = _dc.Conversations.Find(filterById).FirstOrDefault();
if (foundConversation == null) return;
var filter = Builders<ConversationStatesCollection>.Filter.Eq(x => x.ConversationId, Guid.Parse(conversationId));
var foundStates = _dc.ConversationStates.Find(filter).FirstOrDefault();
if (foundStates == null) return;
var update = Builders<ConversationCollection>.Update
var update = Builders<ConversationStatesCollection>.Update
.Set(x => x.State, state)
.Set(x => x.UpdatedTime, DateTime.UtcNow);
_dc.Conversations.UpdateOne(filterById, update);
_dc.ConversationStates.UpdateOne(filter, update);
}
public ConversationRecord GetConversation(string conversationId)
@ -535,37 +559,54 @@ public class MongoRepository : IBotSharpRepository
if (string.IsNullOrEmpty(conversationId)) return null;
var filterById = Builders<ConversationCollection>.Filter.Eq(x => x.Id, Guid.Parse(conversationId));
var found = _dc.Conversations.Find(filterById).FirstOrDefault();
var filterDialog = Builders<ConversationDialogCollection>.Filter.Eq(x => x.ConversationId, Guid.Parse(conversationId));
var filterStates = Builders<ConversationStatesCollection>.Filter.Eq(x => x.ConversationId, Guid.Parse(conversationId));
return found != null ? new ConversationRecord
var conv = _dc.Conversations.Find(filterById).FirstOrDefault();
var dialog = _dc.ConversationDialogs.Find(filterDialog).FirstOrDefault();
var states = _dc.ConversationStates.Find(filterStates).FirstOrDefault();
if (conv == null) return null;
return new ConversationRecord
{
Id = found.Id.ToString(),
AgentId = found.AgentId.ToString(),
UserId = found.UserId.ToString(),
Title = found.Title,
Dialog = found.Dialog,
State = found.State,
CreatedTime = found.CreatedTime,
UpdatedTime = found.UpdatedTime
}: null;
Id = conv.Id.ToString(),
AgentId = conv.AgentId.ToString(),
UserId = conv.UserId.ToString(),
Title = conv.Title,
Dialog = dialog?.Dialog ?? string.Empty,
State = states?.State ?? new List<KeyValueModel>(),
CreatedTime = conv.CreatedTime,
UpdatedTime = conv.UpdatedTime
};
}
public List<ConversationRecord> GetConversations(string userId)
{
if (string.IsNullOrEmpty(userId)) return new List<ConversationRecord>();
var records = new List<ConversationRecord>();
if (string.IsNullOrEmpty(userId)) return records;
var filterByUserId = Builders<ConversationCollection>.Filter.Eq(x => x.UserId, Guid.Parse(userId));
var conversations = _dc.Conversations.Find(filterByUserId).ToList();
return conversations.Select(x => new ConversationRecord
foreach (var conv in conversations)
{
Id = x.Id.ToString(),
AgentId = x.AgentId.ToString(),
UserId = x.UserId.ToString(),
Title = x.Title,
Dialog = x.Dialog,
State = x.State,
CreatedTime = x.CreatedTime,
UpdatedTime = x.UpdatedTime
}).ToList();
var convId = conv.Id.ToString();
var dialog = GetConversationDialog(convId);
var states = GetConversationState(convId);
records.Add(new ConversationRecord
{
Id = convId,
AgentId = conv.AgentId.ToString(),
UserId = conv.UserId.ToString(),
Title = conv.Title,
Dialog = dialog,
State = states,
CreatedTime = conv.CreatedTime,
UpdatedTime = conv.UpdatedTime
});
}
return records;
}
}