diff --git a/.gitignore b/.gitignore index 3def4937..226bf67a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ + __pycache__/ *.py[cod] *$py.class @@ -5,6 +6,8 @@ model_files/ medscribe_env/ **/.DS_Store chat_data/ +.env/ finetunedmodels/ +.env/ src/geval/mistral-7b-instruct-v0.2.Q4_K_M.gguf eval_files/ diff --git a/CHANGELOG.md b/CHANGELOG.md index b0278c04..094b8db0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ - Support multiple models for evaluation and finetuning - Support multiple models for chat - ## 1-31 - Added Evaluation - Added Evaluation via GUI diff --git a/pegasus.py b/pegasus.py new file mode 100644 index 00000000..c2708a26 --- /dev/null +++ b/pegasus.py @@ -0,0 +1,27 @@ +# import pegasus +from transformers import PegasusForConditionalGeneration, PegasusTokenizer +from GUI import * + +class Pegasus: + def __init__ (self): + # load pegasus for summarization + self.model_name = "google/pegasus-xsum" + self.tokenizer = PegasusTokenizer.from_pretrained(self.model_name) # initialize pegasus' tokenizer + self.model = PegasusForConditionalGeneration.from_pretrained(self.model_name) # initialize pegasus model + + + def tokenize(self, input_text): + # tokenize text + tokenized = self.tokenizer(input_text, truncation = True, padding = "longest", return_tensors = "pt") + return tokenized + + def summarizer(self, tokenized_text): + # summarize + summarized = self.model.generate(**tokenized_text) + return summarized + + def detokenize(self, summarized_text): + # detokenize + summary = self.tokenizer.batch_decode (summarized_text) + return summary + diff --git a/requirements.txt b/requirements.txt index b66e6510..ee24cf20 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,4 @@ rouge-score>=0.1.2 nltk>=3.8.1 bert-score>=0.3.13 evaluate>=0.4.0 -llama-cpp-python>=0.2.11 \ No newline at end of file +llama-cpp-python>=0.2.11 diff --git a/sources.txt b/sources.txt new file mode 100644 index 00000000..5ae0d13a --- /dev/null +++ b/sources.txt @@ -0,0 +1,18 @@ + +Works Cited + +Avinash. “LLM Evaluation Metrics — BLEU, ROGUE and METEOR Explained.” Medium, 7 Aug. 2024, avinashselvam.medium.com/llm-evaluation-metrics-bleu-rogue-and-meteor-explained-a5d2b129e87f. Accessed 11 Feb. 2025. +Bais, Gourav. “LLM Evaluation for Text Summarization.” Neptune.ai, 25 Sept. 2024, neptune.ai/blog/llm-evaluation-text-summarization. Accessed 7 Feb. 2025. (photo) +Banerjee, Satanjeev, and Alon Lavie. METEOR: An Automatic Metric for MT Evaluation with Improved Correlation with Human Judgments. 2005. +Bajaj, Ganesh. “When to Use BLEU Score: Evaluating Text Generation with N-Gram Precision.” Medium, Artificial Intelligence in Plain English, 26 Sept. 2024, ai.plainenglish.io/when-to-use-bleu-score-evaluating-text-generation-with-n-gram-precision-3431829a641e. Accessed 7 Feb. 2025. (photo) +“BERT Score - a Hugging Face Space by Evaluate-Metric.” Huggingface.co, huggingface.co/spaces/evaluate-metric/bertscore. +courtzc. “Evaluating the Performance of LLM Summarization Prompts with G-Eval.” Microsoft.com, 25 June 2024, learn.microsoft.com/en-us/ai/playbook/technology-guidance/generative-ai/working-with-llms/evaluation/g-eval-metric-for-summarization. Accessed 11 Feb. 2025. +Falcão, Fabiano. “Metrics for Evaluating Summarization of Texts Performed by Transformers: How to Evaluate The….” Medium, 22 Apr. 2023, fabianofalcao.medium.com/metrics-for-evaluating-summarization-of-texts-performed-by-transformers-how-to-evaluate-the-b3ce68a309c3. +Issiaka Faissal Compaore, et al. “AI-Driven Generation of News Summaries: Leveraging GPT and Pegasus Summarizer for Efficient Information Extraction.” Hal.science, 5 Feb. 2024, hal.science/hal-04437765, https://hal.science/hal-04437765. Accessed 11 Feb. 2025. +Liu, Yang, et al. G-EVAL: NLG Evaluation Using GPT-4 with Better Human Alignment. +Otten, Neri Van, and Neri Van Otten. “METEOR Metric in NLP: How It Works & How to Tutorial in Python.” Spot Intelligence, 26 Aug. 2024, spotintelligence.com/2024/08/26/meteor-metric-in-nlp-how-it-works-how-to-tutorial-in-python/. +---. “ROUGE Metric in NLP: Complete Guide & How to Tutorial in Python.” Spot Intelligence, 12 Aug. 2024, spotintelligence.com/2024/08/12/rouge-metric-in-nlp/. +Ruman. “BERT Score Explained | Medium.” Medium, 17 May 2024, rumn.medium.com/bert-score-explained-8f384d37bb06. Accessed 7 Feb. 2025. (photo) +Yang, Xinyu, et al. “Navigating Dataset Documentations in AI: A Large-Scale Analysis of Dataset Cards on Hugging Face.” ArXiv.org, 24 Jan. 2024, arxiv.org/abs/2401.13822. Accessed 7 Feb. 2025. + + diff --git a/src/components/__init__.py b/src/components/__init__.py index 359cffc1..150f0162 100644 --- a/src/components/__init__.py +++ b/src/components/__init__.py @@ -6,4 +6,3 @@ from components.llm_input import LLMInput from components.llm_list import LLMList from components.evaluation_visualizer import EvaluationVisualizer -from components.llm_details import LLMDetails \ No newline at end of file diff --git a/src/components/evaluation_form.py b/src/components/evaluation_form.py index fdd4725c..f7feeb9d 100644 --- a/src/components/evaluation_form.py +++ b/src/components/evaluation_form.py @@ -60,6 +60,5 @@ def start_evaluation(self): dataset_path, model_path, start_idx, - end_idx, - self.use_geval.get() # Pass the G-EVAL toggle state - ) \ No newline at end of file + end_idx + ) diff --git a/src/components/llm_details.py b/src/components/llm_details.py index 4371bdd4..83cc19bb 100644 --- a/src/components/llm_details.py +++ b/src/components/llm_details.py @@ -4,14 +4,17 @@ import os from itertools import islice from collections import OrderedDict + class LLMDetails(tk.Frame): def __init__(self, parent, llm, **kwargs): super().__init__(parent, bg="#D2E9FC", **kwargs) self.llm = llm self.setup_input_area() + def setup_input_area(self): self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) + # Container frame for LLM Name, LLM Details self.container = tk.Frame(self, bg="#D2E9FC") self.container.grid(row=0, column=0, sticky="nsew", padx=0, pady=15) @@ -19,18 +22,22 @@ def setup_input_area(self): self.container.grid_rowconfigure(1, weight=1) self.container.grid_columnconfigure(0, weight=1) # for name frame self.container.grid_columnconfigure(1, weight=1) # for details frame + # LLM Name container self.llm_name_container = tk.Frame(self.container, bg="#D2E9FC") self.llm_name_container.grid(row=0, column=0, sticky="ew", padx=(5, 10), pady=(20, 5)) self.llm_name_container.grid_columnconfigure(0, weight=1) - # LLM details container frame with rounded corners + + # LLM details container frame with rounded corners self.llm_details_container = RoundedFrame(self.container, "#FFFFFF", radius=50) self.llm_details_container.grid(row=1, column=0, sticky="nsew", padx=(20, 5), pady=10) self.llm_details_container.grid_rowconfigure(0, weight=1) self.llm_details_container.grid_columnconfigure(0, weight=1) + # "LLM Name" string variable string = tk.StringVar() string.set("LLM: " + self.llm) + # "Import LLM" area self.name_label = tk.Label( self.llm_name_container, @@ -42,6 +49,7 @@ def setup_input_area(self): justify="left" ) self.name_label.grid(row=0, column=0, sticky="w", padx=20, pady=(20, 10)) + # LLM detail area self.details = tk.Text( self.llm_details_container, @@ -54,9 +62,11 @@ def setup_input_area(self): highlightthickness=0, relief="flat" ) + self.details.grid(row=0, column=0, sticky="nsew", padx=20, pady=20) self.details.grid_rowconfigure(0, weight=1) config = self.get_model_info() + # get first 10 in config first_twenty = dict(islice(config.items(), 20)) rev = OrderedDict(reversed(list(first_twenty.items()))) @@ -66,6 +76,8 @@ def setup_input_area(self): self.details.insert("1.0", "\n") self.details.insert("1.0", str_key + ": " + str_value) self.details.insert("1.0", "\n") + + def get_model_info(self): # cd to model_files cwd = os.getcwd() @@ -74,4 +86,5 @@ def get_model_info(self): model_dir = os.path.join(parent, file) f = open(model_dir) # read config file of selected model config = json.load(f) # load configurations - return config \ No newline at end of file + return config + diff --git a/src/components/llm_input.py b/src/components/llm_input.py index 941ae1fe..33298149 100644 --- a/src/components/llm_input.py +++ b/src/components/llm_input.py @@ -208,4 +208,4 @@ def get_input(self): def clear_input(self): self.input_text.delete("1.0", "end") - self.input_text.focus() \ No newline at end of file + self.input_text.focus() diff --git a/src/components/llm_list.py b/src/components/llm_list.py index df30e233..57a20d38 100644 --- a/src/components/llm_list.py +++ b/src/components/llm_list.py @@ -75,16 +75,11 @@ def get_models(self): cwd = os.getcwd() # current directory parent = os.path.dirname(cwd) # parent directory model_dir = os.path.join(parent, "model_files") - - # Create model_files directory if it doesn't exist - if not os.path.exists(model_dir): - os.makedirs(model_dir) - - # check all folders in model_files folder - for folder in os.listdir(model_dir): + # check if model_files + for folder in os.listdir(model_dir): # list all folders in model_files folder if os.path.isdir(os.path.join(model_dir, folder)): folder_list.append(folder) - + return folder_list def write_list(self, list): @@ -101,4 +96,4 @@ def mouse_scroll(self, event): self.list.yview_scroll(-1, "units") elif event.num == 5: self.list.yview_scroll(1, "units") - return "break" \ No newline at end of file + return "break" diff --git a/src/components/navbar.py b/src/components/navbar.py index bf97dc41..0753ea05 100644 --- a/src/components/navbar.py +++ b/src/components/navbar.py @@ -4,10 +4,10 @@ # Navigation items nav_items = [ - ("Home","home"), + ("Home", "home"), ("Evaluations", "evaluations"), ("LLMs", "llms"), - ("Finetune", "finetune") + ("Finetune", "finetune"), ] class Navbar(tk.Frame): @@ -15,7 +15,7 @@ def __init__(self, parent, show_page_callback, **kwargs): super().__init__(parent, bg="#FFFFFF", **kwargs) # Set callback function self.show_page_callback = show_page_callback - self.current_page = "llms" # Default page + self.current_page = "home" # Default page self.buttons = {} # Store button references self.logo_photo = None self._setup_navbar() @@ -94,7 +94,7 @@ def _setup_navbar(self): btn.bind("", lambda e, b=btn_container, p=page: self._on_hover(b, p)) btn.bind("", lambda e, b=btn_container, p=page: self._on_leave(b, p)) - self.set_active_page("llms") + self.set_active_page("home") def _handle_click(self, page): if page != self.current_page: @@ -137,4 +137,4 @@ def _on_leave(self, container, page): else: container.configure(bg="#E8F0FE") for child in container.winfo_children(): - child.configure(bg="#E8F0FE") \ No newline at end of file + child.configure(bg="#E8F0FE") diff --git a/src/download_pegasus.py b/src/download_pegasus.py index 73ef0138..8d3fe45c 100644 --- a/src/download_pegasus.py +++ b/src/download_pegasus.py @@ -20,10 +20,19 @@ def download_model(): """ Model Details: +<<<<<<< HEAD +├── config.json (Architecture blueprint) +├── generation_config.json (Controls how the model generates text: beam search) +├── model.safetensors (Weights that change when doing finetuning) +├── special_tokens_map.json (Maps special tokens like [PAD], [EOS], [UNK] to their IDs, Used for handling start/end of text, padding, unknown words) +├── spiece.model (The tokenizer's vocabulary and rules, Defines how to split text into tokens) +└── tokenizer_config.json (Configuration for the tokenizer's behavior) + +======= ├── config.json (Model architecture configuration) ├── generation_config.json (Text generation parameters) ├── model.safetensors (Model weights) ├── special_tokens_map.json (Mapping of special tokens like [PAD], [EOS]) ├── tokenizer.json (Tokenizer vocabulary and rules) └── tokenizer_config.json (Tokenizer configuration) -""" \ No newline at end of file +""" diff --git a/src/main.py b/src/main.py index 7456e5b6..b9a5b74d 100644 --- a/src/main.py +++ b/src/main.py @@ -6,6 +6,7 @@ from pages.finetune_page import FinetunePage from pages.home_page import HomePage + # Set environment variable os.environ['TOKENIZERS_PARALLELISM'] = 'false' @@ -20,7 +21,6 @@ def setup_gui(self): self._configure_root() self._configure_grid() self._setup_navbar() - self.show_page("llms") # Start with llm page def _configure_root(self): self.root.title("Assess.ai") @@ -45,6 +45,7 @@ def _clear_content(self): def show_page(self, page_name): # Show the new page self._clear_content() + if page_name == "evaluations": self.current_page = EvaluationPage(self.root) elif page_name == "llms": @@ -52,7 +53,8 @@ def show_page(self, page_name): elif page_name == "finetune": self.current_page = FinetunePage(self.root) elif page_name == "home": - self.current_page = HomePage(self.root) + self.current_page = HomePage(self.root, self.show_page) + def main(): # Initialize root and components @@ -66,9 +68,10 @@ def main(): # Initialize GUI app = AssessAIGUI(root) + app.show_page("home") # Start main loop root.mainloop() if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/src/pages/evaluation_page.py b/src/pages/evaluation_page.py index 288866c2..b6e70d73 100644 --- a/src/pages/evaluation_page.py +++ b/src/pages/evaluation_page.py @@ -1,16 +1,14 @@ import tkinter as tk from tkinter import ttk import threading -from datetime import datetime from pathlib import Path from utils.evaluation import Evaluator from components.evaluation_form import EvaluationForm -from components.evaluation_visualizer import EvaluationVisualizer class EvaluationPage: def __init__(self, root): self.root = root - self.visualizer = None + # Run method right below self.setup_page() def setup_page(self): @@ -31,40 +29,13 @@ def setup_page(self): ttk.Separator(content, orient="horizontal").grid(row=1, column=0, sticky="ew", padx=20) - # Initialize visualizer before form - self.visualizer = EvaluationVisualizer(content) - self.form = EvaluationForm(content, self.handle_start_evaluation) - def format_metrics(self, scores, use_geval=True): - metrics = ( - f"ROUGE-1: {scores.get('rouge1', 0):.4f}, " - f"ROUGE-2: {scores.get('rouge2', 0):.4f}, " - f"ROUGE-L: {scores.get('rougeL', 0):.4f}\n" - f"BLEU: {scores.get('bleu', 0):.4f}, " - f"METEOR: {scores.get('meteor', 0):.4f}, " - f"BERTScore F1: {scores.get('bert_f1', 0):.4f}" - ) - - if use_geval: - # Add the geval metrics to the traditional metrics - metrics += ( - f"\nG-Eval Metrics:\n" - f" Coherence: {scores.get('coherence', 0):.4f}\n" - f" Consistency: {scores.get('consistency', 0):.4f}\n" - f" Fluency: {scores.get('fluency', 0):.4f}\n" - f" Relevance: {scores.get('relevance', 0):.4f}" - ) - - return metrics - - def run_evaluation(self, dataset_path, model_path, start_idx, end_idx, use_geval=True): + def run_evaluation(self, dataset_path, model_path, start_idx, end_idx): try: - # Initialize evaluator with G-EVAL flag + # Initialize evaluator self.form.update_status("Loading model...") - evaluator = Evaluator(model_path, use_geval) - - self.form.evaluator = evaluator + evaluator = Evaluator(model_path) # Load dataset with specified range self.form.update_status(f"Loading dataset (indices {start_idx}-{end_idx})...") @@ -81,18 +52,16 @@ def progress_callback(progress_info): current = progress_info['current'] total = progress_info['total'] successful = progress_info['successful'] - scores = progress_info.get('scores', {}) + rouge1 = progress_info['rouge1'] - # Update status with current progress and metrics + # Update status with current progress status_text = ( + f"Evaluating samples {start_idx}-{end_idx}\n" f"Current sample: {start_idx + current}/{end_idx} " - f"(Processed {successful} successfully)" - f"\n{self.format_metrics(scores, use_geval)}\n" + f"(Processed {successful} successfully)\n" + f"Current ROUGE-1: {rouge1:.4f}\n" ) - # Update logs self.root.after(0, lambda: self.form.update_status(status_text)) - # Update graph - self.root.after(0, lambda: self.visualizer.update_plots(scores, use_geval)) # Run evaluation final_scores = evaluator.evaluate( @@ -103,47 +72,23 @@ def progress_callback(progress_info): # Update status with final scores final_status = ( f"\nEvaluation complete for samples {start_idx}-{end_idx}!\n" - f"Successfully processed {final_scores['processed_samples']} out of {final_scores['total_samples']} samples\n\n" - f"Final Metrics:\n{self.format_metrics(final_scores, use_geval)}\n" + f"Successfully processed {final_scores['processed_samples']} out of {final_scores['total_samples']} samples\n" + f"Final ROUGE-1: {final_scores['rouge1']:.4f}\n" ) - # Update log with final message self.root.after(0, lambda: self.form.update_status(final_status)) - - # Show final radar chart - self.root.after(0, lambda: self.visualizer.plot_final_radar(final_scores, use_geval)) - - # Create directory for saving results - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - model_name = Path(model_path).stem - log_dir = Path("../eval_files") / f"{timestamp}_{model_name}" - log_dir.mkdir(parents=True, exist_ok=True) - - # Save all evaluation data - evaluator.save_logs(log_dir, final_scores, final_scores['processed_samples'], final_scores['total_samples']) - self.root.after(0, lambda: self.visualizer.save_plots(log_dir)) - - # Reset start button self.root.after(0, lambda: self.form.start_btn.config(state="normal")) except Exception as e: - error_msg = f"Error: {str(e)}" - self.root.after(0, lambda: self.form.update_status(error_msg, is_error=True)) + # Handle any errors during evaluation + self.root.after(0, lambda: self.form.update_status(f"Error: {str(e)}", is_error=True)) self.root.after(0, lambda: self.form.start_btn.config(state="normal")) - def handle_start_evaluation(self, dataset_path, model_path, start_idx, end_idx, use_geval=True): - # Clear previous plots - self.visualizer.clear_plots() - - # Disable start button while evaluation is running - self.form.start_btn.config(state="disabled") - - # Clear previous status - self.form.update_status("") - + def handle_start_evaluation(self, dataset_path, model_path, start_idx, end_idx): # Start evaluation in a separate thread thread = threading.Thread( target=self.run_evaluation, - args=(dataset_path, model_path, start_idx, end_idx, use_geval), + # Passes parameters needed to run evaluation + args=(dataset_path, model_path, start_idx, end_idx), daemon=True ) - thread.start() \ No newline at end of file + thread.start() diff --git a/src/pages/home_page.py b/src/pages/home_page.py index 5a0df5b7..b37ce7c5 100644 --- a/src/pages/home_page.py +++ b/src/pages/home_page.py @@ -1,17 +1,143 @@ import tkinter as tk +from tkinter import * +import os +from tkinter import ttk +from pages.indiv_page import LLMPage +from components import ( + LLMInput, + TitleFrame, + LLMList +) class HomePage: - def __init__(self, root): + def __init__(self, root, show_page_callback): + self.home = None self.root = root + self.container = tk.Frame(self.root, bg="#D2E9FC") + self.container.grid(row=1, column=1, sticky="nsew") + self.llmlist = LLMList (self.container, self.root) + self.show_page_callback = show_page_callback self.setup_page() - + + def setup_page(self): - container = tk.Frame(self.root, bg="#D2E9FC") - container.grid(row=1, column=1, sticky="nsew") - # Placeholder content - tk.Label( - container, - text="Home", - font=("SF Pro Display", 24, "bold"), - bg="#D2E9FC" - ).pack(pady=20) + """Initialize and set up the homepage page """ + self._configure_root() + self._configure_grid() + self._setup_styles() + self._initialize_components() + self._setup_bindings() + + + def _configure_root(self): + """Configure root window settings""" + self.root.title("Assess.ai") + self.root.configure(bg="#D2E9FC") + + def _configure_grid(self): + """Configure grid layout""" + self.container.grid_rowconfigure(0, weight=0) # Title + self.container.grid_rowconfigure(1, weight=0) #homepage label + self.container.grid_rowconfigure(2, weight=0) #button + self.container.grid_rowconfigure(3, weight=0) #labels + self.container.grid_rowconfigure(4, weight=1) #list boxes + self.container.grid_columnconfigure(0, weight=1) + self.container.grid_columnconfigure(1, weight=1) + + def _setup_styles(self): + """Setup ttk styles""" + style = ttk.Style() + + + def _initialize_components(self): + + # welcome label + title_lbl = tk.Label(self.container, text="WELCOME TO ASSESS.AI", font=("SF Pro Display", 24, "bold"), bg="#D2E9FC", fg="black") + title_lbl.grid(row=0,column=0, columnspan=2,pady=10,sticky="n") + + # homepage label + homepage_lbl = tk.Label(self.container, text="Homepage", font=("SF Pro Display", 18, "bold"), bg="#D2E9FC", fg="black") + homepage_lbl.grid(row=1,column=0, columnspan=2,pady=5,sticky="n") + + # nav button + self.llm_button = ttk.Button(self.container, text="New? Get started with LLM page", command=self.nav_to_llm) + # the command is a placeholder for now + self.llm_button.grid(row=2, column=0, columnspan=2, pady=10, padx=20, sticky="ew") + + # Listbox for past llms used + llm_lbl=tk.Label(self.container, text="Past LLMs Used:", font=("SF Pro Display", 14), bg="#D2E9FC", fg="black") + llm_lbl.grid(row=3,column=0, padx=20, pady=(5, 0),sticky="w") + self.llm_lb = tk.Listbox(self.container, height=10) + self.llm_lb.grid(row=4,column=0, padx=20, pady=10, sticky="nsew") + + self.llm_lb.bind("", self.model_selected) # bind list + self.load_past_llms() #loading past llms CHANGE (changed) + + + # List box for past evals + eval_label = tk.Label(self.container, text="Past Evaluations:", font=("SF Pro Display", 14), bg="#D2E9FC", fg="black") + eval_label.grid(row=3,column=1, padx=20, pady=(5,0),sticky="w") + self.eval_lb = tk.Listbox(self.container, height=10) + self.eval_lb.grid(row=4, column=1, padx=20, pady=10, sticky="nsew") + # load eval results into lb + # placeholder content + self.load_evaluations() + + + def _setup_bindings(self): + self.root.bind('', lambda e: self.root.destroy()) + + def load_evaluations(self): + # cd to parent directory + cwd = os.getcwd() # current directory + parent = os.path.dirname(cwd) # parent directory + eval_folder = os.path.join(parent, "eval_files") + if not os.path.exists(eval_folder): + print(f"Error: {eval_folder} directory does not exist.") + return + try: + eval_dirs = [d for d in os.listdir(eval_folder) if os.path.isdir(os.path.join(eval_folder, d))] + # Insert directory names into the Listbox + for eval_dir in eval_dirs: + self.eval_lb.insert(tk.END, eval_dir) # Add the directory name to Listbox (this could also be filename if saved differently) + + except FileNotFoundError: + print(f"Error: {eval_folder} not found.") + + def nav_to_llm(self): + # change displaying page + print("navigating to llm page...") + self.show_page_callback("llms") + + def load_past_llms(self): + # load past llms in to the listbox + imported_models = self.llmlist.get_models() # get_models + + # write to listbox + self.llm_lb.delete(0, tk.END) # delete existing entries + count = 0 + for model in imported_models: + count += 1 + self.llm_lb.insert(count, model) + + def model_selected(self, event): + selection = self.llm_lb.curselection() + if selection: + self.selected_model = self.llm_lb.get(selection) + self.create_window(self.selected_model) + + def create_window(self, model_name): + # main window object + new_win = Toplevel(self.root) # create toplevel widget + + # set title + dimensions + new_win.title(model_name) + new_win.geometry("500x500") + + # populate window with model specific material + self.detail_page = LLMPage(new_win, self.selected_model) + + + + + diff --git a/src/pages/indiv_page.py b/src/pages/indiv_page.py index 3270425f..aa31bc9d 100644 --- a/src/pages/indiv_page.py +++ b/src/pages/indiv_page.py @@ -1,4 +1,6 @@ +import sys import tkinter as tk +import io from tkinter import ttk from components.llm_details import LLMDetails @@ -41,4 +43,4 @@ def _initialize_components(self): # Name + Details self.details_frame = LLMDetails(self.container, self.LLM) - self.details_frame.grid(row=0, column=0, sticky="ew", pady=(0,50)) \ No newline at end of file + self.details_frame.grid(row=0, column=0, sticky="ew", pady=(0,50)) diff --git a/src/pages/llms_page.py b/src/pages/llms_page.py index a6cf7d55..407b1fcf 100644 --- a/src/pages/llms_page.py +++ b/src/pages/llms_page.py @@ -84,5 +84,4 @@ def get_output(self, model_path): self.term_output = f"Error: {str(e)}" sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - return self.term_output \ No newline at end of file + return self.term_output diff --git a/src/pages/logo.png b/src/pages/logo.png new file mode 100644 index 00000000..89ec46bd Binary files /dev/null and b/src/pages/logo.png differ diff --git a/src/utils/data_loader.py b/src/utils/data_loader.py index 2d6d02f0..06b08aab 100644 --- a/src/utils/data_loader.py +++ b/src/utils/data_loader.py @@ -2,6 +2,7 @@ import json from pathlib import Path import csv + class TextDataset(Dataset): def __init__(self, data, tokenizer, max_length=256): self.data = data @@ -113,7 +114,6 @@ def load_dataset(data_path, start_idx=0, end_idx=100): # Validate data structure if not all(isinstance(item, dict) and 'input_text' in item and 'target_text' in item for item in data): raise ValueError("Data must contain 'input_text' and 'target_text' fields") - return data except Exception as e: diff --git a/src/utils/evaluation.py b/src/utils/evaluation.py index 08dd3edf..2b9d838c 100644 --- a/src/utils/evaluation.py +++ b/src/utils/evaluation.py @@ -227,4 +227,5 @@ def generate_summary(self, text): except Exception as e: print(f"Error generating summary: {str(e)}") - return "" \ No newline at end of file + return "" + diff --git a/src/utils/fine_tuning.py b/src/utils/fine_tuning.py index cba6b2fe..9a996b98 100644 --- a/src/utils/fine_tuning.py +++ b/src/utils/fine_tuning.py @@ -148,4 +148,4 @@ def fine_tune(self, train_data, progress_callback=None): except Exception as e: print(f"Training error: {str(e)}") - raise \ No newline at end of file + raise diff --git a/src/utils/llm.py b/src/utils/llm.py index 3c7f81ed..22fb2899 100644 --- a/src/utils/llm.py +++ b/src/utils/llm.py @@ -35,6 +35,7 @@ def import_LLM(self): self.tokenizer.save_pretrained("../model_files/" + path_name) print(self.model_id + " was successfully imported!") + def load_LLM(self): # check model type using AutoConfig # dict of model classes @@ -56,4 +57,4 @@ def load_LLM(self): # load model with correct configurations self.tokenizer = AutoTokenizer.from_pretrained(self.model_id) - self.model = self.model_class.from_pretrained(self.model_id) \ No newline at end of file + self.model = self.model_class.from_pretrained(self.model_id) diff --git a/src/utils/model_config.py b/src/utils/model_config.py index 846f0b63..e2a8a12a 100644 --- a/src/utils/model_config.py +++ b/src/utils/model_config.py @@ -1,7 +1,6 @@ import os from tkinter import messagebox, filedialog - # Define parameter limits for model fine-tuning param_limits = { "num_epochs": {"min": 1, "max": 20}, # Number of training epochs @@ -125,4 +124,4 @@ def browse_file(file_type, path_var): path_var.set(filename) - return filename \ No newline at end of file + return filename