generated from NetCoreTemplates/blazor-vue
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/mythz/pvq.app
- Loading branch information
Showing
3 changed files
with
317 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
using MyApp.ServiceModel; | ||
using ServiceStack; | ||
using ServiceStack.OrmLite; | ||
|
||
namespace MyApp.ServiceInterface; | ||
|
||
public class LeaderboardServices : Service | ||
{ | ||
/// <summary> | ||
/// Leader board stats | ||
/// - Most liked models by human votes | ||
/// - Most liked models by LLM votes | ||
/// - Answerer win rate | ||
/// - Human vs LLM win rate by human votes | ||
/// - Human vs LLM win rate by LLM votes | ||
/// - Model win rate by tag | ||
/// - Model total score | ||
/// - Model total score by tag | ||
/// </summary> | ||
/// <param name="request"></param> | ||
public async Task<object> Any(CalculateLeaderBoard request) | ||
{ | ||
var statTotals = await Db.SelectAsync<StatTotals>(); | ||
// filter to answers only | ||
var answers = statTotals.Where(x => x.Id.Contains('-')).ToList(); | ||
// Sum up votes by model, first group by UserName | ||
var statsByUser = answers.GroupBy(x => x.Id.SplitOnFirst('-')[1]).Select(x => new StatTotals | ||
{ | ||
Id = x.Key, | ||
UpVotes = x.Sum(y => y.UpVotes), | ||
DownVotes = x.Sum(y => y.DownVotes), | ||
StartingUpVotes = x.Sum(y => y.StartingUpVotes), | ||
FavoriteCount = x.Sum(y => y.FavoriteCount) | ||
}).ToList(); | ||
|
||
var statQuestions = statTotals.Where(x => !x.Id.Contains('-')).ToList(); | ||
|
||
var overallWinRates = statsByUser.GroupBy(x => x.Id).Select(y => | ||
{ | ||
var res = new LeaderBoardWinRate | ||
{ | ||
Id = y.Key, | ||
WinRate = CalculateWinRate(answers, y.Key, statQuestions.Count) | ||
}; | ||
return res; | ||
}).ToList(); | ||
|
||
var modelScale = 1 / overallWinRates.Where(x => IsHuman(x.Id) == false) | ||
.Sum(y => y.WinRate); | ||
|
||
|
||
var leaderBoard = new CalculateLeaderboardResponse | ||
{ | ||
MostLikedModels = statsByUser.Where(x => IsHuman(x.Id) == false) | ||
.OrderByDescending(x => x.GetScore()) | ||
.Select(x => new ModelTotalScore | ||
{ | ||
Id = x.Id, | ||
TotalScore = x.GetScore() | ||
}).ToList(), | ||
MostLikedModelsByLlm = statsByUser.Where(x => IsHuman(x.Id) == false) | ||
.OrderByDescending(x => x.StartingUpVotes) | ||
.Select(x => new ModelTotalStartUpVotes | ||
{ | ||
Id = x.Id, | ||
StartingUpVotes = x.GetScore() | ||
}) | ||
.ToList(), | ||
AnswererWinRate = overallWinRates, | ||
ModelWinRate = overallWinRates.Where(x => IsHuman(x.Id) == false) | ||
.Select(x => new ModelWinRate | ||
{ | ||
Id = x.Id, | ||
WinRate = x.WinRate * modelScale * 100 | ||
}).ToList(), | ||
ModelTotalScore = statsByUser.GroupBy(x => x.Id) | ||
.Select(x => new ModelTotalScore | ||
{ | ||
Id = x.Key, | ||
TotalScore = x.Sum(y => y.GetScore()) | ||
}).ToList() | ||
}; | ||
|
||
return leaderBoard; | ||
} | ||
|
||
bool IsHuman(string id) | ||
{ | ||
return id == "accepted" || id == "most-voted"; | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Take all answers, group by PostId derived user, select the answer with the highest score | ||
/// all divided by the total question count | ||
/// </summary> | ||
/// <param name="statTotalsList"></param> | ||
/// <param name="name"></param> | ||
/// <param name="questionCount"></param> | ||
/// <returns></returns> | ||
double CalculateWinRate(List<StatTotals> statTotalsList, string name, int questionCount) | ||
{ | ||
return ((double)statTotalsList | ||
.GroupBy(a => a.PostId | ||
).Select(aq => aq | ||
.MaxBy(b => b.GetScore())) | ||
.Count(winner => | ||
winner != null && winner.Id.Contains("-") && winner.Id.SplitOnFirst('-')[1] == name) | ||
/ questionCount) * 100; | ||
} | ||
} | ||
|
||
public class CalculateLeaderboardResponse | ||
{ | ||
public List<ModelTotalScore> MostLikedModels { get; set; } | ||
public List<ModelTotalStartUpVotes> MostLikedModelsByLlm { get; set; } | ||
public List<LeaderBoardWinRate> AnswererWinRate { get; set; } | ||
public List<LeaderBoardWinRate> HumanVsLlmWinRateByHumanVotes { get; set; } | ||
public List<LeaderBoardWinRate> HumanVsLlmWinRateByLlmVotes { get; set; } | ||
public List<ModelWinRateByTag> ModelWinRateByTag { get; set; } | ||
public List<ModelTotalScore> ModelTotalScore { get; set; } | ||
public List<ModelTotalScoreByTag> ModelTotalScoreByTag { get; set; } | ||
public List<ModelWinRate> ModelWinRate { get; set; } | ||
} | ||
|
||
public class ModelTotalScoreByTag | ||
{ | ||
public string Id { get; set; } | ||
public string Tag { get; set; } | ||
public int TotalScore { get; set; } | ||
} | ||
|
||
public class ModelTotalScore | ||
{ | ||
public string Id { get; set; } | ||
public int TotalScore { get; set; } | ||
} | ||
|
||
public class ModelTotalStartUpVotes | ||
{ | ||
public string Id { get; set; } | ||
public int StartingUpVotes { get; set; } | ||
} | ||
|
||
public class ModelWinRateByTag | ||
{ | ||
public string Id { get; set; } | ||
public string Tag { get; set; } | ||
public double WinRate { get; set; } | ||
} | ||
|
||
public class ModelWinRate | ||
{ | ||
public string Id { get; set; } | ||
public double WinRate { get; set; } | ||
} | ||
|
||
public class LeaderBoardWinRate | ||
{ | ||
public string Id { get; set; } | ||
public double WinRate { get; set; } | ||
} | ||
|
||
public class LeaderBoardWinRateByTag | ||
{ | ||
public string Id { get; set; } | ||
public string Tag { get; set; } | ||
public double WinRate { get; set; } | ||
} | ||
|
||
public class CalculateLeaderBoard : IReturn<CalculateLeaderboardResponse>, IGet | ||
{ | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,34 @@ | ||
@page "/leaderboard" | ||
@using MyApp.ServiceInterface | ||
@inherits AppComponentBase | ||
|
||
<PageTitle>Leaderboard</PageTitle> | ||
|
||
<div class="mt-8 mb-20 mx-auto max-w-fit"> | ||
<Heading1>Counter</Heading1> | ||
<Heading1>Leaderboard</Heading1> | ||
|
||
<div data-component="pages/Counter.mjs"></div> | ||
<div class="mt-8"> | ||
@if (data != null) | ||
{ | ||
<LeaderboardView LeaderBoardData="@data"/> | ||
} | ||
</div> | ||
|
||
</div> | ||
|
||
@code { | ||
|
||
CalculateLeaderboardResponse? data; | ||
|
||
protected override async Task OnInitializedAsync() | ||
{ | ||
await base.OnInitializedAsync(); | ||
var api = await ApiAsync(new CalculateLeaderBoard()); | ||
if (api.Succeeded) | ||
data = api.Response; | ||
else | ||
Console.WriteLine(api.Error?.Message); | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
@using MyApp.ServiceInterface | ||
|
||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"> | ||
<div class="bg-blue-500 text-white p-6 rounded-lg shadow-lg"> | ||
<h2 class="text-2xl font-bold mb-4">Most Liked Models</h2> | ||
<div class="space-y-4"> | ||
@foreach (var model in LeaderBoardData.MostLikedModelsByLlm.OrderByDescending(x => x.StartingUpVotes)) | ||
{ | ||
<div class="flex items-center"> | ||
<img src="@GetAvatarUrl(model.Id)" alt="Avatar" class="w-12 h-12 rounded-full mr-4" /> | ||
<div class="flex-1"> | ||
<h3 class="text-lg font-semibold">@GetModelName(model.Id)</h3> | ||
<div class="text-sm text-green-200">@model.StartingUpVotes votes</div> | ||
</div> | ||
</div> | ||
} | ||
</div> | ||
</div> | ||
|
||
<div class="bg-blue-500 text-white p-6 rounded-lg shadow-lg"> | ||
<h2 class="text-2xl font-bold mb-4">Total Votes</h2> | ||
<div class="space-y-4"> | ||
@foreach (var model in LeaderBoardData.ModelTotalScore.OrderByDescending(x => x.TotalScore)) | ||
{ | ||
<div class="flex items-center"> | ||
<img src="@GetAvatarUrl(model.Id)" alt="Avatar" class="w-12 h-12 rounded-full mr-4" /> | ||
<div class="flex-1"> | ||
<h3 class="text-lg font-semibold">@GetModelName(model.Id)</h3> | ||
<div class="text-sm text-green-200">@model.TotalScore votes</div> | ||
</div> | ||
</div> | ||
} | ||
</div> | ||
</div> | ||
|
||
<div class="bg-blue-500 text-white p-6 rounded-lg shadow-lg"> | ||
<h2 class="text-2xl font-bold mb-4">Overall Win Rate</h2> | ||
<div class="space-y-4"> | ||
@foreach (var model in LeaderBoardData.AnswererWinRate.OrderByDescending(x => x.WinRate)) | ||
{ | ||
<div class="flex items-center"> | ||
<img src="@GetAvatarUrl(model.Id)" alt="Avatar" class="w-12 h-12 rounded-full mr-4" /> | ||
<div class="flex-1"> | ||
<h3 class="text-lg font-semibold">@GetModelName(model.Id)</h3> | ||
<div class="text-sm text-green-200">@(Math.Round(model.WinRate,2)) %</div> | ||
</div> | ||
</div> | ||
} | ||
</div> | ||
</div> | ||
|
||
<div class="bg-blue-500 text-white p-6 rounded-lg shadow-lg"> | ||
<h2 class="text-2xl font-bold mb-4">Win Rate By Models</h2> | ||
<div class="space-y-4"> | ||
@foreach (var model in LeaderBoardData.ModelWinRate.OrderByDescending(x => x.WinRate)) | ||
{ | ||
<div class="flex items-center"> | ||
<img src="@GetAvatarUrl(model.Id)" alt="Avatar" class="w-12 h-12 rounded-full mr-4" /> | ||
<div class="flex-1"> | ||
<h3 class="text-lg font-semibold">@GetModelName(model.Id)</h3> | ||
<div class="text-sm text-green-200">@(Math.Round(model.WinRate,2)) %</div> | ||
</div> | ||
</div> | ||
} | ||
</div> | ||
</div> | ||
|
||
</div> | ||
|
||
@code { | ||
[Parameter] | ||
public CalculateLeaderboardResponse LeaderBoardData { get; set; } | ||
|
||
private string GetModelName(string modelId) | ||
{ | ||
if (modelAliases.TryGetValue(modelId, out var alias)) | ||
{ | ||
return alias; | ||
} | ||
return modelId; | ||
} | ||
|
||
private string GetAvatarUrl(string modelId) | ||
{ | ||
var userName = modelUserMapping.TryGetValue(modelId, out var value) ? value : modelId; | ||
return $"/avatar/{userName}"; | ||
} | ||
|
||
Dictionary<string, string> modelUserMapping = new() | ||
{ | ||
{ "mistral", "mistral" }, | ||
{ "mixtral", "mixtral" }, | ||
{ "mixtral-8x7b", "mixtral" }, | ||
{ "mixtral-8x7b-32768", "mixtral"}, | ||
{ "codellama", "codellama" }, | ||
{ "deepseek-coder:6.7b", "deepseek-coder" }, | ||
{ "deepseek-coder-6", "deepseek-coder"}, | ||
{ "gemma-2b", "gemma-2b" }, | ||
{ "gemma", "gemma" }, | ||
{ "gemma-7b", "gemma" }, | ||
{ "phi", "phi" } | ||
}; | ||
|
||
Dictionary<string, string> modelAliases = new() | ||
{ | ||
{ "mistral", "Mistral 7B" }, | ||
{ "mixtral", "Mixtral 8x7B" }, | ||
{ "codellama", "Codellama" }, | ||
{ "deepseek-coder:6.7b", "Deepseek Coder 6.7B" }, | ||
{ "deepseek-coder-6", "Deepseek Coder 6.7B" }, | ||
{ "gemma-2b", "Gemma 2B" }, | ||
{ "gemma", "Gemma 7B" }, | ||
{ "gemma-7b", "Gemma 7B" }, | ||
{ "phi", "Phi" } | ||
}; | ||
|
||
} |