Merge pull request #301 from iceljc/features/save-conversation-log
add content log and state log
This commit is contained in:
commit
5f80b5e802
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations;
|
||||
|
|
@ -14,6 +15,8 @@ public interface IConversationService
|
|||
Task<List<Conversation>> GetLastConversations();
|
||||
Task<bool> DeleteConversation(string id);
|
||||
Task<bool> TruncateConversation(string conversationId, string messageId);
|
||||
Task<List<ConversationContentLogModel>> GetConversationContentLogs(string conversationId);
|
||||
Task<List<ConversationStateLogModel>> GetConversationStateLogs(string conversationId);
|
||||
|
||||
/// <summary>
|
||||
/// Send message to LLM
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
public class ConversationStateLogModel
|
||||
{
|
||||
[JsonPropertyName("conversation_id")]
|
||||
public string ConvsersationId { get; set; }
|
||||
[JsonPropertyName("states")]
|
||||
public string States { get; set; }
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
|
@ -9,4 +9,6 @@ public class ConversationSetting
|
|||
public int MaxRecursiveDepth { get; set; } = 3;
|
||||
public bool EnableLlmCompletionLog { get; set; }
|
||||
public bool EnableExecutionLog { get; set; }
|
||||
public bool EnableContentLog { get; set; }
|
||||
public bool EnableStateLog { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
namespace BotSharp.Abstraction.Loggers.Models;
|
||||
|
||||
public class StreamingLogModel
|
||||
public class ConversationContentLogModel
|
||||
{
|
||||
[JsonPropertyName("conversation_id")]
|
||||
public string ConversationId { get; set; }
|
||||
[JsonPropertyName("message_id")]
|
||||
public string MessageId { get; set; }
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; set; }
|
||||
[JsonPropertyName("role")]
|
||||
|
|
@ -13,5 +15,5 @@ public class StreamingLogModel
|
|||
public string Content { get; set; }
|
||||
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTime CreateTime { get; set; }
|
||||
public DateTime CreateTime { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
namespace BotSharp.Abstraction.Loggers.Models;
|
||||
|
||||
public class ConversationStateLogModel
|
||||
{
|
||||
[JsonPropertyName("conversation_id")]
|
||||
public string ConversationId { get; set; }
|
||||
[JsonPropertyName("message_id")]
|
||||
public string MessageId { get; set; }
|
||||
[JsonPropertyName("states")]
|
||||
public Dictionary<string, string> States { get; set; }
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTime CreateTime { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
namespace BotSharp.Abstraction.Loggers.Models;
|
||||
|
||||
public class LlmCompletionLog
|
||||
{
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Repositories.Models;
|
||||
|
|
@ -70,6 +71,16 @@ public interface IBotSharpRepository
|
|||
void SaveLlmCompletionLog(LlmCompletionLog log);
|
||||
#endregion
|
||||
|
||||
#region Conversation Content Log
|
||||
void SaveConversationContentLog(ConversationContentLogModel log);
|
||||
List<ConversationContentLogModel> GetConversationContentLogs(string conversationId);
|
||||
#endregion
|
||||
|
||||
#region Conversation State Log
|
||||
void SaveConversationStateLog(ConversationStateLogModel log);
|
||||
List<ConversationStateLogModel> GetConversationStateLogs(string conversationId);
|
||||
#endregion
|
||||
|
||||
#region Statistics
|
||||
void IncrementConversationCount();
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
|
||||
namespace BotSharp.Core.Conversations.Services;
|
||||
|
||||
public partial class ConversationService
|
||||
{
|
||||
public async Task<List<ConversationContentLogModel>> GetConversationContentLogs(string conversationId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var logs = db.GetConversationContentLogs(conversationId);
|
||||
return await Task.FromResult(logs);
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<ConversationStateLogModel>> GetConversationStateLogs(string conversationId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var logs = db.GetConversationStateLogs(conversationId);
|
||||
return await Task.FromResult(logs);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
|
|
@ -255,6 +256,30 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
}
|
||||
#endregion
|
||||
|
||||
#region Conversation Content Log
|
||||
public void SaveConversationContentLog(ConversationContentLogModel log)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<ConversationContentLogModel> GetConversationContentLogs(string conversationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversation State Log
|
||||
public void SaveConversationStateLog(ConversationStateLogModel log)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public List<ConversationStateLogModel> GetConversationStateLogs(string conversationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Stats
|
||||
public void IncrementConversationCount()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using Serilog;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Repository
|
||||
|
|
@ -54,14 +56,112 @@ namespace BotSharp.Core.Repository
|
|||
Directory.CreateDirectory(logDir);
|
||||
}
|
||||
|
||||
var index = GetNextLlmCompletionLogIndex(logDir, log.MessageId);
|
||||
var index = GetNextLogIndex(logDir, log.MessageId);
|
||||
var file = Path.Combine(logDir, $"{log.MessageId}.{index}.log");
|
||||
File.WriteAllText(file, JsonSerializer.Serialize(log, _options));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversation Content Log
|
||||
public void SaveConversationContentLog(ConversationContentLogModel log)
|
||||
{
|
||||
if (log == null) return;
|
||||
|
||||
log.ConversationId = log.ConversationId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
log.MessageId = log.MessageId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
|
||||
var convDir = FindConversationDirectory(log.ConversationId);
|
||||
if (string.IsNullOrEmpty(convDir))
|
||||
{
|
||||
convDir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, log.ConversationId);
|
||||
Directory.CreateDirectory(convDir);
|
||||
}
|
||||
|
||||
var logDir = Path.Combine(convDir, "content_log");
|
||||
if (!Directory.Exists(logDir))
|
||||
{
|
||||
Directory.CreateDirectory(logDir);
|
||||
}
|
||||
|
||||
var index = GetNextLogIndex(logDir, log.MessageId);
|
||||
var file = Path.Combine(logDir, $"{log.MessageId}.{index}.log");
|
||||
File.WriteAllText(file, JsonSerializer.Serialize(log, _options));
|
||||
}
|
||||
|
||||
public List<ConversationContentLogModel> GetConversationContentLogs(string conversationId)
|
||||
{
|
||||
var logs = new List<ConversationContentLogModel>();
|
||||
if (string.IsNullOrEmpty(conversationId)) return logs;
|
||||
|
||||
var convDir = FindConversationDirectory(conversationId);
|
||||
if (string.IsNullOrEmpty(convDir)) return logs;
|
||||
|
||||
var logDir = Path.Combine(convDir, "content_log");
|
||||
if (!Directory.Exists(logDir)) return logs;
|
||||
|
||||
foreach (var file in Directory.GetFiles(logDir))
|
||||
{
|
||||
var text = File.ReadAllText(file);
|
||||
var log = JsonSerializer.Deserialize<ConversationContentLogModel>(text);
|
||||
if (log == null) continue;
|
||||
|
||||
logs.Add(log);
|
||||
}
|
||||
return logs.OrderBy(x => x.CreateTime).ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversation State Log
|
||||
public void SaveConversationStateLog(ConversationStateLogModel log)
|
||||
{
|
||||
if (log == null) return;
|
||||
|
||||
log.ConversationId = log.ConversationId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
log.MessageId = log.MessageId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
|
||||
var convDir = FindConversationDirectory(log.ConversationId);
|
||||
if (string.IsNullOrEmpty(convDir))
|
||||
{
|
||||
convDir = Path.Combine(_dbSettings.FileRepository, _conversationSettings.DataDir, log.ConversationId);
|
||||
Directory.CreateDirectory(convDir);
|
||||
}
|
||||
|
||||
var logDir = Path.Combine(convDir, "state_log");
|
||||
if (!Directory.Exists(logDir))
|
||||
{
|
||||
Directory.CreateDirectory(logDir);
|
||||
}
|
||||
|
||||
var index = GetNextLogIndex(logDir, log.MessageId);
|
||||
var file = Path.Combine(logDir, $"{log.MessageId}.{index}.log");
|
||||
File.WriteAllText(file, JsonSerializer.Serialize(log, _options));
|
||||
}
|
||||
|
||||
public List<ConversationStateLogModel> GetConversationStateLogs(string conversationId)
|
||||
{
|
||||
var logs = new List<ConversationStateLogModel>();
|
||||
if (string.IsNullOrEmpty(conversationId)) return logs;
|
||||
|
||||
var convDir = FindConversationDirectory(conversationId);
|
||||
if (string.IsNullOrEmpty(convDir)) return logs;
|
||||
|
||||
var logDir = Path.Combine(convDir, "state_log");
|
||||
if (!Directory.Exists(logDir)) return logs;
|
||||
|
||||
foreach (var file in Directory.GetFiles(logDir))
|
||||
{
|
||||
var text = File.ReadAllText(file);
|
||||
var log = JsonSerializer.Deserialize<ConversationStateLogModel>(text);
|
||||
if (log == null) continue;
|
||||
|
||||
logs.Add(log);
|
||||
}
|
||||
return logs.OrderBy(x => x.CreateTime).ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
private int GetNextLlmCompletionLogIndex(string logDir, string id)
|
||||
private int GetNextLogIndex(string logDir, string id)
|
||||
{
|
||||
var files = Directory.GetFiles(logDir);
|
||||
if (files.IsNullOrEmpty())
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
|
||||
public class CommonContentGeneratingHook : IContentGeneratingHook
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using System;
|
||||
|
|
@ -34,4 +35,18 @@ public class LoggerController : ControllerBase
|
|||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("/logger/conversation/{conversationId}/content-log")]
|
||||
public async Task<List<ConversationContentLogModel>> GetConversationContentLogs([FromRoute] string conversationId)
|
||||
{
|
||||
var conversationService = _services.GetRequiredService<IConversationService>();
|
||||
return await conversationService.GetConversationContentLogs(conversationId);
|
||||
}
|
||||
|
||||
[HttpGet("/logger/conversation/{conversationId}/state-log")]
|
||||
public async Task<List<ConversationStateLogModel>> GetConversationStateLogs([FromRoute] string conversationId)
|
||||
{
|
||||
var conversationService = _services.GetRequiredService<IConversationService>();
|
||||
return await conversationService.GetConversationStateLogs(conversationId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Messaging;
|
||||
using BotSharp.Abstraction.Messaging.JsonConverters;
|
||||
using BotSharp.Abstraction.Messaging.Models.RichContent;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace BotSharp.Plugin.ChatHub.Hooks;
|
||||
|
|
@ -117,20 +119,28 @@ public class ChatHubConversationHook : ConversationHookBase
|
|||
}
|
||||
}, _serializerOptions);
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnMessageReceivedFromAssistant", json);
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversateStatesGenerated", BuildConversationStates(conv.ConversationId, state.GetStates()));
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnConversateStatesGenerated", BuildConversationStates(conv.ConversationId, state.GetStates(), message));
|
||||
|
||||
await base.OnResponseGenerated(message);
|
||||
}
|
||||
|
||||
private string BuildConversationStates(string conversationId, Dictionary<string, string> states)
|
||||
private string BuildConversationStates(string conversationId, Dictionary<string, string> states, RoleDialogModel message)
|
||||
{
|
||||
var model = new ConversationStateLogModel
|
||||
var log = new ConversationStateLogModel
|
||||
{
|
||||
ConvsersationId = conversationId,
|
||||
States = JsonSerializer.Serialize(states, _serializerOptions),
|
||||
ConversationId = conversationId,
|
||||
MessageId = message.MessageId,
|
||||
States = states,
|
||||
CreateTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
return JsonSerializer.Serialize(model, _serializerOptions);
|
||||
var convSettings = _services.GetRequiredService<ConversationSetting>();
|
||||
if (convSettings.EnableStateLog)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
db.SaveConversationStateLog(log);
|
||||
}
|
||||
|
||||
return JsonSerializer.Serialize(log, _serializerOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Loggers;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Abstraction.Repositories;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace BotSharp.Plugin.ChatHub.Hooks;
|
||||
|
|
@ -37,7 +38,7 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook
|
|||
{
|
||||
var conversationId = _state.GetConversationId();
|
||||
var log = $"MessageId: {message.MessageId} ==>\r\n{message.Role}: {message.Content}";
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, _user.UserName, message.Role, log));
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, _user.UserName, log, message));
|
||||
}
|
||||
|
||||
public async Task BeforeGenerating(Agent agent, List<RoleDialogModel> conversations)
|
||||
|
|
@ -64,25 +65,34 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook
|
|||
var conversationId = _state.GetConversationId();
|
||||
var agent = await agentService.LoadAgent(message.CurrentAgentId);
|
||||
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, agent?.Name, message.Role, tokenStats.Prompt));
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, agent?.Name, tokenStats.Prompt, message));
|
||||
|
||||
var log = message.Role == AgentRole.Function ?
|
||||
$"[{agent?.Name}]: {message.FunctionName}({message.FunctionArgs})" :
|
||||
$"[{agent?.Name}]: {message.Content}";
|
||||
log += $"\r\n<== MessageId: {message.MessageId}";
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, agent?.Name, message.Role, log));
|
||||
await _chatHub.Clients.User(_user.Id).SendAsync("OnContentLogGenerated", BuildLog(conversationId, agent?.Name, log, message));
|
||||
}
|
||||
|
||||
private string BuildLog(string conversationId, string? name, string role, string content)
|
||||
private string BuildLog(string conversationId, string? name, string content, RoleDialogModel message)
|
||||
{
|
||||
var log = new StreamingLogModel
|
||||
var log = new ConversationContentLogModel
|
||||
{
|
||||
ConversationId = conversationId,
|
||||
MessageId = message.MessageId,
|
||||
Name = name,
|
||||
Role = role,
|
||||
Role = message.Role,
|
||||
Content = content,
|
||||
CreateTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var convSettings = _services.GetRequiredService<ConversationSetting>();
|
||||
if (convSettings.EnableContentLog)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
db.SaveConversationContentLog(log);
|
||||
}
|
||||
|
||||
return JsonSerializer.Serialize(log, _serializerOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
namespace BotSharp.Plugin.MongoStorage.Collections;
|
||||
|
||||
public class ConversationContentLogDocument : MongoBase
|
||||
{
|
||||
public string ConversationId { get; set; }
|
||||
public string MessageId { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string Role { get; set; }
|
||||
public string Content { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace BotSharp.Plugin.MongoStorage.Collections;
|
||||
|
||||
public class ConversationStateLogDocument : MongoBase
|
||||
{
|
||||
public string ConversationId { get; set; }
|
||||
public string MessageId { get; set; }
|
||||
public Dictionary<string, string> States { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ public class MongoDbContext
|
|||
_mongoClient = new MongoClient(mongoDbConnectionString);
|
||||
_mongoDbDatabaseName = GetDatabaseName(mongoDbConnectionString);
|
||||
_collectionPrefix = dbSettings.TablePrefix.IfNullOrEmptyAs("BotSharp");
|
||||
//CreateIndex();
|
||||
}
|
||||
|
||||
private string GetDatabaseName(string mongoDbConnectionString)
|
||||
|
|
@ -29,6 +28,7 @@ public class MongoDbContext
|
|||
|
||||
private IMongoDatabase Database { get { return _mongoClient.GetDatabase(_mongoDbDatabaseName); } }
|
||||
|
||||
#region Indexes
|
||||
private IMongoCollection<ConversationDocument> CreateConversationIndex()
|
||||
{
|
||||
var collection = Database.GetCollection<ConversationDocument>($"{_collectionPrefix}_Conversations");
|
||||
|
|
@ -39,7 +39,6 @@ public class MongoDbContext
|
|||
var indexDef = Builders<ConversationDocument>.IndexKeys.Descending(x => x.CreatedTime);
|
||||
collection.Indexes.CreateOne(new CreateIndexModel<ConversationDocument>(indexDef));
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
|
@ -53,28 +52,44 @@ public class MongoDbContext
|
|||
var indexDef = Builders<AgentTaskDocument>.IndexKeys.Descending(x => x.CreatedTime);
|
||||
collection.Indexes.CreateOne(new CreateIndexModel<AgentTaskDocument>(indexDef));
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
private IMongoCollection<ConversationContentLogDocument> CreateContentLogIndex()
|
||||
{
|
||||
var collection = Database.GetCollection<ConversationContentLogDocument>($"{_collectionPrefix}_ConversationContentLogs");
|
||||
var indexes = collection.Indexes.List().ToList();
|
||||
var createTimeIndex = indexes.FirstOrDefault(x => x.GetElement("name").ToString().StartsWith("CreateTime"));
|
||||
if (createTimeIndex == null)
|
||||
{
|
||||
var indexDef = Builders<ConversationContentLogDocument>.IndexKeys.Ascending(x => x.CreateTime);
|
||||
collection.Indexes.CreateOne(new CreateIndexModel<ConversationContentLogDocument>(indexDef));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
private IMongoCollection<ConversationStateLogDocument> CreateStateLogIndex()
|
||||
{
|
||||
var collection = Database.GetCollection<ConversationStateLogDocument>($"{_collectionPrefix}_ConversationStateLogs");
|
||||
var indexes = collection.Indexes.List().ToList();
|
||||
var createTimeIndex = indexes.FirstOrDefault(x => x.GetElement("name").ToString().StartsWith("CreateTime"));
|
||||
if (createTimeIndex == null)
|
||||
{
|
||||
var indexDef = Builders<ConversationStateLogDocument>.IndexKeys.Ascending(x => x.CreateTime);
|
||||
collection.Indexes.CreateOne(new CreateIndexModel<ConversationStateLogDocument>(indexDef));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public IMongoCollection<AgentDocument> Agents
|
||||
=> Database.GetCollection<AgentDocument>($"{_collectionPrefix}_Agents");
|
||||
|
||||
public IMongoCollection<AgentTaskDocument> AgentTasks
|
||||
{
|
||||
get
|
||||
{
|
||||
return CreateAgentTaskIndex();
|
||||
}
|
||||
}
|
||||
=> CreateAgentTaskIndex();
|
||||
|
||||
public IMongoCollection<ConversationDocument> Conversations
|
||||
{
|
||||
get
|
||||
{
|
||||
return CreateConversationIndex();
|
||||
}
|
||||
}
|
||||
=> CreateConversationIndex();
|
||||
|
||||
public IMongoCollection<ConversationDialogDocument> ConversationDialogs
|
||||
=> Database.GetCollection<ConversationDialogDocument>($"{_collectionPrefix}_ConversationDialogs");
|
||||
|
|
@ -85,15 +100,21 @@ public class MongoDbContext
|
|||
public IMongoCollection<ExecutionLogDocument> ExectionLogs
|
||||
=> Database.GetCollection<ExecutionLogDocument>($"{_collectionPrefix}_ExecutionLogs");
|
||||
|
||||
public IMongoCollection<LlmCompletionLogDocument> LlmCompletionLogs
|
||||
=> Database.GetCollection<LlmCompletionLogDocument>($"{_collectionPrefix}_LlmCompletionLogs");
|
||||
|
||||
public IMongoCollection<ConversationContentLogDocument> ContentLogs
|
||||
=> CreateContentLogIndex();
|
||||
|
||||
public IMongoCollection<ConversationStateLogDocument> StateLogs
|
||||
=> CreateStateLogIndex();
|
||||
|
||||
public IMongoCollection<UserDocument> Users
|
||||
=> Database.GetCollection<UserDocument>($"{_collectionPrefix}_Users");
|
||||
|
||||
public IMongoCollection<UserAgentDocument> UserAgents
|
||||
=> Database.GetCollection<UserAgentDocument>($"{_collectionPrefix}_UserAgents");
|
||||
|
||||
public IMongoCollection<LlmCompletionLogDocument> LlmCompletionLogs
|
||||
=> Database.GetCollection<LlmCompletionLogDocument>($"{_collectionPrefix}_Llm_Completion_Logs");
|
||||
|
||||
public IMongoCollection<PluginDocument> Plugins
|
||||
=> Database.GetCollection<PluginDocument>($"{_collectionPrefix}_Plugins");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,14 +63,20 @@ public partial class MongoRepository
|
|||
var filterSates = Builders<ConversationStateDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterExeLog = Builders<ExecutionLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterPromptLog = Builders<LlmCompletionLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterContentLog = Builders<ConversationContentLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
var filterStateLog = Builders<ConversationStateLogDocument>.Filter.Eq(x => x.ConversationId, conversationId);
|
||||
|
||||
var exeLogDeleted = _dc.ExectionLogs.DeleteMany(filterExeLog);
|
||||
var promptLogDeleted = _dc.LlmCompletionLogs.DeleteMany(filterPromptLog);
|
||||
var contentLogDeleted = _dc.ContentLogs.DeleteMany(filterContentLog);
|
||||
var stateLogDeleted = _dc.StateLogs.DeleteMany(filterStateLog);
|
||||
var statesDeleted = _dc.ConversationStates.DeleteMany(filterSates);
|
||||
var dialogDeleted = _dc.ConversationDialogs.DeleteMany(filterDialog);
|
||||
var convDeleted = _dc.Conversations.DeleteMany(filterConv);
|
||||
|
||||
return convDeleted.DeletedCount > 0 || dialogDeleted.DeletedCount > 0 || statesDeleted.DeletedCount > 0
|
||||
|| exeLogDeleted.DeletedCount > 0 || promptLogDeleted.DeletedCount > 0;
|
||||
|| exeLogDeleted.DeletedCount > 0 || promptLogDeleted.DeletedCount > 0
|
||||
|| contentLogDeleted.DeletedCount > 0 || stateLogDeleted.DeletedCount > 0;
|
||||
}
|
||||
|
||||
public List<DialogElement> GetConversationDialogs(string conversationId)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Loggers.Models;
|
||||
using BotSharp.Plugin.MongoStorage.Collections;
|
||||
using BotSharp.Plugin.MongoStorage.Models;
|
||||
|
||||
|
|
@ -58,4 +58,82 @@ public partial class MongoRepository
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Conversation Content Log
|
||||
public void SaveConversationContentLog(ConversationContentLogModel log)
|
||||
{
|
||||
if (log == null) return;
|
||||
|
||||
var conversationId = log.ConversationId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
var messageId = log.MessageId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
|
||||
var logDoc = new ConversationContentLogDocument
|
||||
{
|
||||
ConversationId = conversationId,
|
||||
MessageId = messageId,
|
||||
Name = log.Name,
|
||||
Role = log.Role,
|
||||
Content = log.Content,
|
||||
CreateTime = log.CreateTime
|
||||
};
|
||||
|
||||
_dc.ContentLogs.InsertOne(logDoc);
|
||||
}
|
||||
|
||||
public List<ConversationContentLogModel> GetConversationContentLogs(string conversationId)
|
||||
{
|
||||
var logs = _dc.ContentLogs
|
||||
.AsQueryable()
|
||||
.Where(x => x.ConversationId == conversationId)
|
||||
.Select(x => new ConversationContentLogModel
|
||||
{
|
||||
ConversationId = x.ConversationId,
|
||||
MessageId = x.MessageId,
|
||||
Name = x.Name,
|
||||
Role = x.Role,
|
||||
Content = x.Content,
|
||||
CreateTime = x.CreateTime
|
||||
})
|
||||
.OrderBy(x => x.CreateTime)
|
||||
.ToList();
|
||||
return logs;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversation State Log
|
||||
public void SaveConversationStateLog(ConversationStateLogModel log)
|
||||
{
|
||||
if (log == null) return;
|
||||
|
||||
var conversationId = log.ConversationId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
var messageId = log.MessageId.IfNullOrEmptyAs(Guid.NewGuid().ToString());
|
||||
|
||||
var logDoc = new ConversationStateLogDocument
|
||||
{
|
||||
ConversationId = conversationId,
|
||||
MessageId = messageId,
|
||||
States = log.States,
|
||||
CreateTime = log.CreateTime
|
||||
};
|
||||
|
||||
_dc.StateLogs.InsertOne(logDoc);
|
||||
}
|
||||
|
||||
public List<ConversationStateLogModel> GetConversationStateLogs(string conversationId)
|
||||
{
|
||||
var logs = _dc.StateLogs
|
||||
.AsQueryable()
|
||||
.Where(x => x.ConversationId == conversationId)
|
||||
.Select(x => new ConversationStateLogModel
|
||||
{
|
||||
ConversationId = x.ConversationId,
|
||||
MessageId = x.MessageId,
|
||||
States = x.States,
|
||||
CreateTime = x.CreateTime
|
||||
})
|
||||
.OrderBy(x => x.CreateTime)
|
||||
.ToList();
|
||||
return logs;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,9 @@
|
|||
"DataDir": "conversations",
|
||||
"ShowVerboseLog": false,
|
||||
"EnableLlmCompletionLog": false,
|
||||
"EnableExecutionLog": true
|
||||
"EnableExecutionLog": true,
|
||||
"EnableContentLog": true,
|
||||
"EnableStateLog": true
|
||||
},
|
||||
|
||||
"Statistics": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue