[], 'bad' => [], 'ignored' => []]; private $master; private $trainer; public function __construct(array $strings, MessageClassifier $master, ModelTrainer $trainer) { $this->io = new SymfonyStyle(new ArgvInput(), new ConsoleOutput()); $this->master = $master; $this->trainer = $trainer; $this->loadExistingData(); $cleaned = array_unique(array_map(function ($v) { return preg_replace('/\s+/', ' ', trim(mb_strtolower($v))); }, $strings)); $alreadyDone = array_merge($this->results['good'], $this->results['bad'], $this->results['ignored']); $this->strings = array_diff($cleaned, $alreadyDone); if (!is_dir(self::OUTPUT_DIR)) { mkdir(self::OUTPUT_DIR, 0777, true); } } private function loadExistingData(): void { $files = ['good' => self::GOOD_FILE, 'bad' => self::BAD_FILE, 'ignored' => self::IGNORE_FILE]; foreach ($files as $key => $path) { if (file_exists($path)) { $this->results[$key] = include $path; } } } public function runQuestions(): void { $count = count($this->strings); if ($count === 0) { $this->io->success("Toutes les chaînes sont déjà traitées."); $this->askForTraining(); return; } $this->io->title('Test & Labellisation Assistée par Machine'); foreach ($this->strings as $string) { // L'algorithme fait une suggestion $prediction = $this->master->classify($string); $this->io->section("Message à analyser"); $this->io->text($string); $this->io->note(sprintf( "Suggestion : %s (via %s) - Confiance : %d%% - Détails : %s", $prediction->decision->getValue(), $prediction->method, $prediction->confidence * 100, implode(', ', array_map(function (object $d) { return $d->word . " (" . round($d->score * 100, 2) . "%)"; }, $prediction->getDetails())) )); $answer = $this->io->choice('Valider cette classification ?', [ 'y' => 'Oui (Alerte)', 'n' => 'Non (Info)', 'i' => 'Ignorer', 'q' => 'Sauvegarder et Quitter' ], $prediction->decision->equals(MessageType::ALERTE()) ? 'y' : 'n'); if ($answer === 'q') { break; } if ($answer === 'y') { $this->results['good'][] = $string; } elseif ($answer === 'i') { $this->results['ignored'][] = $string; } else { $this->results['bad'][] = $string; } } $this->saveResults(); $this->askForTraining(); } private function askForTraining(): void { if ($this->io->confirm("Voulez-vous lancer l'apprentissage immédiat du modèle avec ces données ?", true)) { $this->io->comment("Entraînement en cours..."); $this->trainer->trainFromData([ 'ALERTE' => $this->results['good'], 'INFO' => $this->results['bad'] ]); $this->io->success("Modèle mis à jour et sauvegardé !"); } } private function saveResults(): void { foreach (['good' => self::GOOD_FILE, 'bad' => self::BAD_FILE, 'ignored' => self::IGNORE_FILE] as $key => $path) { sort($this->results[$key]); file_put_contents($path, "results[$key], true) . ";\n"); } } }