This commit is contained in:
Saifeddine ALOUI 2023-07-24 14:12:57 +02:00
parent 1ef387408c
commit 9075ab2036
7 changed files with 272 additions and 268 deletions

File diff suppressed because one or more lines are too long

8
web/dist/assets/index-8620bb03.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
web/dist/index.html vendored
View File

@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI - Welcome</title>
<script type="module" crossorigin src="/assets/index-af6d039d.js"></script>
<link rel="stylesheet" href="/assets/index-38afbb3f.css">
<script type="module" crossorigin src="/assets/index-b03ce880.js"></script>
<link rel="stylesheet" href="/assets/index-8620bb03.css">
</head>
<body>
<div id="app"></div>

View File

@ -1,60 +1,125 @@
<template>
<div :class="cardClass">
<!-- Title -->
<div v-if="title" class="font-bold mb-2">{{ title }}</div>
<!-- Child cards -->
<div :class="containerClass">
<slot></slot>
</div>
<div v-if="isActive" class="overlay" @click="toggleCard"></div>
<div
:class="[
'bg-white rounded-lg shadow-lg p-6',
cardWidthClass,
'm-2',
{ hovered: !disableHoverAnimation && isHovered, active: isActive }
]"
@mouseenter="isHovered = true"
@mouseleave="isHovered = false"
@click.self="toggleCard"
:style="{ cursor:!this.disableFocus ? 'pointer' : ''}"
>
<!-- Title -->
<div v-if="title" class="font-bold mb-2">{{ title }}</div>
<div v-if="isHorizontal" class="flex flex-wrap">
<!-- Card Content -->
<slot></slot>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: "",
},
isHorizontal: {
type: Boolean,
default: false,
},
<div v-else class="mb-2">
<!-- Card Content -->
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: "",
},
computed: {
cardClass() {
return [
"bg-gray-50",
"border",
"border-gray-300",
"text-gray-900",
"text-sm",
"rounded-lg",
"focus:ring-blue-500",
"focus:border-blue-500",
"block",
"w-full",
"p-2.5",
"dark:bg-gray-700",
"dark:border-gray-600",
"dark:placeholder-gray-400",
"dark:text-white",
"dark:focus:ring-blue-500",
"dark:focus:border-blue-500",
];
},
containerClass() {
return {
flex: this.isHorizontal,
"flex-col": !this.isHorizontal,
};
},
isHorizontal: {
type: Boolean,
default: false,
},
};
</script>
<style>
/* Optional: You can add more custom styling here if needed */
</style>
cardWidth: {
type: String,
default: "w-3/4",
},
disableHoverAnimation: {
type: Boolean,
default: false,
},
disableFocus: {
type: Boolean,
default: false,
},
},
data() {
return {
isHovered: false,
isActive: false,
};
},
computed: {
cardClass() {
return [
"bg-gray-50",
"border",
"border-gray-300",
"text-gray-900",
"text-sm",
"rounded-lg",
"focus:ring-blue-500",
"focus:border-blue-500",
"w-full",
"p-2.5",
"dark:bg-gray-700",
"dark:border-gray-600",
"dark:placeholder-gray-400",
"dark:text-white",
"dark:focus:ring-blue-500",
"dark:focus:border-blue-500",
{
"cursor-pointer": !this.isActive && !this.disableFocus,
"w-auto": !this.isActive,
},
];
},
cardWidthClass() {
return this.isActive ? this.cardWidth : "";
},
},
methods: {
toggleCard() {
if(!this.disableFocus){
this.isActive = !this.isActive;
}
},
},
};
</script>
<style>
/* Add the animation for the hover effect */
.hovered {
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
transform: scale(1.1); /* You can adjust the scale value as per your preference */
}
/* Add the styles for centering the card when it's active */
.active {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6); /* You can adjust the opacity as per your preference */
/* Make sure the overlay is above other elements */
pointer-events: all; /* Allow interactions with the overlay itself */
}
</style>

View File

@ -1,112 +1,38 @@
<template>
<div class="container overflow-y-scroll flex flex-col no-scrollbar shadow-lg p-10 pt-2 bg-bg-light-tone dark:bg-bg-dark-tone">
<form @submit.prevent="submitForm" class="max-w-md mx-auto">
<!-- Model/Tokenizer -->
<div class="mb-4">
<label for="model_name" class="text-sm">Model Name:</label>
<input
type="text"
id="model_name"
v-model="model_name"
required
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
>
</div>
<div class="mb-4">
<label for="tokenizer_name" class="text-sm">Tokenizer Name:</label>
<input
type="text"
id="tokenizer_name"
v-model="tokenizer_name"
required
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
>
</div>
<!-- Dataset -->
<div class="mb-4">
<label for="dataset_path" class="text-sm">Dataset:</label>
<input
type="file"
id="dataset_path"
ref="dataset_path"
accept=".parquet"
v-on:change="selectDatasetPath"
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
>
<p class="mt-2 text-xs">Selected File: {{ selectedDatasetPath }}</p>
</div>
<div class="mb-4">
<label for="max_length" class="text-sm">Max Length:</label>
<input
type="number"
id="max_length"
v-model.number="max_length"
required
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
>
</div>
<div class="mb-4">
<label for="batch_size" class="text-sm">Batch Size:</label>
<input
type="number"
id="batch_size"
v-model.number="batch_size"
required
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
>
</div>
<!-- Train Dynamics -->
<div class="mb-4">
<label for="lr" class="text-sm">Learning Rate:</label>
<input
type="number"
id="lr"
v-model.number="lr"
required
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
>
</div>
<div class="mb-4">
<label for="num_epochs" class="text-sm">Number of Epochs:</label>
<input
type="number"
id="num_epochs"
v-model.number="num_epochs"
required
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
>
</div>
<!-- Logging -->
<div class="mb-4">
<label for="output_dir" class="text-sm">Output Directory:</label>
<input
type="text"
id="output_dir"
v-model="selectedFolder"
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded"
placeholder="Enter or select the output folder"
>
<input
type="file"
id="folder_selector"
ref="folder_selector"
style="display: none"
webkitdirectory
v-on:change="selectOutputDirectory"
>
<button type="button" @click="openFolderSelector" class="bg-blue-500 text-white px-4 py-2 rounded">Select Folder</button>
</div>
<button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded">Train LLM</button>
<Card title="Quantizing configuration" :isHorizontal="true" :disableHoverAnimation="true" :disableFocus="true">
<Card title="Model" class="" :isHorizontal="false">
<!-- Model/Tokenizer -->
<div class="mb-4">
<label for="model_name" class="text-sm">Model Name:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="model_name" />
</div>
<div class="mb-4">
<label for="tokenizer_name" class="text-sm">Tokenizer Name:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="tokenizer_name" />
</div>
</Card>
</Card>
<Card :disableHoverAnimation="true" :disableFocus="true">
<button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded">Quantize LLM</button>
<ProgressBar v-if="loading" :progress="progressValue" />
</Card>
</form>
</div>
</template>
<script>
import ClipBoardTextInput from "@/components/ClipBoardTextInput.vue";
import Card from "@/components/Card.vue"
import ProgressBar from '@/components/ProgressBar.vue';
export default {
components: {
ClipBoardTextInput,
Card,
ProgressBar
},
data() {
return {
model_name: 'jondurbin/airoboros-7b-gpt4',

View File

@ -1,58 +1,71 @@
<template>
<div class="container overflow-y-scroll flex flex-col no-scrollbar shadow-lg p-10 pt-2 bg-bg-light-tone dark:bg-bg-dark-tone">
<form @submit.prevent="submitForm" class="max-w-md mx-auto">
<!-- Model/Tokenizer -->
<div class="mb-4">
<label for="model_name" class="text-sm">Model Name:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="model_name" />
</div>
<div class="mb-4">
<label for="tokenizer_name" class="text-sm">Tokenizer Name:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="tokenizer_name" />
</div>
<form @submit.prevent="submitForm" class="">
<Card title="Training configuration" :isHorizontal="true" :disableHoverAnimation="true" :disableFocus="true">
<Card title="Model" class="" :isHorizontal="false">
<!-- Model/Tokenizer -->
<div class="mb-4">
<label for="model_name" class="text-sm">Model Name:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="model_name" />
</div>
<div class="mb-4">
<label for="tokenizer_name" class="text-sm">Tokenizer Name:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="tokenizer_name" />
</div>
</Card>
<Card title="Data" :isHorizontal="false">
<!-- Dataset -->
<div class="mb-4">
<label for="dataset_path" class="text-sm">Dataset:</label>
<ClipBoardTextInput id="model_path" inputType="file" :value="dataset_path" onchange="selectDataset()"/>
</div>
</Card>
<Card title="Training" :isHorizontal="false">
<!-- Train Dynamics -->
<div class="mb-4">
<label for="lr" class="text-sm">Learning Rate:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="lr"/>
</div>
<div class="mb-4">
<label for="num_epochs" class="text-sm">Number of Epochs:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="num_epochs"/>
</div>
<div class="mb-4">
<label for="max_length" class="text-sm">Max Length:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="max_length"/>
</div>
<div class="mb-4">
<label for="batch_size" class="text-sm">Batch Size:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="batch_size"/>
</div>
</Card>
<Card title="Output" :isHorizontal="false">
<!-- Logging -->
<div class="mb-4">
<label for="output_dir" class="text-sm">Output Directory:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="output_dir" />
</div>
</Card>
</Card>
<Card :disableHoverAnimation="true" :disableFocus="true">
<button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded">Train LLM</button>
<ProgressBar v-if="loading" :progress="progressValue" />
</Card>
<!-- Dataset -->
<div class="mb-4">
<label for="dataset_path" class="text-sm">Dataset:</label>
<ClipBoardTextInput id="model_path" inputType="file" :value="dataset_path"/>
</div>
<div class="mb-4">
<label for="max_length" class="text-sm">Max Length:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="max_length"/>
</div>
<div class="mb-4">
<label for="batch_size" class="text-sm">Batch Size:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="batch_size"/>
</div>
<!-- Train Dynamics -->
<div class="mb-4">
<label for="lr" class="text-sm">Learning Rate:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="lr"/>
</div>
<div class="mb-4">
<label for="num_epochs" class="text-sm">Number of Epochs:</label>
<ClipBoardTextInput id="model_path" inputType="integer" :value="num_epochs"/>
</div>
<!-- Logging -->
<div class="mb-4">
<label for="output_dir" class="text-sm">Output Directory:</label>
<ClipBoardTextInput id="model_path" inputType="text" :value="output_dir" />
</div>
<button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded">Train LLM</button>
</form>
</div>
</template>
<script>
import ClipBoardTextInput from "@/components/ClipBoardTextInput.vue";
import Card from "@/components/Card.vue"
import ProgressBar from '@/components/ProgressBar.vue';
import axios from "axios";
export default {
components: {
ClipBoardTextInput,
Card,
ProgressBar
},
data() {
return {
@ -64,7 +77,7 @@
lr: 5.0e-5,
num_epochs: 2,
selectedFolder: '',
selectedDatasetPath: '',
selectedDataset: '',
};
},
methods: {
@ -72,16 +85,16 @@
const formData = {
model_name: this.model_name,
tokenizer_name: this.tokenizer_name,
dataset_path: this.selectedDatasetPath,
dataset_file: this.selectedDataset,
max_length: this.max_length,
batch_size: this.batch_size,
lr: this.lr,
num_epochs: this.num_epochs,
output_dir: this.selectedFolder,
};
// Send the form data to the backend
// ...
axios.post("/start_training", formData).then((res)=>{
});
},
openFolderSelector() {
this.$refs.folder_selector.click();
@ -94,10 +107,10 @@
this.selectedFolder = folderPath;
}
},
selectDatasetPath(event) {
selectDataset(event) {
const files = event.target.files;
if (files.length > 0) {
this.selectedDatasetPath = files[0].webkitRelativePath;
this.selectedDataset = files[0];
}
},
},