From 2feaf8f3ad707c76e7ceaa864305bf83d0d0e99a Mon Sep 17 00:00:00 2001 From: Ethan Date: Fri, 27 Dec 2024 18:16:50 -0500 Subject: [PATCH] Add leaderboards --- rust-learning/src/groq.rs | 4 +- rust-learning/src/gui.rs | 1 + rust-learning/src/gui/leaderboard.rs | 110 +++++++++++++++++++++++ rust-learning/src/gui/model_response.rs | 12 ++- rust-learning/src/gui/model_selection.rs | 3 +- rust-learning/src/gui/prompt_input.rs | 31 +++---- rust-learning/src/gui/state.rs | 14 +-- 7 files changed, 148 insertions(+), 27 deletions(-) create mode 100644 rust-learning/src/gui/leaderboard.rs diff --git a/rust-learning/src/groq.rs b/rust-learning/src/groq.rs index 8a08b38..5894b23 100644 --- a/rust-learning/src/groq.rs +++ b/rust-learning/src/groq.rs @@ -64,8 +64,8 @@ impl Groq { }, }], usage: ChatCompletionUsage { - total_tokens: 0, - total_time: 0.0, + total_tokens: -1, + total_time: -1.0, }, }; diff --git a/rust-learning/src/gui.rs b/rust-learning/src/gui.rs index d8d7be2..ff33816 100644 --- a/rust-learning/src/gui.rs +++ b/rust-learning/src/gui.rs @@ -4,6 +4,7 @@ pub mod model_response; pub mod model_selection; pub mod prompt_input; pub mod state; +pub mod leaderboard; pub fn main(models_available: Vec) -> eframe::Result { let options = eframe::NativeOptions { diff --git a/rust-learning/src/gui/leaderboard.rs b/rust-learning/src/gui/leaderboard.rs new file mode 100644 index 0000000..06dad02 --- /dev/null +++ b/rust-learning/src/gui/leaderboard.rs @@ -0,0 +1,110 @@ +use eframe::egui::{self, Response, Ui, Widget}; + +use super::state::AppState; + +pub struct Leaderboard { + entries: Vec, +} + +#[derive(Clone)] +struct LeaderboardEntry { + name: String, + tokens: i32, + time: f32, +} + +impl Leaderboard { + pub fn new(app_state: &AppState) -> Self { + let entries = app_state + .selected_models + .iter() + .map(|model| LeaderboardEntry { + name: model.name.clone(), + tokens: model.tokens, + time: model.time, + }) + .collect(); + + Self { entries } + } +} + +impl Widget for Leaderboard { + fn ui(self, ui: &mut Ui) -> Response { + let leaderboard_gap = 8.0; + + let mut time_leaderboard = self.entries.clone(); + time_leaderboard.sort_by(|a, b| { + a.time + .partial_cmp(&b.time) + .unwrap_or(std::cmp::Ordering::Equal) + }); + + let mut tokens_leaderboard = self.entries.clone(); + tokens_leaderboard.sort_by(|a, b| { + b.tokens + .partial_cmp(&a.tokens) + .unwrap_or(std::cmp::Ordering::Equal) + }); + + let mut time_per_token_leaderboard = self.entries.clone(); + time_per_token_leaderboard.sort_by(|a, b| { + (a.time / a.tokens as f32) + .partial_cmp(&(b.time / b.tokens as f32)) + .unwrap_or(std::cmp::Ordering::Equal) + }); + + ui.vertical(|ui| { + ui.heading("Leaderboard"); + + ui.horizontal_top(|ui| { + egui::Grid::new("time_leaderboard") + .striped(true) + .show(ui, |ui| { + ui.strong("Name"); + ui.strong("Time"); + ui.end_row(); + + for entry in time_leaderboard { + ui.label(entry.name); + ui.label(entry.time.to_string()); + ui.end_row(); + } + }); + + ui.allocate_space(egui::Vec2::new(leaderboard_gap, 0.0)); + + egui::Grid::new("tokens_leaderboard") + .striped(true) + .show(ui, |ui| { + ui.strong("Name"); + ui.strong("Tokens"); + ui.end_row(); + + for entry in tokens_leaderboard { + ui.label(entry.name); + ui.label(entry.tokens.to_string()); + ui.end_row(); + } + }); + + ui.allocate_space(egui::Vec2::new(leaderboard_gap, 0.0)); + + egui::Grid::new("time_per_token_leaderboard") + .striped(true) + .show(ui, |ui| { + ui.strong("Name"); + ui.strong("Time per Token"); + ui.end_row(); + + for entry in time_per_token_leaderboard { + ui.label(entry.name); + ui.label((entry.time / entry.tokens as f32).to_string()); + ui.end_row(); + } + }); + }) + }) + .response + } +} diff --git a/rust-learning/src/gui/model_response.rs b/rust-learning/src/gui/model_response.rs index 1f2bb0e..a9e6c82 100644 --- a/rust-learning/src/gui/model_response.rs +++ b/rust-learning/src/gui/model_response.rs @@ -6,8 +6,8 @@ use crate::groq::{types::ChatCompletionResponse, GROQ_CLIENT}; pub struct ModelResponse { pub name: String, message: String, - tokens: i32, - time: f32, + pub tokens: i32, + pub time: f32, loading: bool, tx: Sender, rx: Receiver, @@ -45,7 +45,11 @@ impl ModelResponse { } } - fn spawn_chat_completion_task(prompt: String, model_name: String, tx: Sender) { + fn spawn_chat_completion_task( + prompt: String, + model_name: String, + tx: Sender, + ) { tokio::spawn(async move { let response = GROQ_CLIENT.chat_completion(model_name, prompt).await; tx.send(response).expect("Failed to send response"); @@ -65,7 +69,7 @@ impl Widget for &mut ModelResponse { .rounding(4.0) .fill(egui::Color32::DARK_GRAY) .show(ui, |ui| { - ui.label(RichText::new(&self.name).strong()); + ui.label(RichText::new(&self.name).strong().heading()); ui.horizontal_wrapped(|ui| { ui.horizontal(|ui| { diff --git a/rust-learning/src/gui/model_selection.rs b/rust-learning/src/gui/model_selection.rs index 8aefc16..8072b0d 100644 --- a/rust-learning/src/gui/model_selection.rs +++ b/rust-learning/src/gui/model_selection.rs @@ -14,9 +14,10 @@ impl<'a> ModelSelection<'a> { impl<'a> Widget for ModelSelection<'a> { fn ui(self, ui: &mut Ui) -> Response { + ui.heading("Models"); ui.horizontal(|ui| { egui::ComboBox::from_label("") - .selected_text("Models") + .selected_text("Model List") .show_ui(ui, |ui| { for model in &self.app_state.models_available { let selected_models = self diff --git a/rust-learning/src/gui/prompt_input.rs b/rust-learning/src/gui/prompt_input.rs index 3d257fa..5422804 100644 --- a/rust-learning/src/gui/prompt_input.rs +++ b/rust-learning/src/gui/prompt_input.rs @@ -14,22 +14,23 @@ impl<'a> PromptInput<'a> { impl<'a> Widget for PromptInput<'a> { fn ui(self, ui: &mut Ui) -> Response { - let label = ui.label("Prompt:"); - ui.add_sized( - Vec2::new(ui.available_width(), 100.0), - TextEdit::multiline(&mut self.app_state.prompt_input), - ) - .labelled_by(label.id); + ui.vertical(|ui| { + let label = ui.heading("Prompt"); + ui.add_sized( + Vec2::new(ui.available_width() / 2.0, 100.0), + TextEdit::multiline(&mut self.app_state.prompt_input), + ) + .labelled_by(label.id); - ui.horizontal(|ui| { - if ui.button("Submit").clicked() { - self.app_state.handle_submission(); - } + ui.horizontal(|ui| { + if ui.button("Submit").clicked() { + self.app_state.handle_submission(); + } - if ui.button("Clear").clicked() { - self.app_state.prompt_input.clear(); - } - }) - .response + if ui.button("Clear").clicked() { + self.app_state.prompt_input.clear(); + } + }) + }).response } } diff --git a/rust-learning/src/gui/state.rs b/rust-learning/src/gui/state.rs index b6abf4c..f0395a5 100644 --- a/rust-learning/src/gui/state.rs +++ b/rust-learning/src/gui/state.rs @@ -3,7 +3,7 @@ use eframe::{ CreationContext, }; -use super::{model_response::ModelResponse, model_selection, prompt_input}; +use super::{leaderboard, model_response::ModelResponse, model_selection, prompt_input}; pub struct AppState { pub selected_models: Vec, @@ -30,12 +30,16 @@ impl AppState { impl eframe::App for AppState { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("Groq Model Comparison"); - ui.label("Compare Groq models with ease!"); - ui.add(model_selection::ModelSelection::new(self)); - ui.add(prompt_input::PromptInput::new(self)); + ui.allocate_space(egui::Vec2::new(0.0, 8.0)); + + ui.horizontal(|ui| { + ui.add(prompt_input::PromptInput::new(self)); + ui.allocate_space(egui::Vec2::new(16.0, 0.0)); + ui.add(leaderboard::Leaderboard::new(self)); + }); + ui.add(Separator::default().spacing(16.0));