Merge branch 'SciSharp:master' into master

This commit is contained in:
Haiping 2025-01-13 09:13:50 -06:00 committed by GitHub
commit 7df494dc67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 121 additions and 8 deletions

View file

@ -3,5 +3,6 @@ namespace BotSharp.Abstraction.Conversations;
public interface IConversationStorage
{
void Append(string conversationId, RoleDialogModel dialog);
void Append(string conversationId, IEnumerable<RoleDialogModel> dialogs);
List<RoleDialogModel> GetDialogs(string conversationId);
}

View file

@ -90,6 +90,7 @@ public interface IBotSharpRepository : IHaveServiceProvider
void UpdateConversationTitle(string conversationId, string title);
void UpdateConversationTitleAlias(string conversationId, string titleAlias);
bool UpdateConversationTags(string conversationId, List<string> tags);
bool AppendConversationTags(string conversationId, List<string> tags);
bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request);
void UpdateConversationBreakpoint(string conversationId, ConversationBreakpoint breakpoint);
ConversationBreakpoint? GetConversationBreakpoint(string conversationId);

View file

@ -1,22 +1,18 @@
using BotSharp.Abstraction.Messaging;
using BotSharp.Abstraction.Messaging.Models.RichContent;
using BotSharp.Abstraction.Options;
using System.IO;
namespace BotSharp.Core.Conversations.Services;
public class ConversationStorage : IConversationStorage
{
private readonly BotSharpDatabaseSettings _dbSettings;
private readonly BotSharpOptions _options;
private readonly IServiceProvider _services;
public ConversationStorage(
BotSharpDatabaseSettings dbSettings,
BotSharpOptions options,
IServiceProvider services)
{
_dbSettings = dbSettings;
_services = services;
_options = options;
}
@ -94,6 +90,76 @@ public class ConversationStorage : IConversationStorage
db.AppendConversationDialogs(conversationId, dialogElements);
}
public void Append(string conversationId, IEnumerable<RoleDialogModel> dialogs)
{
if (dialogs.IsNullOrEmpty()) return;
var db = _services.GetRequiredService<IBotSharpRepository>();
var dialogElements = new List<DialogElement>();
foreach ( var dialog in dialogs)
{
if (dialog.Role == AgentRole.Function)
{
var meta = new DialogMetaData
{
Role = dialog.Role,
AgentId = dialog.CurrentAgentId,
MessageId = dialog.MessageId,
MessageType = dialog.MessageType,
FunctionName = dialog.FunctionName,
CreateTime = dialog.CreatedAt
};
var content = dialog.Content.RemoveNewLine();
if (string.IsNullOrEmpty(content))
{
continue;
}
dialogElements.Add(new DialogElement
{
MetaData = meta,
Content = dialog.Content,
SecondaryContent = dialog.SecondaryContent,
Payload = dialog.Payload
});
}
else
{
var meta = new DialogMetaData
{
Role = dialog.Role,
AgentId = dialog.CurrentAgentId,
MessageId = dialog.MessageId,
MessageType = dialog.MessageType,
SenderId = dialog.SenderId,
FunctionName = dialog.FunctionName,
CreateTime = dialog.CreatedAt
};
var content = dialog.Content.RemoveNewLine();
if (string.IsNullOrEmpty(content))
{
continue;
}
var richContent = dialog.RichContent != null ? JsonSerializer.Serialize(dialog.RichContent, _options.JsonSerializerOptions) : null;
var secondaryRichContent = dialog.SecondaryRichContent != null ? JsonSerializer.Serialize(dialog.SecondaryRichContent, _options.JsonSerializerOptions) : null;
dialogElements.Add(new DialogElement
{
MetaData = meta,
Content = dialog.Content,
SecondaryContent = dialog.SecondaryContent,
RichContent = richContent,
SecondaryRichContent = secondaryRichContent,
Payload = dialog.Payload
});
}
}
db.AppendConversationDialogs(conversationId, dialogElements);
}
public List<RoleDialogModel> GetDialogs(string conversationId)
{
var db = _services.GetRequiredService<IBotSharpRepository>();

View file

@ -111,6 +111,9 @@ public class BotSharpDbContext : Database, IBotSharpRepository
public bool UpdateConversationTags(string conversationId, List<string> tags)
=> throw new NotImplementedException();
public bool AppendConversationTags(string conversationId, List<string> tags)
=> throw new NotImplementedException();
public bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request)
=> throw new NotImplementedException();

View file

@ -169,6 +169,27 @@ namespace BotSharp.Core.Repository
return true;
}
public bool AppendConversationTags(string conversationId, List<string> tags)
{
if (string.IsNullOrEmpty(conversationId) || tags.IsNullOrEmpty()) return false;
var convDir = FindConversationDirectory(conversationId);
if (string.IsNullOrEmpty(convDir)) return false;
var convFile = Path.Combine(convDir, CONVERSATION_FILE);
if (!File.Exists(convFile)) return false;
var json = File.ReadAllText(convFile);
var conv = JsonSerializer.Deserialize<Conversation>(json, _options);
var curTags = conv.Tags ?? new();
var newTags = curTags.Concat(tags).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();
conv.Tags = newTags;
conv.UpdatedTime = DateTime.UtcNow;
File.WriteAllText(convFile, JsonSerializer.Serialize(conv, _options));
return true;
}
public bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request)
{
if (string.IsNullOrEmpty(conversationId)) return false;
@ -507,12 +528,13 @@ namespace BotSharp.Core.Repository
continue;
}
if (excludeAgentIds.Contains(conv.AgentId) || conv.UpdatedTime > utcNow.AddHours(-bufferHours))
if (conv.UpdatedTime > utcNow.AddHours(-bufferHours))
{
continue;
}
if (conv.DialogCount <= messageLimit)
if ((excludeAgentIds.Contains(conv.AgentId) && conv.DialogCount == 0)
|| (!excludeAgentIds.Contains(conv.AgentId) && conv.DialogCount <= messageLimit))
{
ids.Add(conv.Id);
if (ids.Count >= batchSize)

View file

@ -425,7 +425,7 @@ public partial class MongoRepository
var agent = _dc.Agents.AsQueryable().FirstOrDefault(x => x.Id == agentId);
if (agent == null) return string.Empty;
return agent.Templates?.FirstOrDefault(x => x.Name == templateName.ToLower())?.Content ?? string.Empty;
return agent.Templates?.FirstOrDefault(x => x.Name.IsEqualTo(templateName))?.Content ?? string.Empty;
}
public bool PatchAgentTemplate(string agentId, AgentTemplate template)

View file

@ -139,6 +139,24 @@ public partial class MongoRepository
return res.ModifiedCount > 0;
}
public bool AppendConversationTags(string conversationId, List<string> tags)
{
if (string.IsNullOrEmpty(conversationId) || tags.IsNullOrEmpty()) return false;
var filter = Builders<ConversationDocument>.Filter.Eq(x => x.Id, conversationId);
var conv = _dc.Conversations.Find(filter).FirstOrDefault();
if (conv == null) return false;
var curTags = conv.Tags ?? new();
var newTags = curTags.Concat(tags).Distinct(StringComparer.InvariantCultureIgnoreCase).ToList();
var update = Builders<ConversationDocument>.Update
.Set(x => x.Tags, newTags)
.Set(x => x.UpdatedTime, DateTime.UtcNow);
var res = _dc.Conversations.UpdateOne(filter, update);
return res.ModifiedCount > 0;
}
public bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request)
{
if (string.IsNullOrEmpty(conversationId)) return false;
@ -455,7 +473,9 @@ public partial class MongoRepository
{
var skip = (page - 1) * batchSize;
var candidates = _dc.Conversations.AsQueryable()
.Where(x => !excludeAgentIds.Contains(x.AgentId) && x.DialogCount <= messageLimit && x.UpdatedTime <= utcNow.AddHours(-bufferHours))
.Where(x => ((!excludeAgentIds.Contains(x.AgentId) && x.DialogCount <= messageLimit)
|| (excludeAgentIds.Contains(x.AgentId) && x.DialogCount == 0))
&& x.UpdatedTime <= utcNow.AddHours(-bufferHours))
.Skip(skip)
.Take(batchSize)
.Select(x => x.Id)