diff --git a/api/models/teste b/api/models/teste
new file mode 100644
index 00000000..3ef55dc2
Binary files /dev/null and b/api/models/teste differ
diff --git a/src/App.css b/src/App.css
index 4e6b4487..e69de29b 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,4 +0,0 @@
-@import url("https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap");
-.font-roboto {
- font-family: "Roboto Mono", monospace;
-}
diff --git a/src/Shared/apexChartsOptions.ts b/src/Shared/apexChartsOptions.ts
index 8e4f6439..37eba799 100644
--- a/src/Shared/apexChartsOptions.ts
+++ b/src/Shared/apexChartsOptions.ts
@@ -10,13 +10,13 @@ export const ReactApexChartsDefaultOptions = {
xaxis: {
labels: {
style: {
- colors: "#ffffff",
+ colors: "#000",
},
},
title: {
text: "Epoch",
style: {
- color: "#ffffff",
+ color: "#000",
},
},
},
@@ -24,13 +24,13 @@ export const ReactApexChartsDefaultOptions = {
labels: {
formatter: (value: number) => value.toFixed(4),
style: {
- colors: "#ffffff",
+ colors: "#000",
},
},
title: {
text: "Loss",
style: {
- color: "#ffffff",
+ color: "#000",
},
},
},
@@ -38,18 +38,19 @@ export const ReactApexChartsDefaultOptions = {
theme: "dark",
},
grid: {
- borderColor: "#ffffff",
+ borderColor: "#777",
+ strokeDashArray: 1,
},
title: {
text: "Loss vs Epochs",
align: 'center' as 'center',
style: {
- color: "#ffffff",
+ color: "#000",
},
},
legend: {
labels: {
- colors: "#ffffff", // Muda a cor das legendas
+ colors: "#000", // Muda a cor das legendas
},
},
};
diff --git a/src/assets/images/tailLogo.svg b/src/assets/images/tailLogo.svg
new file mode 100644
index 00000000..7a4fafd4
--- /dev/null
+++ b/src/assets/images/tailLogo.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/csvTable/csvTable.tsx b/src/components/csvTable/csvTable.tsx
index 6c3bd5f8..6c6a855c 100644
--- a/src/components/csvTable/csvTable.tsx
+++ b/src/components/csvTable/csvTable.tsx
@@ -1,50 +1,37 @@
import React from "react";
-import './csvTable.css';
interface Props {
- head: any[];
+ head: string[];
data: any[][];
}
export default function CsvTable({ data, head }: Props) {
return (
-
-
-
-
- {head.map((headTitle, index) => {
- return (
-
- {headTitle}
-
- );
- })}
+
+
+
+
+ {head.map((headTitle, index) => (
+
+ {headTitle}
+
+ ))}
- {data.map((row, index) => {
- return (
-
- {row.map((cell, cellIndex) => {
- return (
-
+ {data.map((row, rowIndex) => (
+
+ {
+ row.map((cell, cellIndex) => (
+
+
{cell}
-
- );
- })}
-
- );
- })}
+
+
+ ))
+ }
+
+ ))}
diff --git a/src/components/menu/menu.tsx b/src/components/menu/menu.tsx
index e1007ee2..604a7421 100644
--- a/src/components/menu/menu.tsx
+++ b/src/components/menu/menu.tsx
@@ -1,20 +1,45 @@
import React, { useState } from "react";
-import { HiOutlineMenu, HiOutlineX } from "react-icons/hi"; // Importando ícones do React Icons
-import { Link } from "react-router-dom";
+import { HiOutlineMenu, HiOutlineX } from "react-icons/hi";
+import { Link, useLocation } from "react-router-dom";
import { CSSTransition } from "react-transition-group";
import "./menu.css";
export function Menu() {
const [isExpanded, setIsExpanded] = useState(false);
+ const location = useLocation();
const toggleMenu = () => {
setIsExpanded(!isExpanded);
};
+ const menuItems = [
+ {
+ path: "/",
+ title: "Classificar",
+ description: "Utilize modelos pré-treinados ou use os seus próprios modelos para classificar texto",
+ },
+ {
+ path: "/train",
+ title: "Treinar Classificador",
+ description: "Faça upload dos seus dados e treine o seu próprio classificador textual",
+ },
+ {
+ path: "/about",
+ title: "Sobre",
+ description: "Detalhes sobre o projeto",
+ },
+ {
+ path: "https://forms.gle/Snud46RwuwT16Mrb9",
+ title: "Feedback",
+ description: "Envie sua opinião",
+ external: true,
+ },
+ ];
+
return (
- <>
+
{isExpanded ? (
@@ -29,34 +54,43 @@ export function Menu() {
classNames="menu"
unmountOnExit
>
-
+
- >
+
);
}
diff --git a/src/components/resultTable/resultTable.tsx b/src/components/resultTable/resultTable.tsx
index e9f4a4fe..b54326a4 100644
--- a/src/components/resultTable/resultTable.tsx
+++ b/src/components/resultTable/resultTable.tsx
@@ -1,4 +1,10 @@
import React from "react";
+import CsvTable from "../csvTable/csvTable";
+
+interface TableData {
+ Coluna: string;
+ Valor: any;
+}
interface Props {
data: { [key: string]: any };
@@ -6,38 +12,12 @@ interface Props {
}
export default function ResultTable({ data, classifierName }: Props) {
- return (
-
-
-
-
- {"Index"}
- {"Input"}
+ const tableData: TableData[] = Object.entries(data).map(([key, value]) => ({
+ Coluna: key,
+ Valor: value,
+ }));
+
+ const convertedTableData: any[][] = tableData.slice(0, 4).map((item) => [item.Coluna, item.Valor]);
- {"Output"}
-
-
-
- {Object.keys(data)
- .slice(0, 10)
- .map((row: any, index: number) => {
- return (
-
- {index}
- {row}
-
- {data[row]}
-
-
- );
- })}
-
-
-
- );
+ return ;
}
diff --git a/src/components/selectFileCard/selectFileCard.tsx b/src/components/selectFileCard/selectFileCard.tsx
index e1b94c3c..fbd6468c 100644
--- a/src/components/selectFileCard/selectFileCard.tsx
+++ b/src/components/selectFileCard/selectFileCard.tsx
@@ -2,6 +2,7 @@ import { Icon } from "@iconify/react";
import { ChangeEvent, useState } from "react";
import Papa from "papaparse";
import CsvTable from "../csvTable/csvTable";
+import { Link } from "@mui/material";
interface props {
selectedFile: File | null;
@@ -52,7 +53,6 @@ export default function SelectFileCard({
}
};
- // Arrastar e soltar
const handleDrop = (event: React.DragEvent) => {
setIsDragging(false);
event.preventDefault();
@@ -66,69 +66,66 @@ export default function SelectFileCard({
};
const handleDragOver = (event: React.DragEvent) => {
- setIsDragging(true); // Quando o usuário arrasta algo para cima
+ setIsDragging(true);
event.preventDefault();
};
const handleDragLeave = () => {
- setIsDragging(false); // Quando o usuário cancela o arrasto
+ setIsDragging(false);
};
- return (
+ return !selectedFile ? (
0 ? `w-4/5` : `w-2/5`
- } relative mx-auto mt-24 bg-main-dark border-2 border-main-lighter text-white pt-4 px-4 placeholder-gray-300 rounded-3xl min-h-min flex flex-col items-center justify-between ${
- isDragging ? "blur-sm" : ""
- }`}
+ className={`${data.length > 0 ? `w-4/5` : `w-2/5`
+ } min-h-[170px] relative mx-auto mt-24 bg-gray-100 border-dashed border-2 border-gray-700 text-gray-600 px-4 placeholder-gray-300 rounded-md flex flex-col items-center justify-center gap-4 ${isDragging ? "blur-sm" : ""
+ }`}
onDrop={handleDrop}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
>
- {isDragging ? (
-
Arrastar e soltar
- ) : (
- <>
-
-
- {selectedFile ? ( // se tiver arquivo selecionado, seu nome é exibido
-
{selectedFile.name}
- ) : (
- <>
-
Arrastar e soltar
-
Ou
- >
- )}
-
- {data.length > 0 && (
-
- )}
-
-
{
- const fileInput = document.getElementById("fileInput");
- if (fileInput) {
- fileInput.click();
- }
- }}
- >
- Selecionar do Computador
-
-
- >
+
+
+
+
+
+
+ ) : (
+
+ 0 ? `w-4/5` : `w-2/5`
+ } min-h-[170px] relative mx-auto flex flex-col items-center justify-center ${isDragging ? "blur-sm" : ""
+ }`}
+ onDrop={handleDrop}
+ onDragOver={handleDragOver}
+ onDragLeave={handleDragLeave}
+ >
+
+
+ {data.length > 0 && (
+
)}
- );
+ )
}
diff --git a/src/index.css b/src/index.css
index ae228ce9..bf8caa94 100644
--- a/src/index.css
+++ b/src/index.css
@@ -2,12 +2,18 @@
@tailwind components;
@tailwind utilities;
+@layer base {
+ body {
+ font-family: Inter, sans-serif;
+ }
+
+ code,
+ pre {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+ }
+}
+
* {
margin: 0;
padding: 0;
}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
- monospace;
-}
diff --git a/src/pages/about.tsx b/src/pages/about.tsx
index 6f52b7fb..13bb5f42 100644
--- a/src/pages/about.tsx
+++ b/src/pages/about.tsx
@@ -1,144 +1,8 @@
-import { Menu } from "../components/menu/menu";
-import { FaLinkedin, FaGithub } from "react-icons/fa";
+import Layout from "./layout/layout";
+import AboutView from "./views/aboutView";
export default function About() {
- const teamMembers = [
- {
- name: "Jonas Gabriel",
- linkedin: "https://www.linkedin.com/in/jonas-gabriel-araujo/",
- github: "https://github.com/jonasgabriel18",
- photo: "../../../assets/jonas.jpg",
- },
- {
- name: "Luiz Gusttavo",
- linkedin:
- "https://www.linkedin.com/in/luiz-gusttavo-oliveira-de-souza-7538091b1/",
- github: "https://github.com/GusttavoOliveira",
- photo: "../../../assets/luiz.jpg",
- },
+ return ;
- {
- name: "Bertrand Lira",
- linkedin: "https://www.linkedin.com/in/bertrand-lira-veloso-52aa4926a/",
- github: "https://github.com/BertrandLira",
- photo: "../../../assets/bertrand.jpg",
- },
-
- {
- name: "Cameron Maloney",
- linkedin: "https://www.linkedin.com/in/cameronmal/",
- github: "https://github.com/cmaloney111",
- photo: "../../../assets/cameron.jpg",
- },
-
- {
- name: "Gisele Silva",
- linkedin: "https://www.linkedin.com/in/gisele-silva-6692941a4/",
- github: "https://github.com/GiseleBr678",
- photo: "../../../assets/LINDADEMAIS/gisele.jpg",
- },
-
- {
- name: "Thauã Magalhães",
- linkedin: "https://www.linkedin.com/in/thaua-lucas/",
- github: "https://github.com/tahaluh",
- photo: "../../../assets/thaua.jpg",
- },
-
- {
- name: "Thiago Rodrigues",
- linkedin: "https://www.linkedin.com/in/thiago-rodrigues-b8a328249/",
- github: "https://github.com/tahaluh",
- photo: "../../../assets/thiago.jpg",
- },
- ];
-
- return (
-
-
-
-
-
- LinguifAI
-
-
-
- O LinguifAI é uma aplicação inovadora desenvolvida pela diretoria de
- NLP da TAIL, projetada para simplificar e agilizar o treinamento e a
- classificação de modelos de Machine Learning em texto. Com essa
- ferramenta, é possível experimentar diversos algoritmos e ajustar
- parâmetros de forma intuitiva, tornando o processo de desenvolvimento
- de modelos NLP mais acessível e eficiente.
-
-
-
Tecnologias Utilizadas:
-
-
-
-
Conheça a Equipe:
-
-
- {teamMembers.map((member, index) => (
-
-
-
{member.name}
-
-
- ))}
-
-
-
- );
}
diff --git a/src/pages/home.tsx b/src/pages/home.tsx
index 0dcd7ff8..edcda349 100644
--- a/src/pages/home.tsx
+++ b/src/pages/home.tsx
@@ -1,207 +1,7 @@
-import { useState, useEffect } from "react";
-import SelectFileCard from "../components/selectFileCard/selectFileCard";
-import axios from "axios";
-import ResultTable from "../components/resultTable/resultTable";
-import { Menu } from "../components/menu/menu";
+import Layout from "./layout/layout";
+import HomeView from "./views/homeView";
-export default function Home() {
- const [selectedFile, setSelectedFile] = useState(null);
-
- const [data, setData] = useState([]);
- const [header, setHeader] = useState([]);
-
- const [selectedColumn, setSelectedColumn] = useState(0);
- const [selectedClassifier, setSelectedClassifier] = useState("");
-
- const [classifiers, setClassifiers] = useState<{ [key: string]: string }>({});
-
- const [result, setResult] = useState<{ [key: string]: any }>({});
-
- const [isLoading, setIsLoading] = useState(false);
-
- useEffect(() => {
- const fetchClassifiers = async () => {
- setTimeout(async () => {
- try {
- const response = await axios.get(
- "http://localhost:5000/get-classifiers"
- );
- setClassifiers(response.data);
- } catch (error) {
- try {
- const response = await axios.get(
- "http://localhost:5000/get-classifiers"
- );
- setClassifiers(response.data);
- } catch (error) {
- console.error("Error fetching classifiers:", error);
- }
- }
- }, 25000);
- };
-
- fetchClassifiers();
- }, []);
-
-
- const handleChangeSelectedColumn = (event: any) => {
- setSelectedColumn(event.target.value);
- };
-
- const handleChangeSelectedClassifier = (event: any) => {
- setSelectedClassifier(event.target.value);
- };
-
- const handleSubmit = async () => {
- setIsLoading(true);
- let selectedData = data.map((row) => row[selectedColumn]);
- const response = await axios
- .post("http://localhost:5000/classify", {
- data: selectedData,
- classifier: selectedClassifier,
- })
- .catch((error) => {
- console.error(error.response.data);
- });
-
- if (response && response.data) {
- const parsedData = JSON.parse(response.data.result);
-
- const input: any[] = Object.values(parsedData.input_column);
- const output: any[] = Object.values(parsedData.output_column).flat(1);
-
- if (input.length === output.length) {
- // cria um dicionário com os valores de input e output
- const result = input.reduce((acc, key, index) => {
- acc[key] = output[index];
- return acc;
- }, {} as { [key: string]: any });
- console.log(result);
- setResult(result);
- } else {
- console.error("Os arrays 'input' e 'output' tem tamanhos diferentes.");
- }
- }
-
- setIsLoading(false);
- };
-
- const handleDownloadOutputCSV = async () => {
- // adicionar uma coluna no data
-
- const finalHeader = header.concat(`${selectedClassifier}_output`);
- const finalData = data.map((row) =>
- row.concat(result[row[selectedColumn]])
- );
-
- // gera um csv com os dados
-
- const csv = finalHeader
- .join(",")
- .concat("\n")
- .concat(finalData.map((row) => row.join(",")).join("\n"));
-
- // cria um link para download do csv
-
- const csvFile = new Blob([csv], { type: "text/csv" });
- const csvURL = window.URL.createObjectURL(csvFile);
- const tempLink = document.createElement("a");
- tempLink.href = csvURL;
- tempLink.setAttribute("download", "output.csv");
- tempLink.click();
- };
-
- return (
-
-
-
-
-
- LinguifAI
-
-
- {
-
- }
-
- {selectedFile && (
- <>
-
-
-
- Selecione a coluna de entrada
-
- {header.length > 0 &&
- header.map((column: string, index: number) => {
- return {column} ;
- })}
-
-
-
-
-
- Selecione um classificador
-
- {Object.entries(classifiers).map(([value, label]) => (
-
- {label}
-
- ))}
-
-
-
-
- {isLoading ? "Carregando..." : "Classificar"}
-
-
- {Object.keys(result).length > 0 && (
-
- )}
- >
- )}
-
-
- );
+export default function Home() {
+ return ;
}
diff --git a/src/pages/layout/header.tsx b/src/pages/layout/header.tsx
new file mode 100644
index 00000000..d1a90c7a
--- /dev/null
+++ b/src/pages/layout/header.tsx
@@ -0,0 +1,23 @@
+import React from "react";
+import { Menu } from "../../components/menu/menu";
+import logo from "../../assets/images/tailLogo.svg";
+
+interface HeaderProps {
+ title: string;
+}
+
+const Header: React.FC = ({ title }) => {
+ return (
+
+
+
+
+
+ LinguifAI
+
+
+
+ );
+};
+
+export default Header;
diff --git a/src/pages/layout/layout.tsx b/src/pages/layout/layout.tsx
new file mode 100644
index 00000000..bb51eeb3
--- /dev/null
+++ b/src/pages/layout/layout.tsx
@@ -0,0 +1,17 @@
+import React, { ReactNode } from "react";
+import { Menu } from "../../components/menu/menu";
+import logo from "../../assets/images/tailLogo.svg";
+import Header from "./header";
+
+interface LayoutProps {
+ children: ReactNode;
+}
+
+export default function Layout({ children }: LayoutProps) {
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/pages/train.tsx b/src/pages/train.tsx
index ea3c67f9..c20d55bf 100644
--- a/src/pages/train.tsx
+++ b/src/pages/train.tsx
@@ -4,393 +4,12 @@ import axios from "axios";
import ResultTable from "../components/resultTable/resultTable";
import { Menu } from "../components/menu/menu";
import { ReactApexChartsDefaultOptions } from "../Shared/apexChartsOptions";
+import Layout from "./layout/layout";
+import TrainView from "./views/trainView";
export default function Train() {
- const [selectedFile, setSelectedFile] = useState(null);
-
- const [data, setData] = useState([]);
- const [header, setHeader] = useState([]);
-
- const [selectedColumn, setSelectedColumn] = useState(0);
- const [selectedLabel, setSelectedLabel] = useState(0);
-
- const [isLoading, setIsLoading] = useState(false);
- const [hasTrained, setHasTrained] = useState(false);
- const [isCancelling, setIsCancelling] = useState(false);
-
- const handleChangeSelectedColumn = (event: any) => {
- setSelectedColumn(event.target.value);
- };
-
- const handleChangeSelectedLabel = (event: any) => {
- setSelectedLabel(event.target.value);
- };
-
- const handleRnnSubmit = async () => {
- setIsLoading(true);
- setHasTrained(true);
- setLoadingProgress(0);
- setTrainLosses([]);
- setValidLosses([]);
-
- let selectedData = data.map((row) => ({
- value: row[selectedColumn],
- label: row[selectedLabel],
- }));
-
- let selectedLabels = data.map((row) => row[selectedLabel]);
- let selectedValues = data.map((row) => row[selectedColumn]);
-
- const sendData = {
- data: selectedValues,
- label: selectedLabels,
- batch_size: batchSize || 16,
- epochs: epochs || 50,
- learning_rate: learningRate || 0.001,
- name: modelName || "trained-model",
- };
-
- console.log(sendData);
-
- const url = "http://localhost:5000/neural-network-rnn";
-
- await axios.post(url, sendData).catch(async (error) => {
- await axios.post(url, sendData).catch(async (error) => {
- await axios.post(url, sendData).catch(async (error) => {
- await axios.post(url, sendData).catch((error) => {
- throw new Error(error);
- });
- });
- });
- });
-
- setIsLoading(false);
- };
-
- const handleNbSubmit = async () => {
- setIsLoading(true);
- setLoadingProgress(0);
-
- let selectedData = data.map((row) => ({
- value: row[selectedColumn],
- label: row[selectedLabel],
- }));
-
- let selectedLabels = data.map((row) => row[selectedLabel]);
- let selectedValues = data.map((row) => row[selectedColumn]);
-
- const sendData = {
- data: selectedValues,
- label: selectedLabels,
- batch_size: batchSize || 16,
- epochs: epochs || 50,
- learning_rate: learningRate || 0.001,
- name: modelName || "trained-model",
- };
-
- console.log(sendData);
-
- const url = "http://localhost:5000/neural-network-nb";
-
- await axios.post(url, sendData).catch(async (error) => {
- await axios.post(url, sendData).catch(async (error) => {
- await axios.post(url, sendData).catch(async (error) => {
- await axios.post(url, sendData).catch((error) => {
- throw new Error(error);
- });
- });
- });
- });
-
- setIsLoading(false);
- };
-
- const [batchSize, setBatchSize] = useState(16);
- const [epochs, setEpochs] = useState(50);
- const [learningRate, setLearningRate] = useState(0.001);
- const [modelName, setModelName] = useState("");
-
- const handleBatchSizeChange = (
- event: React.ChangeEvent
- ) => {
- const value = parseInt(event.target.value);
- setBatchSize(value);
- };
-
- const handleEpochsChange = (event: React.ChangeEvent) => {
- const value = parseInt(event.target.value);
- setEpochs(value);
- };
-
- const handleLearningRateChange = (
- event: React.ChangeEvent
- ) => {
- const value = parseFloat(event.target.value);
- setLearningRate(value);
- };
-
- const handleModelNameChange = (
- event: React.ChangeEvent
- ) => {
- const value = event.target.value;
- setModelName(value);
- };
-
- const [advancedOptionsVisible, setAdvancedOptionsVisible] = useState(false);
-
- const toggleAdvancedOptions = () => {
- setAdvancedOptionsVisible(!advancedOptionsVisible);
- };
-
- // carregamento
-
- const [loadingProgress, setLoadingProgress] = useState(0);
- const [train_losses, setTrainLosses] = useState([]);
- const [valid_losses, setValidLosses] = useState([]);
- const prevLoadingProgressRef = useRef(0); // Explicitly type prevLoadingProgressRef
-
- useEffect(() => {
- const fetchData = async () => {
- try {
- const response = await axios.get(
- "http://localhost:5000/training-status"
- );
- const { training_progress, training_in_progress } = response.data;
- const newProgress: number =
- training_in_progress || training_progress === 100
- ? training_progress
- : 0; // Explicitly type newProgress
- updateLoadingProgress(newProgress);
-
- setTrainLosses(train_losses);
- setValidLosses(valid_losses);
- } catch (error) {
- console.error("Error fetching progress:", error);
- }
- };
-
- const updateLoadingProgress = (newProgress: number) => {
- // Explicitly type newProgress parameter
- const duration = 1000; // Duration in milliseconds for the transition
- const startTime = Date.now();
- const startProgress = prevLoadingProgressRef.current;
-
- const updateProgress = () => {
- const elapsedTime = Date.now() - startTime;
- const progress = Math.min(1, elapsedTime / duration); // Ensure progress doesn't exceed 1
- const interpolatedProgress =
- startProgress + (newProgress - startProgress) * progress;
- setLoadingProgress(interpolatedProgress);
-
- if (progress < 1) {
- requestAnimationFrame(updateProgress);
- } else {
- prevLoadingProgressRef.current = newProgress;
- }
- };
-
- updateProgress();
- };
-
- const interval = setInterval(fetchData, 1050);
-
- return () => clearInterval(interval);
- }, []);
return (
-
-
-
-
-
- LinguifAI
-
-
- {
-
- }
-
- {selectedFile && (
- <>
-
-
- Nome do modelo
-
-
-
-
-
-
- Coluna de entrada
-
-
-
- Selecione a coluna de entrada
-
- {header.length > 0 &&
- header.map((column: string, index: number) => {
- return {column} ;
- })}
-
-
-
-
-
- Coluna de label
-
-
-
- Selecione a coluna de label
-
- {header.length > 0 &&
- header.map((column: string, index: number) => {
- return {column} ;
- })}
-
-
-
-
- {advancedOptionsVisible
- ? "Esconder Parâmetros Avançados"
- : "Exibir Parâmetros Avançados"}
-
-
- {advancedOptionsVisible && (
-
- )}
-
-
-
- {isLoading && (
-
-
-
-
- {`Treinamento em ${loadingProgress.toFixed(2)}%`}
-
-
- )}
-
-
- {isLoading ? "Carregando..." : "Treinar RNN"}
-
-
- {isLoading ? "Carregando..." : "Treinar NB"}
-
-
-
- >
- )}
-
-
+
);
}
diff --git a/src/pages/views/aboutView.tsx b/src/pages/views/aboutView.tsx
new file mode 100644
index 00000000..9c619475
--- /dev/null
+++ b/src/pages/views/aboutView.tsx
@@ -0,0 +1,128 @@
+import React from "react";
+import { Menu } from "../../components/menu/menu";
+import { FaGithub, FaLinkedin } from "react-icons/fa";
+
+export default function AboutView() {
+ const teamMembers = [
+ {
+ name: "Jonas Gabriel",
+ linkedin: "https://www.linkedin.com/in/jonas-gabriel-araujo/",
+ github: "https://github.com/jonasgabriel18",
+ photo: "../../../assets/jonas.jpg",
+ },
+ {
+ name: "Luiz Gusttavo",
+ linkedin: "https://www.linkedin.com/in/luiz-gusttavo-oliveira-de-souza-7538091b1/",
+ github: "https://github.com/GusttavoOliveira",
+ photo: "../../../assets/luiz.jpg",
+ },
+ {
+ name: "Bertrand Lira",
+ linkedin: "https://www.linkedin.com/in/bertrand-lira-veloso-52aa4926a/",
+ github: "https://github.com/BertrandLira",
+ photo: "../../../assets/bertrand.jpg",
+ },
+ {
+ name: "Cameron Maloney",
+ linkedin: "https://www.linkedin.com/in/cameronmal/",
+ github: "https://github.com/cmaloney111",
+ photo: "../../../assets/cameron.jpg",
+ },
+ {
+ name: "Gisele Silva",
+ linkedin: "https://www.linkedin.com/in/gisele-silva-6692941a4/",
+ github: "https://github.com/GiseleBr678",
+ photo: "../../../assets/LINDADEMAIS/gisele.jpg",
+ },
+ {
+ name: "Thauã Magalhães",
+ linkedin: "https://www.linkedin.com/in/thaua-lucas/",
+ github: "https://github.com/tahaluh",
+ photo: "../../../assets/thaua.jpg",
+ },
+ {
+ name: "Thiago Rodrigues",
+ linkedin: "https://www.linkedin.com/in/thiago-rodrigues-b8a328249/",
+ github: "https://github.com/tahaluh",
+ photo: "../../../assets/thiago.jpg",
+ },
+ ];
+
+ return (
+
+
+
+
+
+ O LinguifAI é uma aplicação inovadora desenvolvida pela diretoria de NLP da TAIL, projetada para simplificar e agilizar o treinamento e a classificação de modelos de Machine Learning em texto. Com essa ferramenta, é possível experimentar diversos algoritmos e ajustar parâmetros de forma intuitiva, tornando o processo de desenvolvimento de modelos NLP mais acessível e eficiente.
+
+
+
Tecnologias Utilizadas:
+
+
+
+
Conheça nossa equipe:
+
+
+ {teamMembers.map((member, index) => (
+
+
+
{member.name}
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/pages/views/homeView.tsx b/src/pages/views/homeView.tsx
new file mode 100644
index 00000000..f14fa2c6
--- /dev/null
+++ b/src/pages/views/homeView.tsx
@@ -0,0 +1,185 @@
+import React, { useState, useEffect } from "react";
+import axios from "axios";
+import SelectFileCard from "../../components/selectFileCard/selectFileCard";
+import ResultTable from "../../components/resultTable/resultTable";
+
+export default function HomeView() {
+ const [selectedFile, setSelectedFile] = useState(null);
+ const [data, setData] = useState([]);
+ const [header, setHeader] = useState([]);
+ const [selectedColumn, setSelectedColumn] = useState(0);
+ const [selectedClassifier, setSelectedClassifier] = useState("");
+ const [classifiers, setClassifiers] = useState<{ [key: string]: string }>({});
+ const [result, setResult] = useState<{ [key: string]: any }>({});
+ const [isLoading, setIsLoading] = useState(false);
+
+ useEffect(() => {
+ const fetchClassifiers = async () => {
+ while (true) {
+ try {
+ const response = await axios.get(
+ "http://localhost:5000/get-classifiers"
+ );
+ setClassifiers(response.data);
+ break;
+ } catch (error) {
+ console.error("Error fetching classifiers, retrying...", error);
+ await new Promise((resolve) => setTimeout(resolve, 3000));
+ }
+ }
+ };
+
+ fetchClassifiers();
+ }, []);
+
+ const handleChangeSelectedColumn = (event: React.ChangeEvent) => {
+ setSelectedColumn(Number(event.target.value));
+ };
+
+ const handleChangeSelectedClassifier = (event: React.ChangeEvent) => {
+ setSelectedClassifier(event.target.value);
+ };
+
+ const handleSubmit = async () => {
+ setIsLoading(true);
+ let selectedData = data.map((row) => row[selectedColumn]);
+ const response = await axios
+ .post("http://localhost:5000/classify", {
+ data: selectedData,
+ classifier: selectedClassifier,
+ })
+ .catch((error) => {
+ console.error(error.response.data);
+ });
+
+ if (response && response.data) {
+ const parsedData = JSON.parse(response.data.result);
+ const input: any[] = Object.values(parsedData.input_column);
+ const output: any[] = Object.values(parsedData.output_column).flat(1);
+
+ if (input.length === output.length) {
+ const result = input.reduce((acc, key, index) => {
+ acc[key] = output[index];
+ return acc;
+ }, {} as { [key: string]: any });
+
+ console.log(result);
+ setResult(result);
+ } else {
+ console.error("Os arrays 'input' e 'output' tem tamanhos diferentes.");
+ }
+ }
+
+ setIsLoading(false);
+ };
+
+ const handleDownloadOutputCSV = async () => {
+ const finalHeader = header.concat(`${selectedClassifier}_output`);
+ const finalData = data.map((row) =>
+ row.concat(result[row[selectedColumn]])
+ );
+
+ const csv = finalHeader
+ .join(",")
+ .concat("\n")
+ .concat(finalData.map((row) => row.join(",")).join("\n"));
+
+ const csvFile = new Blob([csv], { type: "text/csv" });
+ const csvURL = window.URL.createObjectURL(csvFile);
+ const tempLink = document.createElement("a");
+ tempLink.href = csvURL;
+ tempLink.setAttribute("download", "output.csv");
+ tempLink.click();
+ };
+
+ return (
+
+
+
+ {selectedFile && (
+ <>
+
+
+ Coluna de Entrada
+
+
+
+ Selecione a coluna de entrada
+
+ {header.length > 0 &&
+ header.map((column: string, index: number) => {
+ return {column} ;
+ })}
+
+
+
+
+ Selecione um Classificador
+
+
+
+ Selecione um classificador
+
+ {Object.entries(classifiers).map(([value, label]) => (
+
+ {label}
+
+ ))}
+
+
+
+
+ {isLoading ? "Carregando..." : "Classificar"}
+
+
+ {Object.keys(result).length > 0 && (
+
+ )}
+ >
+ )}
+
+ );
+}
diff --git a/src/pages/views/trainView.tsx b/src/pages/views/trainView.tsx
new file mode 100644
index 00000000..5836b8a2
--- /dev/null
+++ b/src/pages/views/trainView.tsx
@@ -0,0 +1,374 @@
+import React, { useState, useEffect, useRef } from "react";
+import axios from "axios";
+import ReactApexChart from "react-apexcharts";
+import SelectFileCard from "../../components/selectFileCard/selectFileCard";
+import { ReactApexChartsDefaultOptions } from "../../Shared/apexChartsOptions";
+
+export default function TrainView() {
+ const [selectedFile, setSelectedFile] = useState(null);
+
+ const [data, setData] = useState([]);
+ const [header, setHeader] = useState([]);
+
+ const [selectedColumn, setSelectedColumn] = useState(0);
+ const [selectedLabel, setSelectedLabel] = useState(0);
+
+ const [isLoading, setIsLoading] = useState(false);
+ const [hasTrained, setHasTrained] = useState(false);
+ const [isCancelling, setIsCancelling] = useState(false);
+
+ const handleChangeSelectedColumn = (event: React.ChangeEvent) => {
+ setSelectedColumn(Number(event.target.value));
+ };
+
+ const handleChangeSelectedLabel = (event: React.ChangeEvent) => {
+ setSelectedLabel(Number(event.target.value));
+ };
+
+ const handleCancelTraining = async () => {
+ setIsCancelling(true);
+ try {
+ await axios.post('http://localhost:5000/cancel-training');
+ alert('Treinamento cancelado com sucesso!');
+ } catch (error) {
+ console.error('Erro ao cancelar o treinamento:', error);
+ alert('Falha ao cancelar o treinamento.');
+ }
+ setIsCancelling(false);
+ };
+
+ const handleRnnSubmit = async () => {
+ setIsLoading(true);
+ setHasTrained(true);
+ setLoadingProgress(0);
+ setTrainLosses([]);
+ setValidLosses([]);
+
+ let selectedData = data.map((row) => ({
+ value: row[selectedColumn],
+ label: row[selectedLabel],
+ }));
+
+ let selectedLabels = data.map((row) => row[selectedLabel]);
+ let selectedValues = data.map((row) => row[selectedColumn]);
+
+ const sendData = {
+ data: selectedValues,
+ label: selectedLabels,
+ batch_size: batchSize || 16,
+ epochs: epochs || 50,
+ learning_rate: learningRate || 0.001,
+ name: modelName || "trained-model",
+ };
+
+ console.log(sendData);
+
+ const url = "http://localhost:5000/neural-network-rnn";
+
+ await axios.post(url, sendData).catch(async (error) => {
+ await axios.post(url, sendData).catch(async (error) => {
+ await axios.post(url, sendData).catch(async (error) => {
+ await axios.post(url, sendData).catch((error) => {
+ throw new Error(error);
+ });
+ });
+ });
+ });
+
+ setIsLoading(false);
+ };
+
+ const handleNbSubmit = async () => {
+ setIsLoading(true);
+ setLoadingProgress(0);
+
+ let selectedData = data.map((row) => ({
+ value: row[selectedColumn],
+ label: row[selectedLabel],
+ }));
+
+ let selectedLabels = data.map((row) => row[selectedLabel]);
+ let selectedValues = data.map((row) => row[selectedColumn]);
+
+ const sendData = {
+ data: selectedValues,
+ label: selectedLabels,
+ batch_size: batchSize || 16,
+ epochs: epochs || 50,
+ learning_rate: learningRate || 0.001,
+ name: modelName || "trained-model",
+ };
+
+ console.log(sendData);
+
+ const url = "http://localhost:5000/neural-network-nb";
+
+ await axios.post(url, sendData).catch(async (error) => {
+ await axios.post(url, sendData).catch(async (error) => {
+ await axios.post(url, sendData).catch(async (error) => {
+ await axios.post(url, sendData).catch((error) => {
+ throw new Error(error);
+ });
+ });
+ });
+ });
+
+ setIsLoading(false);
+ };
+
+ const [batchSize, setBatchSize] = useState(16);
+ const [epochs, setEpochs] = useState(50);
+ const [learningRate, setLearningRate] = useState(0.001);
+ const [modelName, setModelName] = useState("");
+
+ const handleBatchSizeChange = (
+ event: React.ChangeEvent
+ ) => {
+ const value = parseInt(event.target.value);
+ setBatchSize(value);
+ };
+
+ const handleEpochsChange = (event: React.ChangeEvent) => {
+ const value = parseInt(event.target.value);
+ setEpochs(value);
+ };
+
+ const handleLearningRateChange = (
+ event: React.ChangeEvent
+ ) => {
+ const value = parseFloat(event.target.value);
+ setLearningRate(value);
+ };
+
+ const handleModelNameChange = (
+ event: React.ChangeEvent
+ ) => {
+ const value = event.target.value;
+ setModelName(value);
+ };
+
+ const [advancedOptionsVisible, setAdvancedOptionsVisible] = useState(false);
+
+ const toggleAdvancedOptions = () => {
+ setAdvancedOptionsVisible(!advancedOptionsVisible);
+ };
+
+ const [loadingProgress, setLoadingProgress] = useState(0);
+ const [train_losses, setTrainLosses] = useState([]);
+ const [valid_losses, setValidLosses] = useState([]);
+ const prevLoadingProgressRef = useRef(0);
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ const response = await axios.get(
+ "http://localhost:5000/training-status"
+ );
+ const { training_progress, training_in_progress, train_losses, valid_losses } = response.data;
+ const newProgress: number =
+ training_in_progress || training_progress === 100
+ ? training_progress
+ : 0; // Explicitly type newProgress
+ updateLoadingProgress(newProgress);
+
+ setTrainLosses(train_losses);
+ setValidLosses(valid_losses);
+ } catch (error) {
+ console.error("Error fetching progress:", error);
+ }
+ };
+
+ const updateLoadingProgress = (newProgress: number) => {
+ // Explicitly type newProgress parameter
+ const duration = 1000;
+ const startTime = Date.now();
+ const startProgress = prevLoadingProgressRef.current;
+
+ const updateProgress = () => {
+ const elapsedTime = Date.now() - startTime;
+ const progress = Math.min(1, elapsedTime / duration);
+ const interpolatedProgress =
+ startProgress + (newProgress - startProgress) * progress;
+ setLoadingProgress(interpolatedProgress);
+
+ if (progress < 1) {
+ requestAnimationFrame(updateProgress);
+ } else {
+ prevLoadingProgressRef.current = newProgress;
+ }
+ };
+
+ updateProgress();
+ };
+
+ const interval = setInterval(fetchData, 1050);
+
+ return () => clearInterval(interval);
+ }, []);
+
+ return (
+
+
+
+ {selectedFile && (
+ <>
+
+
+ Nome do modelo
+
+
+
+
+
+
+ Coluna de entrada
+
+
+
+ Selecione a coluna de entrada
+
+ {header.length > 0 &&
+ header.map((column: string, index: number) => (
+ {column}
+ ))}
+
+
+
+
+
+ Coluna de label
+
+
+
+ Selecione a coluna de label
+
+ {header.length > 0 &&
+ header.map((column: string, index: number) => (
+ {column}
+ ))}
+
+
+
+
+
+
+
+
+
+ {isLoading && (
+
+
+
+
+ {`Treinamento em ${loadingProgress.toFixed(2)}%`}
+
+
+ )}
+
+ {!isLoading &&
+ {isLoading ? "Carregando..." : "Treinar"}
+ }
+
+ {hasTrained && train_losses.length > 0 && (
+
+
+
+ )}
+
+ {isLoading && (
+
+ {isCancelling ? 'Cancelando...' : 'Cancelar Treinamento'}
+
+ )}
+
+
+ >
+ )}
+
+ );
+}
+