Add new plugin for dashboard metrics

This commit is contained in:
Visagan Guruparan 2024-01-28 22:18:40 -06:00
parent 0c066d6b4a
commit 910ab43fbd
15 changed files with 201 additions and 5 deletions

View file

@ -81,6 +81,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.HttpHandler
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.SqlDriver", "src\Plugins\BotSharp.Plugin.SqlDriver\BotSharp.Plugin.SqlDriver.csproj", "{D775DB67-A4B4-44E5-9144-522689590057}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.Dashboard", "src\Plugins\BotSharp.Plugin.Dashboard\BotSharp.Plugin.Dashboard.csproj", "{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -313,6 +315,14 @@ Global
{D775DB67-A4B4-44E5-9144-522689590057}.Release|Any CPU.Build.0 = Release|Any CPU
{D775DB67-A4B4-44E5-9144-522689590057}.Release|x64.ActiveCfg = Release|Any CPU
{D775DB67-A4B4-44E5-9144-522689590057}.Release|x64.Build.0 = Release|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|x64.ActiveCfg = Debug|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Debug|x64.Build.0 = Debug|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|Any CPU.Build.0 = Release|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|x64.ActiveCfg = Release|Any CPU
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -353,6 +363,7 @@ Global
{5CA3335E-E6AD-46FD-B277-29BBC3A16500} = {E29DC6C4-5E57-48C5-BCB0-6B8F84782749}
{32D9E720-6FE6-4F29-94B1-B10B05BFAD75} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
{D775DB67-A4B4-44E5-9144-522689590057} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A9969D89-C98B-40A5-A12B-FC87E55B3A19}

View file

@ -48,7 +48,9 @@ public interface IBotSharpRepository
List<Conversation> GetLastConversations();
bool TruncateConversation(string conversationId, string messageId);
#endregion
#region Statistics
void IncrementConversationCount();
#endregion
#region Execution Log
void AddExecutionLogs(string conversationId, List<string> logs);
List<string> GetExecutionLogs(string conversationId);

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Abstraction.Statistics.Model
{
public class Statistics
{
public string Id { get; set; } = string.Empty;
public int ConversationCount { get; set; }
public DateTime UpdatedDateTime { get; set; }
}
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Abstraction.Statistics.Settings
{
public class StatisticsSettings
{
public string DataDir { get; set; }
}
}

View file

@ -184,7 +184,12 @@ public class BotSharpDbContext : Database, IBotSharpRepository
throw new NotImplementedException();
}
#endregion
#region Stats
public void IncrementConversationCount()
{
throw new NotImplementedException();
}
#endregion
#region User
public User? GetUserByEmail(string email)

View file

@ -0,0 +1,57 @@
using BotSharp.Abstraction.Statistics.Model;
using System.IO;
namespace BotSharp.Core.Repository
{
public partial class FileRepository
{
public void IncrementConversationCount()
{
var statsFileDirectory = FindCurrentStatsDirectory();
if (statsFileDirectory == null)
{
statsFileDirectory = CreateStatsFileDirectory();
}
var fileName = GenerateStatsFileName();
var statsFile = Path.Combine(statsFileDirectory, fileName);
if (!File.Exists(statsFile))
{
File.WriteAllText(statsFile, JsonSerializer.Serialize(new Statistics()
{
Id = Guid.NewGuid().ToString(),
UpdatedDateTime = DateTime.UtcNow
}, _options));
}
var json = File.ReadAllText(statsFile);
var stats = JsonSerializer.Deserialize<Statistics>(json, _options);
stats.ConversationCount += 1;
stats.UpdatedDateTime = DateTime.UtcNow;
File.WriteAllText(statsFile, JsonSerializer.Serialize(stats, _options));
}
public string? CreateStatsFileDirectory()
{
var dir = GenerateStatsDirectoryName();
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
return dir;
}
private string? FindCurrentStatsDirectory()
{
var dir = GenerateStatsDirectoryName();
if (!Directory.Exists(dir)) return null;
return dir;
}
private string GenerateStatsDirectoryName()
{
return Path.Combine(_dbSettings.FileRepository, "stats", DateTime.UtcNow.Year.ToString(), DateTime.UtcNow.ToString("MM"));
}
private string GenerateStatsFileName()
{
var fileName = DateTime.UtcNow.ToString("MMdd");
return $"{fileName}-{STATS_FILE}";
}
}
}

View file

@ -29,6 +29,7 @@ public partial class FileRepository : IBotSharpRepository
private const string USER_FILE = "user.json";
private const string USER_AGENT_FILE = "agents.json";
private const string CONVERSATION_FILE = "conversation.json";
private const string STATS_FILE = "stats.json";
private const string DIALOG_FILE = "dialogs.txt";
private const string STATE_FILE = "state.json";
private const string EXECUTION_LOG_FILE = "execution.log";

View file

@ -28,7 +28,6 @@ public class PluginController : ControllerBase
{
var menu = new List<PluginMenuDef>
{
new PluginMenuDef("Dashboard", link: "/page/dashboard", icon: "bx bx-home-circle", weight: 1),
new PluginMenuDef("Apps", weight: 5)
{
IsHeader = true,

View file

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,32 @@
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Plugins;
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Settings;
using BotSharp.Abstraction.Statistics.Settings;
using BotSharp.Plugin.Dashboard.Hooks;
namespace BotSharp.Plugin.Dashboard;
public class DashboardPlugin : IBotSharpPlugin
{
public string Id => "d42a0c21-b461-44f6-ada2-499510d260af";
public string Name => "Dashboard";
public string Description => "Dashboard that offering real-time statistics on model performance, usage trends, and user feedback";
public void RegisterDI(IServiceCollection services, IConfiguration config)
{
services.AddScoped<IConversationHook, StatsConversationHook>();
services.AddScoped(provider =>
{
var settingService = provider.GetRequiredService<ISettingService>();
return settingService.Bind<StatisticsSettings>("Statistics");
});
}
public bool AttachMenu(List<PluginMenuDef> menu)
{
var section = menu.First(x => x.Label == "Apps");
menu.Add(new PluginMenuDef("Dashboard", link: "/page/dashboard", icon: "bx bx-home-circle", weight: section.Weight - 1));
return true;
}
}

View file

@ -0,0 +1,20 @@
using BotSharp.Abstraction.Conversations;
using BotSharp.Abstraction.Plugins.Models;
using BotSharp.Abstraction.Repositories;
namespace BotSharp.Plugin.Dashboard.Hooks;
public class StatsConversationHook : ConversationHookBase
{
private readonly IServiceProvider _services;
public StatsConversationHook(IServiceProvider services)
{
_services = services;
}
public override async Task OnConversationInitialized(Conversation conversation)
{
var db = _services.GetRequiredService<IBotSharpRepository>();
db.IncrementConversationCount();
}
}

View file

@ -0,0 +1,13 @@
global using System;
global using System.Collections.Generic;
global using System.Text;
global using System.Threading.Tasks;
global using System.Linq;
global using System.Text.Json;
global using BotSharp.Abstraction.Conversations.Models;
global using BotSharp.Abstraction.Agents.Models;
global using BotSharp.Abstraction.MLTasks;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using System.Text.Json.Serialization;
global using BotSharp.Abstraction.Utilities;

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BotSharp.Plugin.MongoStorage.Repository
{
public partial class MongoRepository
{
#region Statistics
public void IncrementConversationCount()
{
throw new NotImplementedException();
}
#endregion
}
}

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
@ -27,6 +27,7 @@
<ItemGroup>
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
<ProjectReference Include="..\Plugins\BotSharp.Plugin.Dashboard\BotSharp.Plugin.Dashboard.csproj" />
</ItemGroup>
<ItemGroup Condition="$(SolutionName)==BotSharp">

View file

@ -82,7 +82,9 @@
"EnableLlmCompletionLog": false,
"EnableExecutionLog": true
},
"Stats": {
"DataDir": "stats"
},
"LlamaSharp": {
"Interactive": true,
"ModelDir": "C:/Users/haipi/Downloads",
@ -163,6 +165,7 @@
"Assemblies": [
"BotSharp.Plugin.MongoStorage",
"BotSharp.Core",
"BotSharp.Plugin.Dashboard",
"BotSharp.Plugin.AzureOpenAI",
"BotSharp.Plugin.GoogleAI",
"BotSharp.Plugin.MetaAI",