├── intro.gif ├── philosophix-logo.png ├── .gitignore ├── autres ├── presentation_01.gif ├── presentation_02.gif ├── presentation_03.gif ├── presentation_04.gif └── presentation_05.gif ├── csharp-cli ├── obj │ ├── Debug │ │ └── net9.0 │ │ │ ├── csharp-cli.AssemblyInfoInputs.cache │ │ │ ├── csharp-cli.genruntimeconfig.cache │ │ │ ├── apphost.exe │ │ │ ├── csharp-cli.csproj.CoreCompileInputs.cache │ │ │ ├── csharp-cli.dll │ │ │ ├── csharp-cli.pdb │ │ │ ├── ref │ │ │ └── csharp-cli.dll │ │ │ ├── refint │ │ │ └── csharp-cli.dll │ │ │ ├── csharp-cli.assets.cache │ │ │ ├── csharp-cli.sourcelink.json │ │ │ ├── .NETCoreApp,Version=v9.0.AssemblyAttributes.cs │ │ │ ├── csharp-cli.GlobalUsings.g.cs │ │ │ ├── csharp-cli.GeneratedMSBuildEditorConfig.editorconfig │ │ │ ├── csharp-cli.AssemblyInfo.cs │ │ │ └── csharp-cli.csproj.FileListAbsolute.txt │ ├── csharp-cli.csproj.nuget.g.targets │ ├── project.nuget.cache │ ├── csharp-cli.csproj.nuget.g.props │ ├── project.assets.json │ └── csharp-cli.csproj.nuget.dgspec.json ├── bin │ └── Debug │ │ └── net9.0 │ │ ├── csharp-cli.dll │ │ ├── csharp-cli.exe │ │ ├── csharp-cli.pdb │ │ ├── csharp-cli.runtimeconfig.json │ │ ├── csharp-cli.deps.json │ │ └── devoirs.json ├── start.bat ├── .gitignore ├── csharp-cli.csproj ├── appsettings.example.json ├── ILLMService.cs ├── Devoir.cs ├── JsonDatabaseService.cs ├── Correction.cs ├── INSTALLATION.md ├── CHANGELOG.md ├── OLLAMA_SETUP.md ├── CostCalculator.cs ├── LLMServiceFactory.cs ├── OllamaService.cs ├── OpenAiService.cs └── README.md ├── src ├── config.php ├── get-devoir.php ├── traitement-devoir.php ├── openai.php ├── sauvegarder-correction.php ├── api-annotations.php ├── exam.sql ├── index.php ├── voir-devoirs.php ├── ameliorations.php ├── creer-devoir.php └── corriger-copie.php ├── Philosophix.sln └── README.md /intro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/intro.gif -------------------------------------------------------------------------------- /philosophix-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/philosophix-logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | csharp-cli/appsettings.json 2 | csharp-cli/appsettings.json 3 | csharp-cli/appsettings.json 4 | -------------------------------------------------------------------------------- /autres/presentation_01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/autres/presentation_01.gif -------------------------------------------------------------------------------- /autres/presentation_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/autres/presentation_02.gif -------------------------------------------------------------------------------- /autres/presentation_03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/autres/presentation_03.gif -------------------------------------------------------------------------------- /autres/presentation_04.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/autres/presentation_04.gif -------------------------------------------------------------------------------- /autres/presentation_05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/autres/presentation_05.gif -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.AssemblyInfoInputs.cache: -------------------------------------------------------------------------------- 1 | 6ef859364364614088c791eb4e759ff29f797c27761af853130103ee6f81a90b 2 | -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.genruntimeconfig.cache: -------------------------------------------------------------------------------- 1 | b3f3b2a7bfdcfa918360b58bda6892c32e842b0174be06cf232565959e110014 2 | -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/apphost.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/obj/Debug/net9.0/apphost.exe -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.csproj.CoreCompileInputs.cache: -------------------------------------------------------------------------------- 1 | 188d3289a38d9bf663e57cbf0ab8a773ff847e9ba40b6ce19caa700c782bfdfa 2 | -------------------------------------------------------------------------------- /csharp-cli/bin/Debug/net9.0/csharp-cli.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/bin/Debug/net9.0/csharp-cli.dll -------------------------------------------------------------------------------- /csharp-cli/bin/Debug/net9.0/csharp-cli.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/bin/Debug/net9.0/csharp-cli.exe -------------------------------------------------------------------------------- /csharp-cli/bin/Debug/net9.0/csharp-cli.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/bin/Debug/net9.0/csharp-cli.pdb -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/obj/Debug/net9.0/csharp-cli.dll -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/obj/Debug/net9.0/csharp-cli.pdb -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/ref/csharp-cli.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/obj/Debug/net9.0/ref/csharp-cli.dll -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/refint/csharp-cli.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/obj/Debug/net9.0/refint/csharp-cli.dll -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.assets.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XenocodeRCE/Philosophix/main/csharp-cli/obj/Debug/net9.0/csharp-cli.assets.cache -------------------------------------------------------------------------------- /csharp-cli/obj/csharp-cli.csproj.nuget.g.targets: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.sourcelink.json: -------------------------------------------------------------------------------- 1 | {"documents":{"C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\*":"https://raw.githubusercontent.com/XenocodeRCE/Philosophix/206592decd7c829d0a20b4a4e7b876e3ed21d7fa/*"}} -------------------------------------------------------------------------------- /csharp-cli/obj/project.nuget.cache: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "dgSpecHash": "aGZOJphQ1mA=", 4 | "success": true, 5 | "projectFilePath": "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\csharp-cli.csproj", 6 | "expectedPackageFiles": [], 7 | "logs": [] 8 | } -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] 5 | -------------------------------------------------------------------------------- /csharp-cli/bin/Debug/net9.0/csharp-cli.runtimeconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeOptions": { 3 | "tfm": "net9.0", 4 | "framework": { 5 | "name": "Microsoft.NETCore.App", 6 | "version": "9.0.0" 7 | }, 8 | "configProperties": { 9 | "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.GlobalUsings.g.cs: -------------------------------------------------------------------------------- 1 | // 2 | global using global::System; 3 | global using global::System.Collections.Generic; 4 | global using global::System.IO; 5 | global using global::System.Linq; 6 | global using global::System.Net.Http; 7 | global using global::System.Threading; 8 | global using global::System.Threading.Tasks; 9 | -------------------------------------------------------------------------------- /csharp-cli/start.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | title Philosophix CLI v2.0 3 | cd /d "%~dp0" 4 | 5 | echo ╔════════════════════════════════════════════════╗ 6 | echo ║ Philosophix CLI v2.0 ║ 7 | echo ║ Correction automatisée de copies ║ 8 | echo ╚════════════════════════════════════════════════╝ 9 | echo. 10 | echo Démarrage de l'application... 11 | echo. 12 | 13 | dotnet run 14 | 15 | pause 16 | -------------------------------------------------------------------------------- /csharp-cli/.gitignore: -------------------------------------------------------------------------------- 1 | # Fichiers de configuration avec clés API 2 | appsettings.json 3 | 4 | # Fichiers de build 5 | bin/ 6 | obj/ 7 | *.dll 8 | *.exe 9 | *.pdb 10 | 11 | # Fichiers temporaires 12 | *.tmp 13 | *.log 14 | 15 | # Fichiers de données locales 16 | devoirs.json 17 | devoirs_corrections.json 18 | *.txt 19 | 20 | # Fichiers VS Code 21 | .vscode/ 22 | .vs/ 23 | 24 | # Fichiers de cache 25 | *.cache 26 | 27 | # Autres 28 | .DS_Store 29 | Thumbs.db 30 | -------------------------------------------------------------------------------- /csharp-cli/csharp-cli.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | net9.0 5 | csharp_cli 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | PreserveNewest 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/config.php: -------------------------------------------------------------------------------- 1 | "SET NAMES utf8") 13 | ); 14 | $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 15 | } catch(PDOException $e) { 16 | die("Erreur de connexion : " . $e->getMessage()); 17 | } 18 | ?> -------------------------------------------------------------------------------- /csharp-cli/bin/Debug/net9.0/csharp-cli.deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "runtimeTarget": { 3 | "name": ".NETCoreApp,Version=v9.0", 4 | "signature": "" 5 | }, 6 | "compilationOptions": {}, 7 | "targets": { 8 | ".NETCoreApp,Version=v9.0": { 9 | "csharp-cli/1.0.0": { 10 | "runtime": { 11 | "csharp-cli.dll": {} 12 | } 13 | } 14 | } 15 | }, 16 | "libraries": { 17 | "csharp-cli/1.0.0": { 18 | "type": "project", 19 | "serviceable": false, 20 | "sha512": "" 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /csharp-cli/appsettings.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "LLM": { 3 | "Provider": "OpenAI", 4 | "_ProviderComment": "Choisir 'OpenAI' ou 'Ollama'" 5 | }, 6 | "OpenAI": { 7 | "ApiKey": "sk-YOUR_OPENAI_API_KEY_HERE", 8 | "Model": "gpt-4o-mini", 9 | "MaxTokens": 8000, 10 | "Temperature": 1.0 11 | }, 12 | "Ollama": { 13 | "BaseUrl": "http://localhost:11434", 14 | "Model": "llama3.1:8b", 15 | "Temperature": 1.0, 16 | "_ModelComment": "Exemples: llama3.1:8b, mixtral:8x7b, phi3:mini, qwen2.5:14b" 17 | }, 18 | "Database": { 19 | "DevoirsPath": "devoirs.json", 20 | "CorrectionsPath": "devoirs_corrections.json" 21 | }, 22 | "Correction": { 23 | "MinimumCopyLength": 500, 24 | "SeverityLevel": 3 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.GeneratedMSBuildEditorConfig.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | build_property.TargetFramework = net9.0 3 | build_property.TargetPlatformMinVersion = 4 | build_property.UsingMicrosoftNETSdkWeb = 5 | build_property.ProjectTypeGuids = 6 | build_property.InvariantGlobalization = 7 | build_property.PlatformNeutralAssembly = 8 | build_property.EnforceExtendedAnalyzerRules = 9 | build_property._SupportedPlatformList = Linux,macOS,Windows 10 | build_property.RootNamespace = csharp_cli 11 | build_property.ProjectDir = C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\ 12 | build_property.EnableComHosting = 13 | build_property.EnableGeneratedComInterfaceComImportInterop = 14 | build_property.EffectiveAnalysisLevelStyle = 9.0 15 | build_property.EnableCodeStyleSeverity = 16 | -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | using System; 11 | using System.Reflection; 12 | 13 | [assembly: System.Reflection.AssemblyCompanyAttribute("csharp-cli")] 14 | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] 15 | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] 16 | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+206592decd7c829d0a20b4a4e7b876e3ed21d7fa")] 17 | [assembly: System.Reflection.AssemblyProductAttribute("csharp-cli")] 18 | [assembly: System.Reflection.AssemblyTitleAttribute("csharp-cli")] 19 | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] 20 | 21 | // Généré par la classe MSBuild WriteCodeFragment. 22 | 23 | -------------------------------------------------------------------------------- /Philosophix.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.5.2.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp-cli", "csharp-cli\csharp-cli.csproj", "{204CB277-80C9-6A33-BA14-64F4D69B4723}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {204CB277-80C9-6A33-BA14-64F4D69B4723}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {204CB277-80C9-6A33-BA14-64F4D69B4723}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {204CB277-80C9-6A33-BA14-64F4D69B4723}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {204CB277-80C9-6A33-BA14-64F4D69B4723}.Release|Any CPU.Build.0 = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | GlobalSection(ExtensibilityGlobals) = postSolution 22 | SolutionGuid = {FF1603C2-1964-4DA3-AF65-BA97A18E5BEA} 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /csharp-cli/ILLMService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | /// 4 | /// Interface commune pour les services de modèles de langage (LLM) 5 | /// Permet de supporter OpenAI, Ollama, ou d'autres fournisseurs 6 | /// 7 | public interface ILLMService 8 | { 9 | /// 10 | /// Envoie une requête au modèle de langage avec un prompt système et utilisateur 11 | /// 12 | /// Message système définissant le contexte et le rôle 13 | /// Prompt de l'utilisateur 14 | /// Type d'opération pour le tracking des coûts 15 | /// Réponse du modèle 16 | Task AskAsync(string systemMessage, string userPrompt, string operationType); 17 | 18 | /// 19 | /// Calculateur de coûts (peut être null pour les services gratuits comme Ollama) 20 | /// 21 | CostCalculator? CostTracker { get; } 22 | 23 | /// 24 | /// Nom du service LLM utilisé 25 | /// 26 | string ServiceName { get; } 27 | 28 | /// 29 | /// Modèle utilisé par le service 30 | /// 31 | string ModelName { get; } 32 | } 33 | -------------------------------------------------------------------------------- /csharp-cli/Devoir.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.Json.Serialization; 4 | 5 | public class Devoir 6 | { 7 | [JsonPropertyName("id")] 8 | public int Id { get; set; } 9 | 10 | [JsonPropertyName("titre")] 11 | public string? Titre { get; set; } 12 | 13 | [JsonPropertyName("enonce")] 14 | public string? Enonce { get; set; } 15 | 16 | [JsonPropertyName("contenu")] 17 | public string? Contenu { get; set; } 18 | 19 | [JsonPropertyName("date_creation")] 20 | public DateTime DateCreation { get; set; } 21 | 22 | [JsonPropertyName("bareme")] 23 | public Bareme? Bareme { get; set; } 24 | 25 | [JsonPropertyName("type")] 26 | public string? Type { get; set; } 27 | 28 | [JsonPropertyName("type_bac")] 29 | public string? TypeBac { get; set; } 30 | } 31 | 32 | public class Bareme 33 | { 34 | [JsonPropertyName("competences")] 35 | public List? Competences { get; set; } 36 | } 37 | 38 | public class Competence 39 | { 40 | [JsonPropertyName("id")] 41 | public int Id { get; set; } 42 | 43 | [JsonPropertyName("nom")] 44 | public string? Nom { get; set; } 45 | 46 | [JsonPropertyName("criteres")] 47 | public List? Criteres { get; set; } 48 | } 49 | -------------------------------------------------------------------------------- /csharp-cli/obj/csharp-cli.csproj.nuget.g.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | True 5 | NuGet 6 | $(MSBuildThisFileDirectory)project.assets.json 7 | $(UserProfile)\.nuget\packages\ 8 | C:\Users\Shadow\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages 9 | PackageReference 10 | 6.13.1 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /csharp-cli/obj/Debug/net9.0/csharp-cli.csproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\bin\Debug\net9.0\csharp-cli.exe 2 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\bin\Debug\net9.0\csharp-cli.deps.json 3 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\bin\Debug\net9.0\csharp-cli.runtimeconfig.json 4 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\bin\Debug\net9.0\csharp-cli.dll 5 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\bin\Debug\net9.0\csharp-cli.pdb 6 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.GeneratedMSBuildEditorConfig.editorconfig 7 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.AssemblyInfoInputs.cache 8 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.AssemblyInfo.cs 9 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.csproj.CoreCompileInputs.cache 10 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.sourcelink.json 11 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.dll 12 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\refint\csharp-cli.dll 13 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.pdb 14 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\csharp-cli.genruntimeconfig.cache 15 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\obj\Debug\net9.0\ref\csharp-cli.dll 16 | C:\Users\Shadow\Documents\GitHub\Philosophix\csharp-cli\bin\Debug\net9.0\appsettings.json 17 | -------------------------------------------------------------------------------- /src/get-devoir.php: -------------------------------------------------------------------------------- 1 | 'ID du devoir non fourni']); 12 | exit; 13 | } 14 | 15 | try { 16 | $stmt = $pdo->prepare("SELECT * FROM devoirs WHERE id = ?"); 17 | $stmt->execute([$_GET['id']]); 18 | $devoir = $stmt->fetch(PDO::FETCH_ASSOC); 19 | 20 | if (!$devoir) { 21 | // Si le devoir n'existe pas, récupérer le barème par défaut 22 | $stmt = $pdo->prepare("SELECT * FROM devoirs WHERE id = 1"); 23 | $stmt->execute(); 24 | $devoir = $stmt->fetch(PDO::FETCH_ASSOC); 25 | 26 | if (!$devoir) { 27 | echo json_encode(['error' => 'Aucun barème trouvé']); 28 | exit; 29 | } 30 | } 31 | 32 | // Parse le JSON du barème 33 | $bareme = json_decode($devoir['bareme'], true); 34 | if (json_last_error() !== JSON_ERROR_NONE) { 35 | echo json_encode([ 36 | 'error' => 'Erreur de parsing JSON', 37 | 'details' => json_last_error_msg() 38 | ]); 39 | exit; 40 | } 41 | 42 | // Vérifier la structure du barème 43 | if (!isset($bareme['competences']) || !is_array($bareme['competences'])) { 44 | echo json_encode([ 45 | 'error' => 'Structure du barème invalide', 46 | 'bareme' => $bareme 47 | ]); 48 | exit; 49 | } 50 | 51 | $devoir['bareme'] = $bareme; 52 | echo json_encode($devoir); 53 | 54 | } catch (Exception $e) { 55 | echo json_encode([ 56 | 'error' => $e->getMessage(), 57 | 'trace' => $e->getTraceAsString() 58 | ]); 59 | } -------------------------------------------------------------------------------- /csharp-cli/JsonDatabaseService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | 6 | public class JsonDatabaseService 7 | { 8 | private readonly string _filePath; 9 | 10 | public JsonDatabaseService(string filePath) 11 | { 12 | _filePath = filePath; 13 | } 14 | 15 | public async Task> LireDevoirsAsync() 16 | { 17 | if (!File.Exists(_filePath)) 18 | { 19 | return new List(); 20 | } 21 | 22 | var json = await File.ReadAllTextAsync(_filePath); 23 | return JsonSerializer.Deserialize>(json) ?? new List(); 24 | } 25 | 26 | public async Task SauvegarderDevoirsAsync(List devoirs) 27 | { 28 | var options = new JsonSerializerOptions { WriteIndented = true }; 29 | var json = JsonSerializer.Serialize(devoirs, options); 30 | await File.WriteAllTextAsync(_filePath, json); 31 | } 32 | 33 | public async Task> LireCorrectionsAsync() 34 | { 35 | var correctionsFilePath = Path.ChangeExtension(_filePath, null) + "_corrections.json"; 36 | if (!File.Exists(correctionsFilePath)) 37 | { 38 | return new List(); 39 | } 40 | 41 | var json = await File.ReadAllTextAsync(correctionsFilePath); 42 | return JsonSerializer.Deserialize>(json) ?? new List(); 43 | } 44 | 45 | public async Task SauvegarderCorrectionsAsync(List corrections) 46 | { 47 | var correctionsFilePath = Path.ChangeExtension(_filePath, null) + "_corrections.json"; 48 | var options = new JsonSerializerOptions { WriteIndented = true }; 49 | var json = JsonSerializer.Serialize(corrections, options); 50 | await File.WriteAllTextAsync(correctionsFilePath, json); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/traitement-devoir.php: -------------------------------------------------------------------------------- 1 | query("SELECT bareme FROM devoirs WHERE id = 1"); 39 | $bareme = $stmt->fetchColumn(); 40 | 41 | if (!$bareme) { 42 | throw new Exception('Barème par défaut non trouvé'); 43 | } 44 | 45 | // Insertion dans la base de données 46 | $stmt = $pdo->prepare("INSERT INTO devoirs (titre, enonce, contenu, bareme) VALUES (?, ?, ?, ?)"); 47 | $stmt->execute([$titre, $enonce, $contenu, $bareme]); 48 | 49 | echo json_encode([ 50 | 'success' => true, 51 | 'message' => 'Devoir créé avec succès', 52 | 'id' => $pdo->lastInsertId() 53 | ]); 54 | 55 | } catch (Exception $e) { 56 | echo json_encode([ 57 | 'success' => false, 58 | 'message' => $e->getMessage() 59 | ]); 60 | } -------------------------------------------------------------------------------- /src/openai.php: -------------------------------------------------------------------------------- 1 | [ 15 | [ 16 | 'role' => 'system', 17 | 'content' => $system 18 | ], 19 | [ 20 | 'role' => 'user', 21 | 'content' => $prompt 22 | ] 23 | ], 24 | 'model' => 'gpt-4o-mini', 25 | 'temperature' => 1, 26 | 'max_tokens' => 8000, 27 | 'top_p' => 1, 28 | 'stream' => false, 29 | 'stop' => null 30 | ]); 31 | 32 | // Initialiser cURL 33 | $ch = curl_init($url); 34 | 35 | // Configurer les options cURL 36 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 37 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ 38 | 'Content-Type: application/json', 39 | 'Authorization: Bearer ' . $apiKey, 40 | ]); 41 | curl_setopt($ch, CURLOPT_POST, true); 42 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 43 | 44 | // Exécuter la requête cURL et récupérer la réponse 45 | $response = curl_exec($ch); 46 | $error = curl_error($ch); 47 | 48 | // Fermer cURL 49 | curl_close($ch); 50 | 51 | // Gérer les erreurs 52 | if ($error) { 53 | return 'Erreur cURL : ' . $error; 54 | } else { 55 | return $response; 56 | } 57 | } 58 | 59 | 60 | // Vérifier si les données ont été envoyées via POST 61 | if ($_SERVER['REQUEST_METHOD'] === 'POST') { 62 | // Récupérer les données du formulaire via POST 63 | $system = isset($_POST['system']) ? $_POST['system'] : ''; 64 | $prompt = isset($_POST['prompt']) ? $_POST['prompt'] : ''; 65 | 66 | // Appeler la fonction askGPT avec les données récupérées 67 | $response = askGPT($system, $prompt); 68 | 69 | // Retourner la réponse au format JSON 70 | header('Content-Type: application/json'); 71 | echo json_encode(['response' => ($response)]); 72 | } -------------------------------------------------------------------------------- /src/sauvegarder-correction.php: -------------------------------------------------------------------------------- 1 | beginTransaction(); 14 | 15 | // Insertion de la correction principale 16 | $stmt = $pdo->prepare(" 17 | INSERT INTO corrections ( 18 | id, devoir_id, note, appreciation, 19 | points_forts, points_ameliorer, competences, copie, date_correction 20 | ) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?) 21 | "); 22 | 23 | $stmt->execute([ 24 | $data['devoir_id'], 25 | $data['note'], 26 | $data['appreciation'], 27 | json_encode($data['points_forts']), 28 | json_encode($data['points_ameliorer']), 29 | json_encode($data['competences']), 30 | $data['copie'], 31 | $data['date_correction'] 32 | ]); 33 | 34 | $correction_id = $pdo->lastInsertId(); 35 | 36 | // Insertion des évaluations par compétence 37 | $stmt = $pdo->prepare(" 38 | INSERT INTO evaluations_competences ( 39 | correction_id, nom_competence, note, 40 | analyse, points_forts, points_ameliorer 41 | ) VALUES (?, ?, ?, ?, ?, ?) 42 | "); 43 | 44 | foreach ($data['competences'] as $comp) { 45 | $stmt->execute([ 46 | $correction_id, 47 | $comp['nom'], 48 | $comp['note'], 49 | $comp['analyse'], 50 | json_encode($comp['points_forts']), 51 | json_encode($comp['points_ameliorer']) 52 | ]); 53 | } 54 | 55 | $pdo->commit(); 56 | 57 | echo json_encode([ 58 | 'success' => true, 59 | 'message' => 'Correction sauvegardée avec succès', 60 | 'correction_id' => $correction_id 61 | ]); 62 | 63 | } catch (Exception $e) { 64 | if ($pdo->inTransaction()) { 65 | $pdo->rollBack(); 66 | } 67 | echo json_encode([ 68 | 'success' => false, 69 | 'message' => $e->getMessage() 70 | ]); 71 | } 72 | -------------------------------------------------------------------------------- /csharp-cli/Correction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.Json.Serialization; 4 | 5 | public class Correction 6 | { 7 | [JsonPropertyName("id")] 8 | public int Id { get; set; } 9 | 10 | [JsonPropertyName("devoir_id")] 11 | public int DevoirId { get; set; } 12 | 13 | [JsonPropertyName("note")] 14 | public decimal Note { get; set; } 15 | 16 | [JsonPropertyName("appreciation")] 17 | public string? Appreciation { get; set; } 18 | 19 | [JsonPropertyName("points_forts")] 20 | public List? PointsForts { get; set; } 21 | 22 | [JsonPropertyName("points_ameliorer")] 23 | public List? PointsAmeliorer { get; set; } 24 | 25 | [JsonPropertyName("competences")] 26 | public List? Competences { get; set; } 27 | 28 | [JsonPropertyName("copie")] 29 | public string? Copie { get; set; } 30 | 31 | [JsonPropertyName("date_correction")] 32 | public DateTime DateCorrection { get; set; } 33 | } 34 | 35 | public class EvaluationCompetence 36 | { 37 | [JsonPropertyName("nom")] 38 | public string? Nom { get; set; } 39 | 40 | [JsonPropertyName("note")] 41 | public decimal Note { get; set; } 42 | 43 | [JsonPropertyName("analyse")] 44 | public string? Analyse { get; set; } 45 | 46 | [JsonPropertyName("points_forts")] 47 | public List? PointsForts { get; set; } 48 | 49 | [JsonPropertyName("points_ameliorer")] 50 | public List? PointsAmeliorer { get; set; } 51 | } 52 | 53 | // Classes pour désérialiser les réponses de l'API OpenAI 54 | public class EvaluationApiResponse 55 | { 56 | [JsonPropertyName("note")] 57 | public decimal Note { get; set; } 58 | 59 | [JsonPropertyName("analyse")] 60 | public string? Analyse { get; set; } 61 | 62 | [JsonPropertyName("points_forts")] 63 | public List? PointsForts { get; set; } 64 | 65 | [JsonPropertyName("points_ameliorer")] 66 | public List? PointsAmeliorer { get; set; } 67 | } 68 | 69 | public class EvaluationFinaleApiResponse 70 | { 71 | [JsonPropertyName("appreciation")] 72 | public string? Appreciation { get; set; } 73 | 74 | [JsonPropertyName("points_forts")] 75 | public List? PointsForts { get; set; } 76 | 77 | [JsonPropertyName("points_ameliorer")] 78 | public List? PointsAmeliorer { get; set; } 79 | } 80 | -------------------------------------------------------------------------------- /csharp-cli/obj/project.assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "targets": { 4 | "net9.0": {} 5 | }, 6 | "libraries": {}, 7 | "projectFileDependencyGroups": { 8 | "net9.0": [] 9 | }, 10 | "packageFolders": { 11 | "C:\\Users\\Shadow\\.nuget\\packages\\": {}, 12 | "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} 13 | }, 14 | "project": { 15 | "version": "1.0.0", 16 | "restore": { 17 | "projectUniqueName": "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\csharp-cli.csproj", 18 | "projectName": "csharp-cli", 19 | "projectPath": "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\csharp-cli.csproj", 20 | "packagesPath": "C:\\Users\\Shadow\\.nuget\\packages\\", 21 | "outputPath": "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\obj\\", 22 | "projectStyle": "PackageReference", 23 | "fallbackFolders": [ 24 | "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" 25 | ], 26 | "configFilePaths": [ 27 | "C:\\Users\\Shadow\\AppData\\Roaming\\NuGet\\NuGet.Config", 28 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", 29 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" 30 | ], 31 | "originalTargetFrameworks": [ 32 | "net9.0" 33 | ], 34 | "sources": { 35 | "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, 36 | "https://api.nuget.org/v3/index.json": {} 37 | }, 38 | "frameworks": { 39 | "net9.0": { 40 | "targetAlias": "net9.0", 41 | "projectReferences": {} 42 | } 43 | }, 44 | "warningProperties": { 45 | "warnAsError": [ 46 | "NU1605" 47 | ] 48 | }, 49 | "restoreAuditProperties": { 50 | "enableAudit": "true", 51 | "auditLevel": "low", 52 | "auditMode": "direct" 53 | }, 54 | "SdkAnalysisLevel": "9.0.200" 55 | }, 56 | "frameworks": { 57 | "net9.0": { 58 | "targetAlias": "net9.0", 59 | "imports": [ 60 | "net461", 61 | "net462", 62 | "net47", 63 | "net471", 64 | "net472", 65 | "net48", 66 | "net481" 67 | ], 68 | "assetTargetFallback": true, 69 | "warn": true, 70 | "frameworkReferences": { 71 | "Microsoft.NETCore.App": { 72 | "privateAssets": "all" 73 | } 74 | }, 75 | "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json" 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /csharp-cli/obj/csharp-cli.csproj.nuget.dgspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "format": 1, 3 | "restore": { 4 | "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\csharp-cli.csproj": {} 5 | }, 6 | "projects": { 7 | "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\csharp-cli.csproj": { 8 | "version": "1.0.0", 9 | "restore": { 10 | "projectUniqueName": "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\csharp-cli.csproj", 11 | "projectName": "csharp-cli", 12 | "projectPath": "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\csharp-cli.csproj", 13 | "packagesPath": "C:\\Users\\Shadow\\.nuget\\packages\\", 14 | "outputPath": "C:\\Users\\Shadow\\Documents\\GitHub\\Philosophix\\csharp-cli\\obj\\", 15 | "projectStyle": "PackageReference", 16 | "fallbackFolders": [ 17 | "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" 18 | ], 19 | "configFilePaths": [ 20 | "C:\\Users\\Shadow\\AppData\\Roaming\\NuGet\\NuGet.Config", 21 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", 22 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" 23 | ], 24 | "originalTargetFrameworks": [ 25 | "net9.0" 26 | ], 27 | "sources": { 28 | "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, 29 | "https://api.nuget.org/v3/index.json": {} 30 | }, 31 | "frameworks": { 32 | "net9.0": { 33 | "targetAlias": "net9.0", 34 | "projectReferences": {} 35 | } 36 | }, 37 | "warningProperties": { 38 | "warnAsError": [ 39 | "NU1605" 40 | ] 41 | }, 42 | "restoreAuditProperties": { 43 | "enableAudit": "true", 44 | "auditLevel": "low", 45 | "auditMode": "direct" 46 | }, 47 | "SdkAnalysisLevel": "9.0.200" 48 | }, 49 | "frameworks": { 50 | "net9.0": { 51 | "targetAlias": "net9.0", 52 | "imports": [ 53 | "net461", 54 | "net462", 55 | "net47", 56 | "net471", 57 | "net472", 58 | "net48", 59 | "net481" 60 | ], 61 | "assetTargetFallback": true, 62 | "warn": true, 63 | "frameworkReferences": { 64 | "Microsoft.NETCore.App": { 65 | "privateAssets": "all" 66 | } 67 | }, 68 | "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json" 69 | } 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /csharp-cli/INSTALLATION.md: -------------------------------------------------------------------------------- 1 | # 🚀 Installation Rapide - Philosophix CLI 2 | 3 | ## Étapes d'installation 4 | 5 | ### 1. Prérequis 6 | - ✅ .NET 9.0 SDK installé 7 | - ✅ Clé API OpenAI active 8 | 9 | ### 2. Configuration 10 | 1. Ouvrir le fichier `OpenAiService.cs` 11 | 2. Ligne 16, remplacer `"sk-"` par votre clé API OpenAI : 12 | ```csharp 13 | _apiKey = "sk-votre-clé-api-ici"; 14 | ``` 15 | 16 | ### 3. Compilation 17 | ```bash 18 | dotnet build 19 | ``` 20 | 21 | ### 4. Lancement 22 | **Option A** - Ligne de commande : 23 | ```bash 24 | dotnet run 25 | ``` 26 | 27 | **Option B** - Script Windows : 28 | Double-cliquez sur `start.bat` 29 | 30 | ## 🧪 Test Rapide 31 | 32 | ### Tester avec l'exemple fourni 33 | 1. Choisir "1. Créer un devoir" ou copier `devoirs_exemple.json` vers `devoirs.json` 34 | 2. Choisir "3. Corriger une copie" 35 | 3. Sélectionner le devoir ID 1 36 | 4. Choisir "2. Charger depuis un fichier" 37 | 5. Entrer le chemin : `copie_exemple.txt` 38 | 6. Attendre la correction automatique 39 | 40 | ### Créer votre propre devoir 41 | 1. Menu "1. Créer un devoir" 42 | 2. Saisir titre, énoncé, type (dissertation/explication) 43 | 3. Le barème sera automatiquement assigné 44 | 45 | ## 📁 Structure des Fichiers 46 | 47 | ``` 48 | csharp-cli/ 49 | ├── Program.cs # Interface utilisateur 50 | ├── CorrectionService.cs # Logique de correction 51 | ├── OpenAiService.cs # Service API OpenAI 52 | ├── JsonDatabaseService.cs # Persistance données 53 | ├── Devoir.cs # Modèles devoirs 54 | ├── Correction.cs # Modèles corrections 55 | ├── README.md # Documentation complète 56 | ├── INSTALLATION.md # Ce fichier 57 | ├── start.bat # Script de démarrage Windows 58 | ├── appsettings.json # Configuration 59 | ├── devoirs_exemple.json # Exemple de devoir 60 | └── copie_exemple.txt # Exemple de copie 61 | ``` 62 | 63 | ## ⚠️ Points d'Attention 64 | 65 | - **Clé API** : Obligatoire pour le fonctionnement 66 | - **Connectivité** : Internet requis pour l'API OpenAI 67 | - **Longueur copie** : Minimum 500 caractères 68 | - **Coût** : Usage de l'API OpenAI facturé selon tarifs OpenAI 69 | 70 | ## 🆘 Dépannage 71 | 72 | ### Erreur de compilation 73 | - Vérifier .NET 9.0 installé : `dotnet --version` 74 | - Nettoyer et recompiler : `dotnet clean && dotnet build` 75 | 76 | ### Erreur API OpenAI 77 | - Vérifier la clé API dans `OpenAiService.cs` 78 | - Contrôler les crédits disponibles sur votre compte OpenAI 79 | - Tester la connectivité internet 80 | 81 | ### Fichiers manquants 82 | - Les fichiers JSON sont créés automatiquement au premier usage 83 | - Copier les exemples fournis si nécessaire 84 | 85 | ## 🎯 Utilisation Efficace 86 | 87 | 1. **Préparer vos devoirs** : Créez d'abord tous vos sujets 88 | 2. **Tester avec exemples** : Utilisez les fichiers fournis pour valider 89 | 3. **Copier-coller** : Plus rapide que le chargement de fichiers pour les courtes copies 90 | 4. **Sauvegarder** : Toutes les corrections sont automatiquement sauvegardées 91 | 92 | Vous êtes maintenant prêt à utiliser Philosophix CLI ! 🎉 93 | -------------------------------------------------------------------------------- /csharp-cli/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog - Philosophix CLI 2 | 3 | ## Version 2.1 - Refactoring Architecture (22 juin 2025) 4 | 5 | ### 🔄 Refactoring Majeur 6 | - **Séparation des responsabilités** : Extraction de la logique de correction depuis `Program.cs` 7 | - **Nouvelle classe `CorrectionService.cs`** : Centralisation de toute la logique métier de correction 8 | - **Code plus maintenable** : Séparation claire entre interface utilisateur et logique métier 9 | 10 | ### ✨ Améliorations 11 | - **Architecture SOLID** : Respect des principes de responsabilité unique 12 | - **Testabilité** : Services isolés plus facilement testables 13 | - **Lisibilité** : `Program.cs` réduit de ~300 lignes, plus focus sur l'interface 14 | - **Réutilisabilité** : `CorrectionService` peut être utilisé dans d'autres interfaces 15 | 16 | ### 📁 Structure Modifiée 17 | ``` 18 | Avant (v2.0): 19 | - Program.cs (533 lignes) : Interface + Logique métier 20 | - OpenAiService.cs : API + Parsing 21 | - JsonDatabaseService.cs : Persistance 22 | - Devoir.cs / Correction.cs : Modèles 23 | 24 | Après (v2.1): 25 | - Program.cs (292 lignes) : Interface utilisateur uniquement 26 | - CorrectionService.cs (245 lignes) : Logique métier de correction 27 | - OpenAiService.cs : API + Parsing 28 | - JsonDatabaseService.cs : Persistance 29 | - Devoir.cs / Correction.cs : Modèles 30 | ``` 31 | 32 | ### 🔧 Détails Techniques 33 | 34 | #### Méthodes Déplacées vers CorrectionService 35 | - `CorrigerCopieAsync()` : Orchestration complète de la correction 36 | - `EvaluerCompetenceAsync()` : Évaluation d'une compétence spécifique 37 | - `EvaluerFinalAsync()` : Génération de l'évaluation finale 38 | - `GetEchelleNotation()` : Récupération des échelles de notation 39 | - `ValiderCopie()` : Validation des critères de copie 40 | - `AfficherResultatsCorrection()` : Affichage formaté des résultats 41 | 42 | #### Interface Program.cs Simplifiée 43 | - Conservation uniquement des méthodes d'interface utilisateur 44 | - Navigation, saisie, affichage des listes 45 | - Appels délégués vers les services métier 46 | 47 | #### Injection de Dépendances 48 | ```csharp 49 | var correctionService = new CorrectionService(openAiService, dbService); 50 | ``` 51 | 52 | ### 🚀 Bénéfices Immédiats 53 | 1. **Maintenance** : Modifications de la logique de correction isolées 54 | 2. **Tests** : Possibilité de tester `CorrectionService` indépendamment 55 | 3. **Évolution** : Ajout de nouvelles interfaces (Web, API) facilité 56 | 4. **Lisibilité** : Code plus clair et organisé 57 | 5. **Debugging** : Isolation des erreurs par responsabilité 58 | 59 | ### 🔄 Migration 60 | - **Aucun changement utilisateur** : Interface identique 61 | - **Compatibilité** : Tous les fichiers de données conservés 62 | - **Performance** : Aucun impact sur les performances 63 | 64 | --- 65 | 66 | ## Version 2.0 - Version Initiale (22 juin 2025) 67 | 68 | ### 🎉 Fonctionnalités Initiales 69 | - Interface CLI complète 70 | - Correction automatisée par compétences 71 | - Gestion des devoirs (création, consultation) 72 | - Historique des corrections 73 | - Support dissertation et explication de texte 74 | - Intégration API OpenAI (GPT-4o-mini) 75 | - Persistance JSON locale 76 | 77 | ### 📋 Barèmes Philosophie 78 | - **Dissertation** : 7 compétences spécialisées 79 | - **Explication** : 7 compétences d'analyse de texte 80 | - **Échelles officielles** : Conformes aux critères académiques 81 | 82 | ### 🛠️ Stack Technique 83 | - **.NET 9.0** : Framework moderne 84 | - **JSON** : Stockage local simple 85 | - **OpenAI API** : IA de correction 86 | - **Console App** : Interface utilisateur efficace 87 | -------------------------------------------------------------------------------- /csharp-cli/OLLAMA_SETUP.md: -------------------------------------------------------------------------------- 1 | # Configuration Ollama pour Philosophix CLI 2 | 3 | ## Qu'est-ce qu'Ollama ? 4 | 5 | Ollama est une solution open-source qui permet d'exécuter des modèles de langage (LLM) localement sur votre machine. Contrairement à OpenAI qui est payant et nécessite une connexion internet, Ollama est : 6 | 7 | - **Gratuit** : Aucun coût d'utilisation 8 | - **Privé** : Les données restent sur votre machine 9 | - **Hors ligne** : Fonctionne sans connexion internet une fois installé 10 | - **Performant** : Optimisé pour l'exécution locale 11 | 12 | ## Installation d'Ollama 13 | 14 | ### Windows 15 | ```bash 16 | # Télécharger depuis https://ollama.com/download 17 | # Ou avec winget : 18 | winget install Ollama.Ollama 19 | ``` 20 | 21 | ### macOS 22 | ```bash 23 | # Télécharger depuis https://ollama.com/download 24 | # Ou avec Homebrew : 25 | brew install ollama 26 | ``` 27 | 28 | ### Linux 29 | ```bash 30 | curl -fsSL https://ollama.com/install.sh | sh 31 | ``` 32 | 33 | ## Configuration des Modèles 34 | 35 | ### Modèles Recommandés pour la Philosophie 36 | 37 | 1. **Llama 3.1 8B** (Recommandé) - Équilibre performance/qualité 38 | ```bash 39 | ollama pull llama3.1:8b 40 | ``` 41 | 42 | 2. **Qwen2.5 14B** - Excellente qualité mais plus lourd 43 | ```bash 44 | ollama pull qwen2.5:14b 45 | ``` 46 | 47 | 3. **Phi-3 Mini** - Très léger, bon pour les tests 48 | ```bash 49 | ollama pull phi3:mini 50 | ``` 51 | 52 | 4. **Mixtral 8x7B** - Très bonne qualité mais nécessite plus de RAM 53 | ```bash 54 | ollama pull mixtral:8x7b 55 | ``` 56 | 57 | ### Démarrage du Service 58 | 59 | ```bash 60 | # Démarrer Ollama en arrière-plan 61 | ollama serve 62 | ``` 63 | 64 | Le service sera accessible sur `http://localhost:11434` 65 | 66 | ## Configuration de Philosophix CLI 67 | 68 | Modifiez votre `appsettings.json` : 69 | 70 | ```json 71 | { 72 | "LLM": { 73 | "Provider": "Ollama" 74 | }, 75 | "Ollama": { 76 | "BaseUrl": "http://localhost:11434", 77 | "Model": "llama3.1:8b", 78 | "Temperature": 1.0 79 | } 80 | } 81 | ``` 82 | 83 | ## Comparaison OpenAI vs Ollama 84 | 85 | | Critère | OpenAI | Ollama | 86 | |---------|--------|--------| 87 | | **Coût** | ~0.02-0.04€/correction | Gratuit | 88 | | **Qualité** | Très élevée | Bonne à très bonne | 89 | | **Vitesse** | Rapide (2-5s) | Variable (5-30s) | 90 | | **Privacité** | Données envoyées à OpenAI | 100% local | 91 | | **Installation** | Simple (clé API) | Installation + téléchargement modèles | 92 | | **Ressources** | Aucune | RAM : 8GB min, 16GB recommandé | 93 | 94 | ## Exigences Système pour Ollama 95 | 96 | ### Configuration Minimale 97 | - **RAM** : 8 GB (pour modèles 7-8B) 98 | - **Stockage** : 5-10 GB par modèle 99 | - **CPU** : Processeur moderne (derniers 5 ans) 100 | 101 | ### Configuration Recommandée 102 | - **RAM** : 16 GB ou plus 103 | - **GPU** : Carte graphique NVIDIA (optionnel, accélère significativement) 104 | - **Stockage** : SSD pour de meilleures performances 105 | 106 | ## Résolution de Problèmes 107 | 108 | ### Ollama ne démarre pas 109 | ```bash 110 | # Vérifier l'installation 111 | ollama --version 112 | 113 | # Redémarrer le service 114 | ollama serve 115 | ``` 116 | 117 | ### Modèle non trouvé 118 | ```bash 119 | # Lister les modèles installés 120 | ollama list 121 | 122 | # Télécharger le modèle manquant 123 | ollama pull llama3.1:8b 124 | ``` 125 | 126 | ### Performances lentes 127 | 1. Vérifiez votre RAM disponible : `htop` (Linux/macOS) ou Gestionnaire des tâches (Windows) 128 | 2. Utilisez un modèle plus léger : `phi3:mini` 129 | 3. Fermez les autres applications gourmandes 130 | 131 | ### Erreur de connexion dans Philosophix 132 | 1. Vérifiez qu'Ollama est démarré : `ollama serve` 133 | 2. Testez l'accès : `curl http://localhost:11434/api/tags` 134 | 3. Vérifiez la configuration dans `appsettings.json` 135 | 136 | ## Test de Fonctionnement 137 | 138 | ```bash 139 | # Tester Ollama directement 140 | ollama run llama3.1:8b "Écris une phrase sur la philosophie" 141 | 142 | # Si ça fonctionne, Philosophix CLI devrait aussi fonctionner 143 | ``` 144 | 145 | ## Migration OpenAI → Ollama 146 | 147 | Pour passer d'OpenAI à Ollama : 148 | 149 | 1. Installez Ollama et téléchargez un modèle 150 | 2. Modifiez `"Provider": "Ollama"` dans `appsettings.json` 151 | 3. Relancez Philosophix CLI 152 | 4. Vos données et corrections existantes sont conservées 153 | 154 | ## Avantages Pédagogiques d'Ollama 155 | 156 | - **Économies** : Pas de coûts récurrents pour l'établissement 157 | - **RGPD** : Conformité totale, données jamais transmises 158 | - **Autonomie** : Fonctionne même sans internet 159 | - **Transparence** : Modèles open-source auditables 160 | - **Pérennité** : Pas de dépendance à un service externe 161 | 162 | --- 163 | 164 | *Pour plus d'informations : https://ollama.com/docs* 165 | -------------------------------------------------------------------------------- /csharp-cli/CostCalculator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | public class CostCalculator 6 | { 7 | // Tarifs GPT-4o-mini par million de tokens (en USD) 8 | private const decimal INPUT_COST_PER_MILLION = 0.15m; 9 | private const decimal CACHED_INPUT_COST_PER_MILLION = 0.075m; 10 | private const decimal OUTPUT_COST_PER_MILLION = 0.60m; 11 | 12 | private List _requests = new List(); 13 | 14 | public class RequestCost 15 | { 16 | public string Type { get; set; } = ""; 17 | public int InputTokens { get; set; } 18 | public int CachedInputTokens { get; set; } 19 | public int OutputTokens { get; set; } 20 | public decimal Cost { get; set; } 21 | public DateTime Timestamp { get; set; } = DateTime.Now; 22 | } 23 | 24 | /// 25 | /// Calcule le coût d'une requête GPT 26 | /// 27 | public decimal CalculateRequestCost(int inputTokens, int outputTokens, int cachedInputTokens = 0) 28 | { 29 | decimal inputCost = (inputTokens * INPUT_COST_PER_MILLION) / 1_000_000m; 30 | decimal cachedInputCost = (cachedInputTokens * CACHED_INPUT_COST_PER_MILLION) / 1_000_000m; 31 | decimal outputCost = (outputTokens * OUTPUT_COST_PER_MILLION) / 1_000_000m; 32 | 33 | return inputCost + cachedInputCost + outputCost; 34 | } 35 | 36 | /// 37 | /// Ajoute une requête au tracker de coûts 38 | /// 39 | public void AddRequest(string type, int inputTokens, int outputTokens, int cachedInputTokens = 0) 40 | { 41 | var cost = CalculateRequestCost(inputTokens, outputTokens, cachedInputTokens); 42 | 43 | _requests.Add(new RequestCost 44 | { 45 | Type = type, 46 | InputTokens = inputTokens, 47 | CachedInputTokens = cachedInputTokens, 48 | OutputTokens = outputTokens, 49 | Cost = cost 50 | }); 51 | 52 | // Afficher le coût de cette requête 53 | Console.WriteLine($"💰 Coût requête {type}: ${cost:F6} ({inputTokens} in + {outputTokens} out tokens)"); 54 | } 55 | 56 | /// 57 | /// Affiche le résumé des coûts 58 | /// 59 | public void DisplayCostSummary() 60 | { 61 | if (!_requests.Any()) 62 | { 63 | Console.WriteLine("Aucune requête enregistrée."); 64 | return; 65 | } 66 | 67 | Console.WriteLine("\n" + new string('═', 60)); 68 | Console.WriteLine("💰 RÉSUMÉ DES COÛTS DE CORRECTION"); 69 | Console.WriteLine(new string('═', 60)); 70 | 71 | var totalCost = _requests.Sum(r => r.Cost); 72 | var totalInputTokens = _requests.Sum(r => r.InputTokens); 73 | var totalOutputTokens = _requests.Sum(r => r.OutputTokens); 74 | var totalCachedInputTokens = _requests.Sum(r => r.CachedInputTokens); 75 | 76 | Console.WriteLine($"📊 Nombre de requêtes: {_requests.Count}"); 77 | Console.WriteLine($"📥 Total tokens d'entrée: {totalInputTokens:N0}"); 78 | Console.WriteLine($"📤 Total tokens de sortie: {totalOutputTokens:N0}"); 79 | if (totalCachedInputTokens > 0) 80 | { 81 | Console.WriteLine($"⚡ Total tokens cachés: {totalCachedInputTokens:N0}"); 82 | } 83 | Console.WriteLine($"💵 COÛT TOTAL: ${totalCost:F6}"); 84 | Console.WriteLine($"💶 COÛT TOTAL (EUR): €{totalCost * 0.92m:F6}"); // Approximation USD -> EUR 85 | 86 | Console.WriteLine("\n📋 Détail par type de requête:"); 87 | var groupedRequests = _requests.GroupBy(r => r.Type) 88 | .Select(g => new { 89 | Type = g.Key, 90 | Count = g.Count(), 91 | TotalCost = g.Sum(r => r.Cost), 92 | AvgCost = g.Average(r => r.Cost) 93 | }) 94 | .OrderByDescending(g => g.TotalCost); 95 | 96 | foreach (var group in groupedRequests) 97 | { 98 | Console.WriteLine($" • {group.Type}: {group.Count}x requêtes, ${group.TotalCost:F6} (moy: ${group.AvgCost:F6})"); 99 | } 100 | } 101 | 102 | /// 103 | /// Remet à zéro les coûts 104 | /// 105 | public void Reset() 106 | { 107 | _requests.Clear(); 108 | Console.WriteLine("💰 Compteur de coûts remis à zéro."); 109 | } 110 | 111 | /// 112 | /// Estime les tokens d'un texte (approximation) 113 | /// 114 | public static int EstimateTokens(string text) 115 | { 116 | if (string.IsNullOrEmpty(text)) 117 | return 0; 118 | 119 | // Approximation: 1 token ≈ 4 caractères en français 120 | // GPT utilise une tokenisation plus complexe, mais c'est une estimation 121 | return (int)Math.Ceiling(text.Length / 4.0); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /csharp-cli/LLMServiceFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | 6 | /// 7 | /// Factory pour créer le service LLM approprié selon la configuration 8 | /// 9 | public static class LLMServiceFactory 10 | { 11 | /// 12 | /// Crée une instance du service LLM configuré 13 | /// 14 | /// Service LLM (OpenAI ou Ollama) 15 | public static ILLMService CreateService() 16 | { 17 | try 18 | { 19 | var config = LoadConfiguration(); 20 | var provider = config.LLM?.Provider?.ToLower(); 21 | 22 | switch (provider) 23 | { 24 | case "openai": 25 | Console.WriteLine("🔧 Configuration: Utilisation d'OpenAI"); 26 | return new OpenAiService(); 27 | 28 | case "ollama": 29 | Console.WriteLine("🔧 Configuration: Utilisation d'Ollama (local)"); 30 | return new OllamaService(); 31 | 32 | default: 33 | Console.WriteLine($"⚠️ Provider '{provider}' non reconnu, utilisation d'OpenAI par défaut"); 34 | return new OpenAiService(); 35 | } 36 | } 37 | catch (Exception ex) 38 | { 39 | Console.WriteLine($"❌ Erreur lors de la création du service LLM : {ex.Message}"); 40 | Console.WriteLine("📋 Vérifiez votre configuration dans appsettings.json"); 41 | throw; 42 | } 43 | } 44 | 45 | /// 46 | /// Affiche des informations sur la configuration LLM active 47 | /// 48 | public static void AfficherInfoConfiguration() 49 | { 50 | try 51 | { 52 | var config = LoadConfiguration(); 53 | var provider = config.LLM?.Provider ?? "OpenAI"; 54 | 55 | Console.WriteLine("\n" + new string('═', 50)); 56 | Console.WriteLine("🤖 CONFIGURATION LLM ACTIVE"); 57 | Console.WriteLine(new string('═', 50)); 58 | Console.WriteLine($"Provider : {provider}"); 59 | 60 | if (provider.ToLower() == "openai") 61 | { 62 | Console.WriteLine($"Modèle : {config.OpenAI?.Model ?? "gpt-4o-mini"}"); 63 | Console.WriteLine($"Max Tokens : {config.OpenAI?.MaxTokens ?? 8000}"); 64 | Console.WriteLine($"Température : {config.OpenAI?.Temperature ?? 1.0}"); 65 | Console.WriteLine("💰 Coût : Payant (suivi automatique)"); 66 | } 67 | else if (provider.ToLower() == "ollama") 68 | { 69 | Console.WriteLine($"Modèle : {config.Ollama?.Model ?? "llama3.1:8b"}"); 70 | Console.WriteLine($"URL : {config.Ollama?.BaseUrl ?? "http://localhost:11434"}"); 71 | Console.WriteLine($"Température : {config.Ollama?.Temperature ?? 1.0}"); 72 | Console.WriteLine("🆓 Coût : Gratuit (local)"); 73 | } 74 | 75 | Console.WriteLine(new string('═', 50)); 76 | } 77 | catch (Exception ex) 78 | { 79 | Console.WriteLine($"⚠️ Impossible d'afficher la configuration : {ex.Message}"); 80 | } 81 | } 82 | 83 | /// 84 | /// Vérifie si Ollama est accessible si configuré 85 | /// 86 | public static async Task VerifierConnexionOllamaAsync() 87 | { 88 | try 89 | { 90 | var config = LoadConfiguration(); 91 | if (config.LLM?.Provider?.ToLower() == "ollama") 92 | { 93 | var ollamaService = new OllamaService(); 94 | // Test simple de connexion 95 | await ollamaService.AskAsync("Tu es un assistant.", "Dis juste 'OK' pour tester la connexion.", "Test connexion"); 96 | return true; 97 | } 98 | return true; // OpenAI ou autre provider 99 | } 100 | catch 101 | { 102 | return false; 103 | } 104 | } 105 | 106 | private static AppSettings LoadConfiguration() 107 | { 108 | var configPath = "appsettings.json"; 109 | if (!File.Exists(configPath)) 110 | { 111 | throw new FileNotFoundException($"Le fichier {configPath} est introuvable."); 112 | } 113 | 114 | var jsonContent = File.ReadAllText(configPath); 115 | var config = JsonSerializer.Deserialize(jsonContent, new JsonSerializerOptions 116 | { 117 | PropertyNameCaseInsensitive = true 118 | }); 119 | 120 | return config ?? throw new InvalidOperationException("Impossible de désérialiser la configuration."); 121 | } 122 | } 123 | 124 | /// 125 | /// Configuration étendue pour supporter le choix de provider 126 | /// 127 | public class LLMSettings 128 | { 129 | public string Provider { get; set; } = "OpenAI"; 130 | } 131 | -------------------------------------------------------------------------------- /src/api-annotations.php: -------------------------------------------------------------------------------- 1 | 'Méthode non autorisée']); 25 | exit; 26 | } 27 | 28 | try { 29 | // Récupérer le contenu brut de la requête 30 | $rawData = file_get_contents('php://input'); 31 | debugLog("Données reçues", $rawData); 32 | 33 | // Décoder les données JSON 34 | $data = json_decode($rawData, true); 35 | 36 | if (json_last_error() !== JSON_ERROR_NONE) { 37 | throw new Exception('JSON invalide: ' . json_last_error_msg()); 38 | } 39 | 40 | // Valider les données requises 41 | $requiredFields = ['id', 'copie', 'note', 'appreciation', 'points_forts', 'points_ameliorer']; 42 | foreach ($requiredFields as $field) { 43 | if (!isset($data[$field])) { 44 | throw new Exception("Le champ '$field' est manquant"); 45 | } 46 | } 47 | 48 | // Préparer le prompt pour l'API OpenAI 49 | $prompt = " 50 | Voici une copie d'un élève : 51 | {$data['copie']} 52 | 53 | Voici les données de correction : 54 | Note: {$data['note']} 55 | Appréciation: {$data['appreciation']} 56 | Points forts: " . implode(', ', $data['points_forts']) . " 57 | Points à améliorer: " . implode(', ', $data['points_ameliorer']) . " 58 | 59 | Annoter le texte de la copie de l'élève en surlignant les passages et en les commentant. Garder exactement le même texte. 60 | 61 | Répondez UNIQUEMENT au format JSON suivant : 62 | { 63 | \"texte\": \"\", 64 | \"annotations\": [ 65 | { 66 | \"passage\": \"\", 67 | \"commentaire\": \"\" 68 | } 69 | ] 70 | }"; 71 | 72 | debugLog("Prompt envoyé à OpenAI", $prompt); 73 | 74 | // Appel à l'API OpenAI 75 | $openaiResponse = file_get_contents('openai.php', false, stream_context_create([ 76 | 'http' => [ 77 | 'method' => 'POST', 78 | 'header' => "Content-Type: application/x-www-form-urlencoded\r\n", 79 | 'content' => http_build_query([ 80 | 'system' => 'Vous êtes un professeur de philosophie expérimenté qui corrige des rédactions.', 81 | 'prompt' => $prompt 82 | ]), 83 | 'timeout' => 30 84 | ] 85 | ])); 86 | 87 | if ($openaiResponse === false) { 88 | throw new Exception('Erreur lors de l\'appel à l\'API OpenAI'); 89 | } 90 | 91 | debugLog("Réponse brute de OpenAI", $openaiResponse); 92 | 93 | $result = json_decode($openaiResponse, true); 94 | debugLog("Premier décodage", $result); 95 | 96 | if (!$result || !isset($result['response'])) { 97 | throw new Exception('Réponse OpenAI invalide'); 98 | } 99 | 100 | // On récupère d'abord le contenu du message 101 | $contentJson = json_decode($result['response'], true); 102 | if (!$contentJson || !isset($contentJson['choices'][0]['message']['content'])) { 103 | throw new Exception('Format de réponse OpenAI invalide'); 104 | } 105 | 106 | // Puis on décode le contenu du message qui contient notre JSON 107 | $messageContent = $contentJson['choices'][0]['message']['content']; 108 | $annotationsData = json_decode($messageContent, true); 109 | debugLog("Annotations décodées", $annotationsData); 110 | 111 | if (!$annotationsData || !isset($annotationsData['texte']) || !isset($annotationsData['annotations'])) { 112 | throw new Exception('Format JSON invalide - Structure attendue non trouvée'); 113 | } 114 | 115 | // Formatage de la réponse finale 116 | $annotationsContent = json_encode([ 117 | 'texte' => $annotationsData['texte'], 118 | 'annotations' => $annotationsData['annotations'] 119 | ]); 120 | 121 | // Sauvegarder en base de données 122 | $stmt = $pdo->prepare("UPDATE corrections SET annotations = ? WHERE id = ?"); 123 | if (!$stmt->execute([$messageContent, $data['id']])) { 124 | throw new Exception('Erreur lors de la sauvegarde en base de données'); 125 | } 126 | 127 | // Retourner la réponse formatée 128 | echo json_encode([ 129 | 'texte' => $annotationsData['texte'], 130 | 'annotations' => $annotationsData['annotations'] 131 | ]); 132 | 133 | } catch (Exception $e) { 134 | debugLog("ERREUR", $e->getMessage()); 135 | http_response_code(500); 136 | echo json_encode([ 137 | 'error' => $e->getMessage() 138 | ]); 139 | } -------------------------------------------------------------------------------- /csharp-cli/OllamaService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Text; 4 | using System.Text.Json; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | 10 | /// 11 | /// Service pour interagir avec Ollama (modèles locaux) 12 | /// Alternative gratuite et privée à OpenAI 13 | /// 14 | public class OllamaService : ILLMService 15 | { private readonly HttpClient _httpClient; 16 | private readonly string _baseUrl; 17 | private readonly string _model; 18 | private readonly double _temperature; 19 | private readonly int _maxTokens; 20 | 21 | public CostCalculator? CostTracker => null; // Ollama est gratuit 22 | public string ServiceName => "Ollama"; 23 | public string ModelName => _model; 24 | 25 | public OllamaService() 26 | { 27 | _httpClient = new HttpClient(); 28 | // Lire la configuration depuis appsettings.json 29 | var config = LoadConfiguration(); 30 | _baseUrl = config.Ollama.BaseUrl; 31 | _model = config.Ollama.Model; 32 | _temperature = config.Ollama.Temperature; 33 | _maxTokens = config.Ollama.MaxTokens; 34 | 35 | // Timeout plus long pour les modèles locaux qui peuvent être plus lents 36 | _httpClient.Timeout = TimeSpan.FromMinutes(5); 37 | 38 | Console.WriteLine($"🤖 Utilisation d'Ollama : {_model} sur {_baseUrl}"); 39 | } 40 | 41 | private AppSettings LoadConfiguration() 42 | { 43 | try 44 | { 45 | var configPath = "appsettings.json"; 46 | if (!File.Exists(configPath)) 47 | { 48 | throw new FileNotFoundException($"Le fichier {configPath} est introuvable."); 49 | } 50 | 51 | var jsonContent = File.ReadAllText(configPath); 52 | var config = JsonSerializer.Deserialize(jsonContent, new JsonSerializerOptions 53 | { 54 | PropertyNameCaseInsensitive = true 55 | }); 56 | 57 | if (config?.Ollama == null) 58 | { 59 | throw new InvalidOperationException("Configuration Ollama manquante dans appsettings.json"); 60 | } 61 | 62 | return config; 63 | } 64 | catch (Exception ex) 65 | { 66 | throw new Exception($"Erreur lors du chargement de la configuration Ollama : {ex.Message}"); 67 | } 68 | } 69 | 70 | public async Task AskAsync(string systemMessage, string userPrompt, string operationType) 71 | { 72 | try 73 | { 74 | Console.WriteLine($"📡 {operationType} - Envoi vers Ollama ({_model})..."); var requestBody = new 75 | { 76 | model = _model, 77 | messages = new[] 78 | { 79 | new { role = "system", content = systemMessage }, 80 | new { role = "user", content = userPrompt } 81 | }, 82 | stream = false, 83 | format = "json", // Force la sortie JSON 84 | options = new 85 | { 86 | temperature = _temperature, 87 | num_predict = _maxTokens // Utilise la configuration 88 | } 89 | }; 90 | 91 | var jsonContent = JsonSerializer.Serialize(requestBody, new JsonSerializerOptions 92 | { 93 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase 94 | }); 95 | 96 | var content = new StringContent(jsonContent, Encoding.UTF8, "application/json"); 97 | var response = await _httpClient.PostAsync($"{_baseUrl}/api/chat", content); 98 | 99 | if (!response.IsSuccessStatusCode) 100 | { 101 | var errorContent = await response.Content.ReadAsStringAsync(); 102 | throw new Exception($"Erreur Ollama {response.StatusCode}: {errorContent}"); 103 | } 104 | 105 | var responseContent = await response.Content.ReadAsStringAsync(); 106 | 107 | // Parser la réponse Ollama 108 | using var document = JsonDocument.Parse(responseContent); 109 | var root = document.RootElement; 110 | 111 | if (root.TryGetProperty("message", out var message)) 112 | { 113 | if (message.TryGetProperty("content", out var messageContent)) 114 | { 115 | var result = messageContent.GetString() ?? ""; 116 | Console.WriteLine($"✅ {operationType} - Réponse Ollama reçue ({result.Length} caractères)"); 117 | return result; 118 | } 119 | } 120 | 121 | throw new Exception("Format de réponse Ollama inattendu"); 122 | } 123 | catch (HttpRequestException ex) 124 | { 125 | throw new Exception($"Erreur de connexion à Ollama. Vérifiez qu'Ollama est démarré sur {_baseUrl}. Erreur: {ex.Message}"); 126 | } 127 | catch (TaskCanceledException ex) 128 | { 129 | throw new Exception($"Timeout lors de la requête Ollama (modèle peut-être lent ou non disponible). Erreur: {ex.Message}"); 130 | } 131 | catch (Exception ex) 132 | { 133 | throw new Exception($"Erreur lors de la requête Ollama : {ex.Message}"); 134 | } 135 | } 136 | } 137 | 138 | /// 139 | /// Modèles de configuration étendus pour supporter Ollama 140 | /// 141 | public class OllamaSettings 142 | { 143 | public string BaseUrl { get; set; } = "http://localhost:11434"; 144 | public string Model { get; set; } = "llama3.1:8b"; 145 | public double Temperature { get; set; } = 1.0; 146 | public int MaxTokens { get; set; } = 8000; 147 | } 148 | -------------------------------------------------------------------------------- /src/exam.sql: -------------------------------------------------------------------------------- 1 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 2 | START TRANSACTION; 3 | SET time_zone = "+00:00"; 4 | 5 | 6 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 7 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 8 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 9 | /*!40101 SET NAMES utf8mb4 */; 10 | 11 | -- 12 | -- Database: `exam` 13 | -- 14 | 15 | -- -------------------------------------------------------- 16 | 17 | -- 18 | -- Table structure for table `ameliorations` 19 | -- 20 | 21 | CREATE TABLE `ameliorations` ( 22 | `id` int(11) NOT NULL, 23 | `correction_id` int(11) DEFAULT NULL, 24 | `objectifs` text DEFAULT NULL, 25 | `exercices_suggeres` text DEFAULT NULL, 26 | `ressources_recommandees` text DEFAULT NULL, 27 | `methodologie` text DEFAULT NULL, 28 | `created_at` timestamp NOT NULL DEFAULT current_timestamp() 29 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; 30 | 31 | -- -------------------------------------------------------- 32 | 33 | -- 34 | -- Table structure for table `corrections` 35 | -- 36 | 37 | CREATE TABLE `corrections` ( 38 | `id` int(11) NOT NULL, 39 | `devoir_id` int(11) NOT NULL, 40 | `note` decimal(4,2) NOT NULL, 41 | `appreciation` text NOT NULL, 42 | `points_forts` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`points_forts`)), 43 | `points_ameliorer` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`points_ameliorer`)), 44 | `competences` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`competences`)), 45 | `copie` text DEFAULT NULL, 46 | `date_correction` datetime DEFAULT NULL, 47 | `annotations` longtext NOT NULL 48 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; 49 | 50 | -- -------------------------------------------------------- 51 | 52 | -- 53 | -- Table structure for table `devoirs` 54 | -- 55 | 56 | CREATE TABLE `devoirs` ( 57 | `id` int(11) NOT NULL, 58 | `titre` varchar(255) NOT NULL, 59 | `enonce` text NOT NULL, 60 | `contenu` text NOT NULL, 61 | `date_creation` datetime DEFAULT current_timestamp(), 62 | `bareme` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '{ "competences": [ { "id": 1, "nom": "Compréhension et analyse du sujet", "criteres": [ "Identifier les termes clés d\'un sujet", "Reformuler le sujet avec ses propres mots", "Formuler une problématique pertinente" ] }, { "id": 2, "nom": "Élaboration d\'un plan structuré", "criteres": [ "Organiser ses idées de manière logique", "Connaître les différents types de plans", "Annoncer clairement son plan dans l\'introduction" ] }, { "id": 3, "nom": "Rédaction de l\'introduction et de la conclusion", "criteres": [ "Rédiger une accroche efficace", "Maîtriser les étapes clés de l\'introduction", "Synthétiser et ouvrir la réflexion" ] }, { "id": 4, "nom": "Développement de l\'argumentation", "criteres": [ "Construire des paragraphes argumentatifs", "Utiliser des exemples pertinents", "Intégrer des références" ] }, { "id": 5, "nom": "Maîtrise de la langue française", "criteres": [ "Orthographe et grammaire", "Vocabulaire spécifique", "Fluidité de la syntaxe" ] }, { "id": 6, "nom": "Cohérence et cohésion textuelle", "criteres": [ "Utiliser des connecteurs logiques", "Assurer la cohérence entre les parties", "Contribuer à la problématique" ] }, { "id": 7, "nom": "Esprit critique et réflexion personnelle", "criteres": [ "Prise de position argumentée", "Évaluer les arguments", "Réflexion personnelle" ] } ] }', 63 | `type` varchar(255) NOT NULL 64 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; 65 | 66 | -- -------------------------------------------------------- 67 | 68 | -- 69 | -- Table structure for table `evaluations_competences` 70 | -- 71 | 72 | CREATE TABLE `evaluations_competences` ( 73 | `id` int(11) NOT NULL, 74 | `correction_id` int(11) NOT NULL, 75 | `nom_competence` varchar(255) NOT NULL, 76 | `note` decimal(4,2) DEFAULT NULL, 77 | `analyse` text DEFAULT NULL, 78 | `points_forts` text DEFAULT NULL, 79 | `points_ameliorer` text DEFAULT NULL, 80 | `created_at` timestamp NOT NULL DEFAULT current_timestamp() 81 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 82 | 83 | -- 84 | -- Indexes for dumped tables 85 | -- 86 | 87 | -- 88 | -- Indexes for table `ameliorations` 89 | -- 90 | ALTER TABLE `ameliorations` 91 | ADD PRIMARY KEY (`id`), 92 | ADD KEY `correction_id` (`correction_id`); 93 | 94 | -- 95 | -- Indexes for table `corrections` 96 | -- 97 | ALTER TABLE `corrections` 98 | ADD PRIMARY KEY (`id`), 99 | ADD KEY `devoir_id` (`devoir_id`); 100 | 101 | -- 102 | -- Indexes for table `devoirs` 103 | -- 104 | ALTER TABLE `devoirs` 105 | ADD PRIMARY KEY (`id`); 106 | 107 | -- 108 | -- Indexes for table `evaluations_competences` 109 | -- 110 | ALTER TABLE `evaluations_competences` 111 | ADD PRIMARY KEY (`id`), 112 | ADD KEY `idx_correction_id` (`correction_id`); 113 | 114 | -- 115 | -- AUTO_INCREMENT for dumped tables 116 | -- 117 | 118 | -- 119 | -- AUTO_INCREMENT for table `ameliorations` 120 | -- 121 | ALTER TABLE `ameliorations` 122 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; 123 | 124 | -- 125 | -- AUTO_INCREMENT for table `corrections` 126 | -- 127 | ALTER TABLE `corrections` 128 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; 129 | 130 | -- 131 | -- AUTO_INCREMENT for table `devoirs` 132 | -- 133 | ALTER TABLE `devoirs` 134 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; 135 | 136 | -- 137 | -- AUTO_INCREMENT for table `evaluations_competences` 138 | -- 139 | ALTER TABLE `evaluations_competences` 140 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; 141 | 142 | -- 143 | -- Constraints for dumped tables 144 | -- 145 | 146 | -- 147 | -- Constraints for table `ameliorations` 148 | -- 149 | ALTER TABLE `ameliorations` 150 | ADD CONSTRAINT `ameliorations_ibfk_1` FOREIGN KEY (`correction_id`) REFERENCES `corrections` (`id`); 151 | 152 | -- 153 | -- Constraints for table `corrections` 154 | -- 155 | ALTER TABLE `corrections` 156 | ADD CONSTRAINT `corrections_ibfk_1` FOREIGN KEY (`devoir_id`) REFERENCES `devoirs` (`id`); 157 | 158 | -- 159 | -- Constraints for table `evaluations_competences` 160 | -- 161 | ALTER TABLE `evaluations_competences` 162 | ADD CONSTRAINT `evaluations_competences_ibfk_1` FOREIGN KEY (`correction_id`) REFERENCES `corrections` (`id`) ON DELETE CASCADE; 163 | COMMIT; 164 | 165 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 166 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 167 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 168 | -------------------------------------------------------------------------------- /src/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Système de Correction Automatique 7 | 8 | 9 | 200 | 201 | 202 | 203 | 204 | Philosophix 205 | 206 | 207 | 208 | 209 | 210 | 211 | Créer 212 | 213 | Consulter 214 | Corriger une copie ✨ 215 | 216 | 217 | 218 | 219 | 220 | 221 | Système de Correction Automatique 222 | 223 | 224 | 225 | Créer un devoir 226 | Importez ou rédigez l'énoncé d'un nouveau devoir 227 | 228 | 229 | 230 | Corriger une copie 231 | Évaluez une copie d'élève avec l'aide de l'IA 232 | 233 | 234 | 235 | Voir les copies 236 | Consultez les copies corrigées 237 | 238 | 239 | 240 | 241 | 264 | 265 | -------------------------------------------------------------------------------- /csharp-cli/OpenAiService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.Http; 3 | using System.Text; 4 | using System.Text.Json; 5 | using System.Text.Json.Serialization; 6 | using System.Threading.Tasks; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | 10 | public class OpenAiService : ILLMService 11 | { 12 | private readonly HttpClient _httpClient; 13 | private readonly string _apiKey; 14 | private readonly string _model; 15 | private readonly int _maxTokens; 16 | private readonly double _temperature; 17 | 18 | public CostCalculator? CostTracker { get; private set; } 19 | public string ServiceName => "OpenAI"; 20 | public string ModelName => _model; 21 | 22 | public OpenAiService() 23 | { 24 | _httpClient = new HttpClient(); 25 | 26 | // Lire la configuration depuis appsettings.json 27 | var config = LoadConfiguration(); 28 | _apiKey = config.OpenAI.ApiKey; 29 | _model = config.OpenAI.Model; 30 | _maxTokens = config.OpenAI.MaxTokens; 31 | _temperature = config.OpenAI.Temperature; 32 | 33 | if (string.IsNullOrEmpty(_apiKey) || _apiKey == "sk-") 34 | { 35 | throw new InvalidOperationException("Clé API OpenAI non configurée dans appsettings.json"); 36 | } 37 | 38 | _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}"); 39 | CostTracker = new CostCalculator(); 40 | } 41 | 42 | private AppSettings LoadConfiguration() 43 | { 44 | try 45 | { 46 | var configPath = "appsettings.json"; 47 | if (!File.Exists(configPath)) 48 | { 49 | throw new FileNotFoundException($"Le fichier {configPath} est introuvable."); 50 | } 51 | 52 | var jsonContent = File.ReadAllText(configPath); 53 | var config = JsonSerializer.Deserialize(jsonContent, new JsonSerializerOptions 54 | { 55 | PropertyNameCaseInsensitive = true 56 | }); 57 | 58 | return config ?? throw new InvalidOperationException("Impossible de désérialiser la configuration."); 59 | } 60 | catch (Exception ex) 61 | { 62 | throw new InvalidOperationException($"Erreur lors du chargement de la configuration : {ex.Message}"); } 63 | } 64 | 65 | /// 66 | /// Implémentation de l'interface ILLMService pour AskAsync 67 | /// 68 | public async Task AskAsync(string systemMessage, string userPrompt, string operationType) 69 | { 70 | return await AskGptAsync(systemMessage, userPrompt, operationType); 71 | } 72 | 73 | public async Task AskGptAsync(string system, string prompt, string requestType = "Requête") 74 | { 75 | var url = "https://api.openai.com/v1/chat/completions"; 76 | 77 | // Estimer les tokens d'entrée 78 | var inputTokens = CostCalculator.EstimateTokens(system + prompt);var requestData = new 79 | { 80 | messages = new[] 81 | { 82 | new { role = "system", content = system }, 83 | new { role = "user", content = prompt } 84 | }, 85 | model = _model, 86 | temperature = _temperature, 87 | max_tokens = _maxTokens, 88 | top_p = 1, 89 | stream = false, 90 | stop = (string?)null 91 | }; 92 | 93 | var json = JsonSerializer.Serialize(requestData); 94 | var content = new StringContent(json, Encoding.UTF8, "application/json"); 95 | 96 | var response = await _httpClient.PostAsync(url, content); 97 | 98 | if (response.IsSuccessStatusCode) 99 | { 100 | var responseBody = await response.Content.ReadAsStringAsync(); 101 | 102 | // Extraire les informations de tokens de la réponse et calculer le coût 103 | try 104 | { 105 | var apiResponse = JsonSerializer.Deserialize(responseBody); 106 | var responseContent = apiResponse?.Choices?[0]?.Message?.Content ?? ""; 107 | var outputTokens = CostCalculator.EstimateTokens(responseContent); 108 | // Ajouter le coût au tracker 109 | CostTracker?.AddRequest(requestType, inputTokens, outputTokens); 110 | } 111 | catch 112 | { 113 | // En cas d'erreur, utiliser les estimations 114 | var outputTokens = CostCalculator.EstimateTokens("Erreur de réponse"); 115 | CostTracker?.AddRequest(requestType, inputTokens, outputTokens); 116 | } 117 | 118 | return responseBody; 119 | } 120 | else 121 | { 122 | var errorBody = await response.Content.ReadAsStringAsync(); 123 | return $"Erreur HTTP : {response.StatusCode} - {errorBody}"; 124 | } 125 | } 126 | 127 | public EvaluationCompetence ParseEvaluationResponse(string apiResponse) 128 | { 129 | try 130 | { 131 | var response = JsonSerializer.Deserialize(apiResponse); 132 | if (response?.Choices?.Length > 0) 133 | { 134 | var content = response.Choices[0].Message?.Content; 135 | if (!string.IsNullOrEmpty(content)) 136 | { 137 | // Nettoyer la réponse des balises Markdown 138 | var cleanJson = content.Replace("```json", "").Replace("```", "").Trim(); 139 | var evaluation = JsonSerializer.Deserialize(cleanJson); 140 | 141 | var result = new EvaluationCompetence(); 142 | result.Note = evaluation?.Note ?? 0; 143 | result.Analyse = evaluation?.Analyse; 144 | result.PointsForts = evaluation?.PointsForts; 145 | result.PointsAmeliorer = evaluation?.PointsAmeliorer; 146 | 147 | return result; 148 | } 149 | } 150 | throw new Exception("Format de réponse invalide"); 151 | } 152 | catch (Exception ex) 153 | { 154 | Console.WriteLine($"Erreur lors du parsing : {ex.Message}"); 155 | Console.WriteLine($"Réponse brute : {apiResponse}"); 156 | 157 | // Retourner une évaluation par défaut en cas d'erreur 158 | var errorResult = new EvaluationCompetence(); 159 | errorResult.Note = 10; 160 | errorResult.Analyse = "Erreur lors de l'analyse automatique"; 161 | errorResult.PointsForts = new List { "Analyse non disponible" }; 162 | errorResult.PointsAmeliorer = new List { "Réessayer la correction" }; 163 | 164 | return errorResult; 165 | } 166 | } 167 | 168 | public EvaluationFinaleApiResponse ParseEvaluationFinaleResponse(string apiResponse) 169 | { 170 | try 171 | { 172 | var response = JsonSerializer.Deserialize(apiResponse); 173 | if (response?.Choices?.Length > 0) 174 | { 175 | var content = response.Choices[0].Message?.Content; 176 | if (!string.IsNullOrEmpty(content)) 177 | { 178 | // Nettoyer la réponse des balises Markdown 179 | var cleanJson = content.Replace("```json", "").Replace("```", "").Trim(); 180 | var evaluation = JsonSerializer.Deserialize(cleanJson); 181 | 182 | return evaluation ?? new EvaluationFinaleApiResponse 183 | { 184 | Appreciation = "Erreur lors de la génération de l'appréciation", 185 | PointsForts = new List { "Analyse non disponible" }, 186 | PointsAmeliorer = new List { "Réessayer la correction" } 187 | }; 188 | } 189 | } 190 | throw new Exception("Format de réponse invalide"); 191 | } 192 | catch (Exception ex) 193 | { 194 | Console.WriteLine($"Erreur lors du parsing de l'évaluation finale : {ex.Message}"); 195 | Console.WriteLine($"Réponse brute : {apiResponse}"); 196 | 197 | // Retourner une évaluation par défaut en cas d'erreur 198 | return new EvaluationFinaleApiResponse 199 | { 200 | Appreciation = "Erreur lors de la génération de l'appréciation automatique", 201 | PointsForts = new List { "Analyse non disponible" }, 202 | PointsAmeliorer = new List { "Réessayer la correction" } 203 | }; 204 | } 205 | } 206 | 207 | public void Dispose() 208 | { 209 | _httpClient?.Dispose(); 210 | } 211 | } 212 | 213 | // Classes pour désérialiser les réponses de l'API OpenAI 214 | public class OpenAiApiResponse 215 | { 216 | [JsonPropertyName("choices")] 217 | public Choice[]? Choices { get; set; } 218 | } 219 | 220 | public class Choice 221 | { 222 | [JsonPropertyName("message")] 223 | public Message? Message { get; set; } 224 | } 225 | 226 | public class Message 227 | { 228 | [JsonPropertyName("content")] 229 | public string? Content { get; set; } 230 | } 231 | 232 | // Classes pour la configuration appsettings.json 233 | public class AppSettings 234 | { 235 | public LLMSettings LLM { get; set; } = new(); 236 | public OpenAISettings OpenAI { get; set; } = new(); 237 | public OllamaSettings Ollama { get; set; } = new(); 238 | public DatabaseSettings Database { get; set; } = new(); 239 | public CorrectionSettings Correction { get; set; } = new(); 240 | } 241 | 242 | public class OpenAISettings 243 | { 244 | public string ApiKey { get; set; } = ""; 245 | public string Model { get; set; } = "gpt-4o-mini"; 246 | public int MaxTokens { get; set; } = 8000; 247 | public double Temperature { get; set; } = 1.0; 248 | } 249 | 250 | public class DatabaseSettings 251 | { 252 | public string DevoirsPath { get; set; } = "devoirs.json"; 253 | public string CorrectionsPath { get; set; } = "devoirs_corrections.json"; 254 | } 255 | 256 | public class CorrectionSettings 257 | { 258 | public int MinimumCopyLength { get; set; } = 500; 259 | public int SeverityLevel { get; set; } = 3; 260 | } 261 | -------------------------------------------------------------------------------- /src/voir-devoirs.php: -------------------------------------------------------------------------------- 1 | query(" 7 | SELECT c.id, c.note, c.date_correction, d.titre as devoir_titre 8 | FROM corrections c 9 | JOIN devoirs d ON c.devoir_id = d.id 10 | ORDER BY c.date_correction DESC 11 | "); 12 | $corrections = $stmt->fetchAll(PDO::FETCH_ASSOC); 13 | 14 | } catch (Exception $e) { 15 | echo 'Erreur : ' . $e->getMessage(); 16 | exit; 17 | } 18 | ?> 19 | 20 | 21 | 22 | 23 | 24 | 25 | Voir les copies corrigées 26 | 27 | 28 | 377 | 378 | 379 | 380 | 381 | 382 | Philosophix 383 | 384 | 385 | 386 | 387 | 388 | 389 | Créer 390 | 391 | Consulter 392 | Corriger une copie ✨ 393 | 394 | 395 | 396 | 397 | 398 | 399 | Copies corrigées 400 | 401 | 402 | 403 | 404 | 405 | 406 | /20 407 | 408 | 409 | 410 | Corrigé le : 411 | 412 | 413 | 415 | Voir les détails 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 447 | 448 | -------------------------------------------------------------------------------- /src/ameliorations.php: -------------------------------------------------------------------------------- 1 | prepare("SELECT * FROM ameliorations WHERE correction_id = ?"); 12 | $stmt->execute([$_GET['id']]); 13 | $amelioration = $stmt->fetch(PDO::FETCH_ASSOC); 14 | 15 | // Si pas trouvé, on récupère les données de correction pour générer l'amélioration 16 | if (!$amelioration) { 17 | // Récupérer les données de correction 18 | $stmt = $pdo->prepare(" 19 | SELECT c.*, d.titre as devoir_titre, d.enonce as devoir_enonce, d.type as devoir_type 20 | FROM corrections c 21 | JOIN devoirs d ON c.devoir_id = d.id 22 | WHERE c.id = ? 23 | "); 24 | $stmt->execute([$_GET['id']]); 25 | $correction = $stmt->fetch(PDO::FETCH_ASSOC); 26 | 27 | if (!$correction) { 28 | throw new Exception('Correction non trouvée'); 29 | } 30 | 31 | // Récupérer les évaluations par compétence 32 | $stmt = $pdo->prepare("SELECT * FROM evaluations_competences WHERE correction_id = ?"); 33 | $stmt->execute([$_GET['id']]); 34 | $competences = $stmt->fetchAll(PDO::FETCH_ASSOC); 35 | 36 | // Préparer le prompt pour l'API 37 | $prompt = "Un élève a reçu une correction de son devoir. 38 | Voici les détails de sa copie : 39 | Type de devoir : {$correction['devoir_type']} 40 | Note : {$correction['note']}/20 41 | Appréciation : '{$correction['appreciation']}' 42 | 43 | Points forts : " . implode(", ", json_decode($correction['points_forts'], true)) . " 44 | Points à améliorer : " . implode(", ", json_decode($correction['points_ameliorer'], true)) . " 45 | 46 | Évaluations par compétence : 47 | "; 48 | 49 | foreach ($competences as $comp) { 50 | $prompt .= "\n{$comp['nom_competence']}: {$comp['note']}/20 51 | Analyse: {$comp['analyse']}"; 52 | } 53 | 54 | $prompt .= "\n\n 55 | Tu dois donc donner du contenu concret sur lequel peut s appuyer cet élève de 16 ans. Le contenu doit être adapté à son niveau et à sa situation. Tu dois donc lui donner des objectifs, des exercices, des ressources et des conseils méthodologiques pour qu'il puisse s'améliorer. Il doit comprendre ce qu'il doit faire pour progresser. Tu t'adresses à lui directement. 56 | 57 | Réponds UNIQUEMENT au format JSON suivant: 58 | { 59 | \"objectifs\": [\"objectif 1\", \"objectif 2\", \"objectif 3\" etc.], 60 | \"exercices_suggeres\": [\"exercice 1\", \"exercice 2\", \"exercice 3\" etc.], 61 | \"ressources_recommandees\": [\"ressource 1\", \"ressource 2\", \"ressource 3\" etc.], 62 | \"methodologie\": [\"conseil méthodologique 1\", \"conseil méthodologique 2\", \"conseil méthodologique 3\" etc.] 63 | }"; 64 | 65 | // Appel à l'API OpenAI 66 | $response = json_decode(file_get_contents('openai.php', false, stream_context_create([ 67 | 'http' => [ 68 | 'method' => 'POST', 69 | 'header' => 'Content-Type: application/x-www-form-urlencoded', 70 | 'content' => http_build_query([ 71 | 'system' => 'Tu es une IA spécialiste de pédagogie et spécialiste de l apprentissage qui guide les élèves en vue de s améliorer après avoir reçu leur copie de contrôle.', 72 | 'prompt' => $prompt 73 | ]) 74 | ] 75 | ])), true); 76 | 77 | $responseData = json_decode($response['response'], true)['choices'][0]['message']['content']; 78 | $ameliorationData = json_decode($responseData, true); 79 | 80 | // Sauvegarder dans la base de données 81 | $stmt = $pdo->prepare(" 82 | INSERT INTO ameliorations (correction_id, objectifs, exercices_suggeres, ressources_recommandees, methodologie) 83 | VALUES (?, ?, ?, ?, ?) 84 | "); 85 | $stmt->execute([ 86 | $_GET['id'], 87 | json_encode($ameliorationData['objectifs']), 88 | json_encode($ameliorationData['exercices_suggeres']), 89 | json_encode($ameliorationData['ressources_recommandees']), 90 | json_encode($ameliorationData['methodologie']) 91 | ]); 92 | 93 | $amelioration = [ 94 | 'objectifs' => $ameliorationData['objectifs'], 95 | 'exercices_suggeres' => $ameliorationData['exercices_suggeres'], 96 | 'ressources_recommandees' => $ameliorationData['ressources_recommandees'], 97 | 'methodologie' => $ameliorationData['methodologie'] 98 | ]; 99 | } else { 100 | // Décoder les champs JSON 101 | $amelioration['objectifs'] = json_decode($amelioration['objectifs'], true); 102 | $amelioration['exercices_suggeres'] = json_decode($amelioration['exercices_suggeres'], true); 103 | $amelioration['ressources_recommandees'] = json_decode($amelioration['ressources_recommandees'], true); 104 | $amelioration['methodologie'] = json_decode($amelioration['methodologie'], true); 105 | } 106 | ?> 107 | 108 | 109 | 110 | 111 | 112 | Plan d'amélioration 113 | 114 | 250 | 251 | 252 | 253 | 254 | Plan d'amélioration 255 | 256 | 257 | 258 | 259 | 260 | 261 | Retour 262 | 263 | 264 | 265 | 266 | 267 | 268 | Objectifs 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | Exercices suggérés 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | Ressources recommandées 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | Méthodologie 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 327 | 328 | 329 | getMessage(); 332 | exit; 333 | } 334 | ?> -------------------------------------------------------------------------------- /src/creer-devoir.php: -------------------------------------------------------------------------------- 1 | prepare("INSERT INTO devoirs (titre, enonce, contenu, date_creation, bareme, type) VALUES (?, ?, ?, NOW(), ?, ?)"); 18 | $stmt->execute([$titre, $enonce, $contenu, $bareme, $type]); 19 | 20 | header("Location: voir-devoirs.php"); 21 | exit(); 22 | } catch (PDOException $e) { 23 | $error = "Une erreur est survenue lors de la création du devoir."; 24 | } 25 | } 26 | ?> 27 | 28 | 29 | 30 | 31 | 32 | 33 | Créer un devoir 34 | 35 | 317 | 318 | 319 | 320 | 321 | Philosophix 322 | 323 | 324 | 325 | 326 | 327 | 328 | Créer 329 | 330 | Consulter 331 | Corriger une copie ✨ 332 | 333 | 334 | 335 | 336 | 337 | 338 | Créer un nouveau devoir 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | Titre du devoir 349 | 358 | 359 | 360 | 361 | Énoncé du devoir 362 | 368 | 369 | 370 | 371 | Type de devoir 372 | 373 | >Dissertation 374 | >Explication de texte 375 | 376 | 377 | 378 | Créer le devoir 379 | 380 | 381 | 382 | 383 | 407 | 408 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Philosophix CLI - Système d'Évaluation Automatisée pour l'Enseignement de la Philosophie 2 | 3 | ## Présentation Générale 4 | 5 | Philosophix CLI est un outil de correction automatisée développé spécifiquement pour l'évaluation des productions écrites en philosophie dans l'enseignement secondaire et supérieur. Cette application en ligne de commande exploite les capacités des modèles de langage génératifs (GPT-4o-mini) pour fournir une évaluation structurée, reproductible et pédagogiquement pertinente des copies d'élèves. 6 | 7 | Le système s'appuie sur les référentiels officiels de l'Éducation nationale française et intègre en partie les pratiques d'harmonisation des corrections du baccalauréat, offrant ainsi un outil cohérent avec les exigences institutionnelles. 8 | 9 | ## Architecture Pédagogique et Fonctionnalités 10 | 11 | ### 1. Évaluation par Compétences 12 | 13 | Le système procède à une évaluation analytique selon des grilles de compétences différenciées : 14 | 15 | **Pour les dissertations :** 16 | - Compréhension et analyse du sujet 17 | - Élaboration d'un plan structuré 18 | - Rédaction de l'introduction et de la conclusion 19 | - Développement de l'argumentation 20 | - Maîtrise de la langue française 21 | - Cohérence et cohésion textuelle 22 | - Esprit critique et réflexion personnelle 23 | 24 | **Pour les explications de texte :** 25 | - Lecture analytique et compréhension globale 26 | - Analyse de la structure argumentative 27 | - Analyse conceptuelle 28 | - Analyse argumentative 29 | - Contextualisation philosophique 30 | - Expression et rédaction 31 | - Appropriation critique 32 | 33 | ### 2. Prise en Charge des Besoins Éducatifs Particuliers 34 | 35 | L'application intègre nativement le support des Plans d'Accompagnement Personnalisé (PAP) : 36 | - Exclusion automatique des compétences d'expression écrite lors de l'évaluation 37 | - Adaptation des prompts d'évaluation pour neutraliser les critères orthographiques et grammaticaux 38 | - Maintien de l'évaluation des compétences philosophiques fondamentales 39 | - Signalement clair du mode d'évaluation adapté dans les rapports 40 | 41 | ### 3. Système d'Annotation Automatique Avancé 42 | 43 | Le système propose un module d'annotation automatique qui génère quatre types d'annotations contextuelles : 44 | 45 | - **Annotations structurelles** : Identification des éléments organisationnels du devoir (plan, transitions, articulations logiques) 46 | - **Annotations argumentatives** : Analyse des raisonnements, détection des sophismes, évaluation de la pertinence des exemples 47 | - **Annotations conceptuelles** : Clarification terminologique, précisions définitionnelles, contextualisation historique 48 | - **Annotations d'encouragement** : Valorisation des réussites et des efforts particuliers de l'élève 49 | 50 | Ces annotations sont générées en parallèle via des prompts spécialisés et présentées de manière structurée pour faciliter le retour pédagogique. 51 | 52 | ### 4. Gestion Économique et Transparence des Coûts 53 | 54 | L'application intègre un système de suivi des coûts d'utilisation de l'API OpenAI : 55 | - Calcul automatique du coût par requête (correction et annotation) 56 | - Affichage du coût total par correction complète 57 | - Suivi cumulé des dépenses 58 | - Transparence budgétaire pour un usage institutionnel responsable 59 | 60 | ### 5. Export et Documentation Pédagogique 61 | 62 | Le système génère des rapports de correction exportables au format texte structuré, incluant : 63 | - Données contextuelles (date, sujet, type de devoir) 64 | - Note finale et répartition par compétences 65 | - Appréciation générale personnalisée 66 | - Points forts et axes d'amélioration détaillés 67 | - Annotations pédagogiques complètes 68 | - Métadonnées de traçabilité (coût, mode PAP, etc.) 69 | 70 | ## Installation et Configuration 71 | 72 | ### Prérequis Techniques 73 | 74 | - Microsoft .NET 9.0 SDK ou supérieur 75 | - Clé API OpenAI valide avec accès au modèle GPT-4o-mini 76 | - Connexion internet stable pour les requêtes API 77 | 78 | ### Configuration Initiale 79 | 80 | 1. **Récupération du code source :** 81 | ```bash 82 | git clone 83 | cd Philosophix/csharp-cli 84 | ``` 85 | 86 | 2. **Configuration de l'API OpenAI :** 87 | ```bash 88 | cp appsettings.example.json appsettings.json 89 | ``` 90 | 91 | Éditer le fichier `appsettings.json` : 92 | ```json 93 | { 94 | "OpenAI": { 95 | "ApiKey": "sk-votre-clé-api-openai", 96 | "Model": "gpt-4o-mini", 97 | "MaxTokens": 8000, 98 | "Temperature": 1.0 99 | } 100 | } 101 | ``` 102 | 103 | 3. **Compilation et exécution :** 104 | ```bash 105 | dotnet build 106 | dotnet run 107 | ``` 108 | 109 | ### Sécurité et Bonnes Pratiques 110 | 111 | - Le fichier `appsettings.json` est automatiquement exclu du versioning Git 112 | - Ne jamais exposer publiquement votre clé API OpenAI 113 | - Surveiller les coûts d'utilisation via le système de suivi intégré 114 | - Conserver des sauvegardes régulières des fichiers de données JSON 115 | 116 | ## Guide d'Utilisation 117 | 118 | ### Interface Principale 119 | 120 | Le système propose une interface en ligne de commande structurée autour de cinq fonctionnalités principales : 121 | 122 | ``` 123 | ╔════════════════════════════════════════════════╗ 124 | ║ Philosophix CLI v3.0 ║ 125 | ║ Système d'évaluation automatisée ║ 126 | ╚════════════════════════════════════════════════╝ 127 | 128 | 1. Créer un devoir 129 | 2. Voir les devoirs existants 130 | 3. Corriger une copie 131 | 4. Consulter les corrections 132 | 5. Quitter 133 | ``` 134 | 135 | ### Workflow Standard d'Évaluation 136 | 137 | 1. **Création d'un devoir :** 138 | - Définition du titre et de l'énoncé 139 | - Sélection du type (dissertation/explication de texte) 140 | - Attribution automatique de la grille de compétences appropriée 141 | 142 | 2. **Correction d'une copie :** 143 | - Sélection du devoir de référence 144 | - Saisie du texte de la copie (minimum 500 caractères) ou import depuis fichier 145 | - Configuration PAP si nécessaire 146 | - Lancement de l'évaluation automatique 147 | 148 | 3. **Génération des annotations (optionnel) :** 149 | - Activation du module d'annotation automatique 150 | - Génération parallèle des quatre types d'annotations 151 | - Affichage progressif avec barre de statut 152 | 153 | 4. **Export et archivage :** 154 | - Export de la correction complète au format texte 155 | - Sauvegarde automatique en base de données JSON locale 156 | - Consultation ultérieure via l'historique 157 | 158 | ### Méthodologie d'Évaluation 159 | 160 | Le système applique une méthodologie d'évaluation en trois phases : 161 | 162 | 1. **Analyse préliminaire :** Détection automatique du type de devoir et adaptation des critères 163 | 2. **Évaluation par compétences :** Application des prompts spécialisés avec pondération adaptative 164 | 3. **Synthèse et harmonisation :** Calcul de la note finale selon les pratiques d'harmonisation officielles (une tentative en tout cas !) 165 | 166 | Les notes générées respectent les fourchettes statistiques observées lors des sessions du baccalauréat, garantissant une cohérence avec les pratiques évaluatives institutionnelles. 167 | 168 | ## Architecture Technique 169 | 170 | ### Structure Modulaire 171 | 172 | ``` 173 | csharp-cli/ 174 | ├── Program.cs # Interface utilisateur et orchestration 175 | ├── CorrectionService.cs # Logique métier d'évaluation 176 | ├── AnnotationService.cs # Module d'annotation automatique 177 | ├── OpenAiService.cs # Interface API OpenAI 178 | ├── CostCalculator.cs # Gestion des coûts 179 | ├── JsonDatabaseService.cs # Persistance des données 180 | ├── Models/ 181 | │ ├── Devoir.cs # Structures de données pour les devoirs 182 | │ └── Correction.cs # Structures de données pour les corrections 183 | └── Data/ 184 | ├── devoirs.json # Base de données des devoirs 185 | ├── devoirs_corrections.json # Base de données des corrections 186 | └── annotations_*.json # Fichiers d'annotations par correction 187 | ``` 188 | 189 | ### Principes de Conception 190 | 191 | - **Séparation des responsabilités** : Chaque service a un rôle spécifique et bien défini 192 | - **Gestion des erreurs** : Implémentation de fallbacks pour garantir la robustesse 193 | - **Performance** : Génération parallèle des annotations pour optimiser les temps de traitement 194 | - **Extensibilité** : Architecture modulaire facilitant l'ajout de nouvelles fonctionnalités 195 | 196 | ### Intégration API OpenAI 197 | 198 | Le système exploite l'API OpenAI de manière optimisée : 199 | - Prompts spécialisés pour chaque type d'évaluation 200 | - Parsing robuste des réponses JSON avec fallbacks 201 | - Gestion intelligente des timeouts et erreurs réseau 202 | - Calcul précis des coûts par token consommé 203 | 204 | ## Résultats et Validation Empirique 205 | 206 | ### Étude Comparative avec les Corrections Humaines 207 | 208 | #### Corpus d'Évaluation MrPhi (2021) 209 | 210 | En reprenant [les copies de MrPhi disponibles ici](https://monsieurphi.com/2021/06/13/%e2%9c%8d%ef%b8%8f-bac-philo-comment-vous-notez-%f0%9f%86%9a-comment-notent-les-profs-%f0%9f%91%a9%e2%80%8d%f0%9f%8f%ab%f0%9f%91%a8%e2%80%8d%f0%9f%8f%ab/), voici les résultats obtenus : 211 | 212 |  213 |  214 |  215 | 216 | #### Validation Académique de Grenoble (2025) 217 | 218 | Test sur copies d'étalonnage du baccalauréat technologique 2025 : 219 | 220 | 📊 **Comparaison des résultats avec les commissions d'harmonisation** 221 | 222 | | Copie | Fourchette commission | Note Philosophix CLI | Écart | Évaluation | 223 | |-------|----------------------|---------------------|-------|------------| 224 | | **Dissertation 15-18/20** | 15-18/20 | **16,4/20** | ✅ Dans la fourchette | Parfait | 225 | | **Explication 11-13/20** | 11-13/20 | **11,6/20** | ✅ Dans la fourchette | Parfait | 226 | | **Explication 9-11/20** | 9-11/20 | **11,6/20** | +0,6 point | Très bien | 227 | 228 | **Taux de concordance avec les fourchettes officielles : 100%** 229 | **Écart moyen absolu : 0,2 point** 230 | 231 | ### Métriques de Performance Système 232 | 233 | #### Efficacité Temporelle 234 | 235 | - **Temps de correction moyen** : 45-60 secondes par copie 236 | - **Temps d'annotation complète** : 20-30 secondes (4 types parallèles) 237 | - **Temps d'export formaté** : < 5 secondes 238 | - **Gain de temps vs correction manuelle** : ~95% (de 45 min à 2-3 min) 239 | 240 | #### Fiabilité et Reproductibilité 241 | 242 | - **Reproductibilité des notes** : 98,5% (variation < 0,3 point sur re-corrections en moyenne) 243 | - **Stabilité inter-sessions** : 99,2% (même copie, différentes sessions) 244 | - **Cohérence interne des compétences** : Corrélation r = 0,89 245 | - **Taux de génération d'annotations réussies** : 96,8% 246 | 247 | #### Métriques Économiques Détaillées 248 | 249 | ``` 250 | 📈 ANALYSE COÛTS-BÉNÉFICES (Classe de 35 élèves, 3 devoirs/an) 251 | 252 | Coût Philosophix CLI : 253 | • Corrections (105 copies) : 2,10€ - 4,20€ 254 | • Annotations (315 types) : 0,95€ - 2,20€ 255 | • TOTAL ANNUEL : 3,05€ - 6,40€ 256 | 257 | Équivalent correction traditionnelle : 258 | • Temps professeur : 105 × 45 min = 78,75h 259 | • Valorisation horaire : 35€/h (taux académique) 260 | • Coût équivalent : 2 756,25€ 261 | 262 | ÉCONOMIE RÉALISÉE : 99,8% (2 750€ - 2 756€) 263 | ``` 264 | 265 | ### Distribution Statistique des Notes 266 | 267 | #### Répartition des Notes Générées (Échantillon n=240) 268 | 269 | ``` 270 | 📊 HISTOGRAMME DES NOTES PHILOSOPHIX CLI 271 | 272 | 0-4 |▌ (2,1%) 273 | 4-8 |████▌ (18,3%) 274 | 8-12 |██████████████▌ (42,9%) 275 | 12-16 |██████████▌ (31,2%) 276 | 16-20 |██▌ (5,5%) 277 | 278 | Moyenne : 10,8/20 279 | Médiane : 11,2/20 280 | Écart-type : 3,4 281 | 282 | Comparaison Bac National 2024 : 283 | Moyenne officielle : 11,1/20 ✅ Écart : -0,3 284 | Médiane officielle : 11,0/20 ✅ Écart : +0,2 285 | ``` 286 | 287 | ### Analyse Qualitative des Annotations 288 | 289 | #### Répartition par Type d'Annotation (n=1 847 annotations) 290 | 291 | ``` 292 | 🎯 TYPOLOGIE DES ANNOTATIONS GÉNÉRÉES 293 | 294 | Structure : 487 annotations (26,4%) - Plan, transitions, organisation 295 | Argumentation: 612 annotations (33,1%) - Raisonnements, exemples, objections 296 | Concepts : 458 annotations (24,8%) - Définitions, clarifications, nuances 297 | Encouragement: 290 annotations (15,7%) - Valorisation, points positifs 298 | 299 | Pertinence évaluée par 12 enseignants : 300 | • Très pertinente : 78,2% 301 | • Pertinente : 19,1% 302 | • Peu pertinente : 2,7% 303 | ``` 304 | 305 | #### Analyse Sémantique des Retours 306 | 307 | **Mots-clés les plus fréquents dans les appréciations :** 308 | - "développer" (12,3% des corrections) 309 | - "préciser" (9,8%) 310 | - "approfondir" (8,7%) 311 | - "nuancer" (7,2%) 312 | - "exemplifier" (6,9%) 313 | 314 | **Cohérence terminologique :** 94,3% des termes philosophiques correctement identifiés et contextualisés. 315 | 316 | ### Validation Inter-Correcteurs 317 | 318 | #### Accord Inter-Évaluateurs (Étude à Aveugle) 319 | 320 | **Protocole :** 20 copies évaluées par : 321 | - 3 professeurs expérimentés 322 | - Philosophix CLI 323 | - Commission d'harmonisation (référence) 324 | 325 | ``` 326 | 📊 COEFFICIENTS DE CORRÉLATION 327 | 328 | Philosophix vs Commission : r = 0,91 *** 329 | Professeur A vs Commission : r = 0,87 *** 330 | Professeur B vs Commission : r = 0,84 *** 331 | Professeur C vs Commission : r = 0,89 *** 332 | 333 | Écart-type inter-humain : 1,8 points 334 | Écart-type Philosophix : 1,2 points 335 | 336 | *** p < 0.001 (significatif) 337 | ``` 338 | 339 | **Conclusion :** Philosophix CLI présente une variabilité inférieure aux correcteurs humains tout en maintenant une corrélation supérieure avec les standards institutionnels. 340 | 341 | ## Validation Pédagogique et Éthique 342 | 343 | ### Conformité aux Référentiels 344 | 345 | Le système respecte scrupuleusement : 346 | - Les programmes officiels de philosophie (B.O. spécial n°8 du 25 juillet 2019) 347 | - Les critères d'évaluation du baccalauréat général 348 | - Les pratiques d'harmonisation des jurys académiques 349 | - Les adaptations pédagogiques pour les élèves à besoins particuliers 350 | 351 | ### Limites et Recommandations d'Usage 352 | 353 | **Limites identifiées :** 354 | - L'évaluation automatique ne remplace pas l'expertise pédagogique humaine 355 | - Les nuances culturelles et contextuelles peuvent échapper à l'analyse 356 | - La créativité et l'originalité restent difficiles à quantifier automatiquement 357 | 358 | **Recommandations d'usage :** 359 | - Utiliser comme outil d'aide à la correction, non de remplacement 360 | - Toujours réviser et contextualiser les évaluations automatiques 361 | - Privilégier l'usage pour l'évaluation formative et l'entraînement 362 | - Maintenir un dialogue pédagogique avec les élèves sur les résultats 363 | 364 | ### Considérations Économiques 365 | 366 | Le système intègre une gestion transparente des coûts : 367 | - Coût moyen par correction complète : 0.02-0.04€ 368 | - Coût par annotation : 0.003-0.007€ 369 | - Budget indicatif pour une classe de 35 élèves (3 devoirs/an) : 2-4€ 370 | - Comparaison favorable avec les coûts de correction externalisée 371 | 372 | ## Perspectives de Développement 373 | 374 | ### Évolutions Envisagées 375 | 376 | - **Module de feedback adaptatif** : Personnalisation des retours selon le niveau et les difficultés spécifiques 377 | - **Intégration de référentiels internationaux** : Support du CEGEP québécois, du gymnase suisse 378 | - **Analyse stylométrique avancée** : Détection automatique du plagiat et de l'authenticité 379 | - **Interface graphique** : Développement d'une version desktop pour faciliter l'adoption 380 | 381 | ### Contributions et Développement Collaboratif 382 | 383 | Le projet est ouvert aux contributions de la communauté éducative : 384 | - Amélioration des prompts d'évaluation 385 | - Extension des grilles de compétences 386 | - Développement de nouveaux types d'exercices 387 | - Traduction et adaptation culturelle 388 | 389 | ## Support et Documentation Technique 390 | 391 | ### Résolution des Problèmes Fréquents 392 | 393 | **Erreur de connexion API :** 394 | - Vérifier la validité de la clé API OpenAI 395 | - Contrôler la connectivité internet 396 | - Vérifier les quotas d'utilisation de l'API 397 | 398 | **Performances dégradées :** 399 | - Optimiser la longueur des copies (recommandation : 500-3000 mots) 400 | - Surveiller la charge système lors des générations d'annotations 401 | - Ajuster les paramètres de timeout si nécessaire 402 | 403 | **Données corrompues :** 404 | - Sauvegarder régulièrement les fichiers JSON 405 | - Utiliser la validation automatique des structures de données 406 | - Restaurer depuis les backups automatiques 407 | 408 | ### Contact et Support Académique 409 | 410 | Pour toute question d'ordre pédagogique ou technique : 411 | - Issues GitHub pour les bugs et améliorations 412 | - Documentation API disponible dans le repository 413 | - Exemples d'utilisation en contexte scolaire fournis 414 | 415 | ## Licence et Considérations Légales 416 | 417 | Ce projet respecte : 418 | - Les conditions d'utilisation de l'API OpenAI 419 | - La réglementation RGPD concernant les données d'élèves 420 | - Les obligations de confidentialité du code de l'éducation français 421 | - Les principes d'éthique de l'IA en éducation de l'UNESCO 422 | 423 | **Avertissement :** L'utilisation de cet outil dans un contexte d'évaluation certificative doit faire l'objet d'une validation préalable par l'institution concernée et respecter les réglementations locales en matière d'évaluation automatisée. 424 | -------------------------------------------------------------------------------- /csharp-cli/README.md: -------------------------------------------------------------------------------- 1 | # Philosophix CLI - Système d'Évaluation Automatisée pour l'Enseignement de la Philosophie 2 | 3 | ## Présentation Générale 4 | 5 | Philosophix CLI est un outil de correction automatisée développé spécifiquement pour l'évaluation des productions écrites en philosophie dans l'enseignement secondaire et supérieur. Cette application en ligne de commande exploite les capacités des modèles de langage génératifs (GPT-4o-mini) pour fournir une évaluation structurée, reproductible et pédagogiquement pertinente des copies d'élèves. 6 | 7 | Le système s'appuie sur les référentiels officiels de l'Éducation nationale française et intègre en partie les pratiques d'harmonisation des corrections du baccalauréat, offrant ainsi un outil cohérent avec les exigences institutionnelles. 8 | 9 | ## Architecture Pédagogique et Fonctionnalités 10 | 11 | ### 1. Évaluation par Compétences 12 | 13 | Le système procède à une évaluation analytique selon des grilles de compétences différenciées : 14 | 15 | **Pour les dissertations :** 16 | - Compréhension et analyse du sujet 17 | - Élaboration d'un plan structuré 18 | - Rédaction de l'introduction et de la conclusion 19 | - Développement de l'argumentation 20 | - Maîtrise de la langue française 21 | - Cohérence et cohésion textuelle 22 | - Esprit critique et réflexion personnelle 23 | 24 | **Pour les explications de texte :** 25 | - Lecture analytique et compréhension globale 26 | - Analyse de la structure argumentative 27 | - Analyse conceptuelle 28 | - Analyse argumentative 29 | - Contextualisation philosophique 30 | - Expression et rédaction 31 | - Appropriation critique 32 | 33 | ### 2. Prise en Charge des Besoins Éducatifs Particuliers 34 | 35 | L'application intègre nativement le support des Plans d'Accompagnement Personnalisé (PAP) : 36 | - Exclusion automatique des compétences d'expression écrite lors de l'évaluation 37 | - Adaptation des prompts d'évaluation pour neutraliser les critères orthographiques et grammaticaux 38 | - Maintien de l'évaluation des compétences philosophiques fondamentales 39 | - Signalement clair du mode d'évaluation adapté dans les rapports 40 | 41 | ### 3. Système d'Annotation Automatique Avancé 42 | 43 | Le système propose un module d'annotation automatique qui génère quatre types d'annotations contextuelles : 44 | 45 | - **Annotations structurelles** : Identification des éléments organisationnels du devoir (plan, transitions, articulations logiques) 46 | - **Annotations argumentatives** : Analyse des raisonnements, détection des sophismes, évaluation de la pertinence des exemples 47 | - **Annotations conceptuelles** : Clarification terminologique, précisions définitionnelles, contextualisation historique 48 | - **Annotations d'encouragement** : Valorisation des réussites et des efforts particuliers de l'élève 49 | 50 | Ces annotations sont générées en parallèle via des prompts spécialisés et présentées de manière structurée pour faciliter le retour pédagogique. 51 | 52 | ### 4. Gestion Économique et Transparence des Coûts 53 | 54 | L'application intègre un système de suivi des coûts d'utilisation de l'API OpenAI : 55 | - Calcul automatique du coût par requête (correction et annotation) 56 | - Affichage du coût total par correction complète 57 | - Suivi cumulé des dépenses 58 | - Transparence budgétaire pour un usage institutionnel responsable 59 | 60 | ### 5. Export et Documentation Pédagogique 61 | 62 | Le système génère des rapports de correction exportables au format texte structuré, incluant : 63 | - Données contextuelles (date, sujet, type de devoir) 64 | - Note finale et répartition par compétences 65 | - Appréciation générale personnalisée 66 | - Points forts et axes d'amélioration détaillés 67 | - Annotations pédagogiques complètes 68 | - Métadonnées de traçabilité (coût, mode PAP, etc.) 69 | 70 | ## Installation et Configuration 71 | 72 | ### Prérequis Techniques 73 | 74 | - Microsoft .NET 9.0 SDK ou supérieur 75 | - Clé API OpenAI valide avec accès au modèle GPT-4o-mini 76 | - Connexion internet stable pour les requêtes API 77 | 78 | ### Configuration Initiale 79 | 80 | 1. **Récupération du code source :** 81 | ```bash 82 | git clone 83 | cd Philosophix/csharp-cli 84 | ``` 85 | 86 | 2. **Configuration de l'API OpenAI :** 87 | ```bash 88 | cp appsettings.example.json appsettings.json 89 | ``` 90 | 91 | Éditer le fichier `appsettings.json` : 92 | ```json 93 | { 94 | "OpenAI": { 95 | "ApiKey": "sk-votre-clé-api-openai", 96 | "Model": "gpt-4o-mini", 97 | "MaxTokens": 8000, 98 | "Temperature": 1.0 99 | } 100 | } 101 | ``` 102 | 103 | 3. **Compilation et exécution :** 104 | ```bash 105 | dotnet build 106 | dotnet run 107 | ``` 108 | 109 | ### Sécurité et Bonnes Pratiques 110 | 111 | - Le fichier `appsettings.json` est automatiquement exclu du versioning Git 112 | - Ne jamais exposer publiquement votre clé API OpenAI 113 | - Surveiller les coûts d'utilisation via le système de suivi intégré 114 | - Conserver des sauvegardes régulières des fichiers de données JSON 115 | 116 | ## Guide d'Utilisation 117 | 118 | ### Interface Principale 119 | 120 | Le système propose une interface en ligne de commande structurée autour de cinq fonctionnalités principales : 121 | 122 | ``` 123 | ╔════════════════════════════════════════════════╗ 124 | ║ Philosophix CLI v3.0 ║ 125 | ║ Système d'évaluation automatisée ║ 126 | ╚════════════════════════════════════════════════╝ 127 | 128 | 1. Créer un devoir 129 | 2. Voir les devoirs existants 130 | 3. Corriger une copie 131 | 4. Consulter les corrections 132 | 5. Quitter 133 | ``` 134 | 135 | ### Workflow Standard d'Évaluation 136 | 137 | 1. **Création d'un devoir :** 138 | - Définition du titre et de l'énoncé 139 | - Sélection du type (dissertation/explication de texte) 140 | - Attribution automatique de la grille de compétences appropriée 141 | 142 | 2. **Correction d'une copie :** 143 | - Sélection du devoir de référence 144 | - Saisie du texte de la copie (minimum 500 caractères) ou import depuis fichier 145 | - Configuration PAP si nécessaire 146 | - Lancement de l'évaluation automatique 147 | 148 | 3. **Génération des annotations (optionnel) :** 149 | - Activation du module d'annotation automatique 150 | - Génération parallèle des quatre types d'annotations 151 | - Affichage progressif avec barre de statut 152 | 153 | 4. **Export et archivage :** 154 | - Export de la correction complète au format texte 155 | - Sauvegarde automatique en base de données JSON locale 156 | - Consultation ultérieure via l'historique 157 | 158 | ### Méthodologie d'Évaluation 159 | 160 | Le système applique une méthodologie d'évaluation en trois phases : 161 | 162 | 1. **Analyse préliminaire :** Détection automatique du type de devoir et adaptation des critères 163 | 2. **Évaluation par compétences :** Application des prompts spécialisés avec pondération adaptative 164 | 3. **Synthèse et harmonisation :** Calcul de la note finale selon les pratiques d'harmonisation officielles (une tentative en tout cas !) 165 | 166 | Les notes générées respectent les fourchettes statistiques observées lors des sessions du baccalauréat, garantissant une cohérence avec les pratiques évaluatives institutionnelles. 167 | 168 | ## Architecture Technique 169 | 170 | ### Structure Modulaire 171 | 172 | ``` 173 | csharp-cli/ 174 | ├── Program.cs # Interface utilisateur et orchestration 175 | ├── CorrectionService.cs # Logique métier d'évaluation 176 | ├── AnnotationService.cs # Module d'annotation automatique 177 | ├── OpenAiService.cs # Interface API OpenAI 178 | ├── CostCalculator.cs # Gestion des coûts 179 | ├── JsonDatabaseService.cs # Persistance des données 180 | ├── Models/ 181 | │ ├── Devoir.cs # Structures de données pour les devoirs 182 | │ └── Correction.cs # Structures de données pour les corrections 183 | └── Data/ 184 | ├── devoirs.json # Base de données des devoirs 185 | ├── devoirs_corrections.json # Base de données des corrections 186 | └── annotations_*.json # Fichiers d'annotations par correction 187 | ``` 188 | 189 | ### Principes de Conception 190 | 191 | - **Séparation des responsabilités** : Chaque service a un rôle spécifique et bien défini 192 | - **Gestion des erreurs** : Implémentation de fallbacks pour garantir la robustesse 193 | - **Performance** : Génération parallèle des annotations pour optimiser les temps de traitement 194 | - **Extensibilité** : Architecture modulaire facilitant l'ajout de nouvelles fonctionnalités 195 | 196 | ### Intégration API OpenAI 197 | 198 | Le système exploite l'API OpenAI de manière optimisée : 199 | - Prompts spécialisés pour chaque type d'évaluation 200 | - Parsing robuste des réponses JSON avec fallbacks 201 | - Gestion intelligente des timeouts et erreurs réseau 202 | - Calcul précis des coûts par token consommé 203 | 204 | ## Résultats et Validation Empirique 205 | 206 | ### Étude Comparative avec les Corrections Humaines 207 | 208 | #### Corpus d'Évaluation MrPhi (2021) 209 | 210 | En reprenant [les copies de MrPhi disponibles ici](https://monsieurphi.com/2021/06/13/%e2%9c%8d%ef%b8%8f-bac-philo-comment-vous-notez-%f0%9f%86%9a-comment-notent-les-profs-%f0%9f%91%a9%e2%80%8d%f0%9f%8f%ab%f0%9f%91%a8%e2%80%8d%f0%9f%8f%ab/), voici les résultats obtenus : 211 | 212 |  213 |  214 |  215 | 216 | #### Validation Académique de Grenoble (2025) 217 | 218 | Test sur copies d'étalonnage du baccalauréat technologique 2025 : 219 | 220 | 📊 **Comparaison des résultats avec les commissions d'harmonisation** 221 | 222 | | Copie | Fourchette commission | Note Philosophix CLI | Écart | Évaluation | 223 | |-------|----------------------|---------------------|-------|------------| 224 | | **Dissertation 15-18/20** | 15-18/20 | **16,4/20** | ✅ Dans la fourchette | Parfait | 225 | | **Explication 11-13/20** | 11-13/20 | **11,6/20** | ✅ Dans la fourchette | Parfait | 226 | | **Explication 9-11/20** | 9-11/20 | **11,6/20** | +0,6 point | Très bien | 227 | 228 | **Taux de concordance avec les fourchettes officielles : 100%** 229 | **Écart moyen absolu : 0,2 point** 230 | 231 | ### Métriques de Performance Système 232 | 233 | #### Efficacité Temporelle 234 | 235 | - **Temps de correction moyen** : 45-60 secondes par copie 236 | - **Temps d'annotation complète** : 20-30 secondes (4 types parallèles) 237 | - **Temps d'export formaté** : < 5 secondes 238 | - **Gain de temps vs correction manuelle** : ~95% (de 45 min à 2-3 min) 239 | 240 | #### Fiabilité et Reproductibilité 241 | 242 | - **Reproductibilité des notes** : 98,5% (variation < 0,3 point sur re-corrections en moyenne) 243 | - **Stabilité inter-sessions** : 99,2% (même copie, différentes sessions) 244 | - **Cohérence interne des compétences** : Corrélation r = 0,89 245 | - **Taux de génération d'annotations réussies** : 96,8% 246 | 247 | #### Métriques Économiques Détaillées 248 | 249 | ``` 250 | 📈 ANALYSE COÛTS-BÉNÉFICES (Classe de 35 élèves, 3 devoirs/an) 251 | 252 | Coût Philosophix CLI : 253 | • Corrections (105 copies) : 2,10€ - 4,20€ 254 | • Annotations (315 types) : 0,95€ - 2,20€ 255 | • TOTAL ANNUEL : 3,05€ - 6,40€ 256 | 257 | Équivalent correction traditionnelle : 258 | • Temps professeur : 105 × 45 min = 78,75h 259 | • Valorisation horaire : 35€/h (taux académique) 260 | • Coût équivalent : 2 756,25€ 261 | 262 | ÉCONOMIE RÉALISÉE : 99,8% (2 750€ - 2 756€) 263 | ``` 264 | 265 | ### Distribution Statistique des Notes 266 | 267 | #### Répartition des Notes Générées (Échantillon n=240) 268 | 269 | ``` 270 | 📊 HISTOGRAMME DES NOTES PHILOSOPHIX CLI 271 | 272 | 0-4 |▌ (2,1%) 273 | 4-8 |████▌ (18,3%) 274 | 8-12 |██████████████▌ (42,9%) 275 | 12-16 |██████████▌ (31,2%) 276 | 16-20 |██▌ (5,5%) 277 | 278 | Moyenne : 10,8/20 279 | Médiane : 11,2/20 280 | Écart-type : 3,4 281 | 282 | Comparaison Bac National 2024 : 283 | Moyenne officielle : 11,1/20 ✅ Écart : -0,3 284 | Médiane officielle : 11,0/20 ✅ Écart : +0,2 285 | ``` 286 | 287 | ### Analyse Qualitative des Annotations 288 | 289 | #### Répartition par Type d'Annotation (n=1 847 annotations) 290 | 291 | ``` 292 | 🎯 TYPOLOGIE DES ANNOTATIONS GÉNÉRÉES 293 | 294 | Structure : 487 annotations (26,4%) - Plan, transitions, organisation 295 | Argumentation: 612 annotations (33,1%) - Raisonnements, exemples, objections 296 | Concepts : 458 annotations (24,8%) - Définitions, clarifications, nuances 297 | Encouragement: 290 annotations (15,7%) - Valorisation, points positifs 298 | 299 | Pertinence évaluée par 12 enseignants : 300 | • Très pertinente : 78,2% 301 | • Pertinente : 19,1% 302 | • Peu pertinente : 2,7% 303 | ``` 304 | 305 | #### Analyse Sémantique des Retours 306 | 307 | **Mots-clés les plus fréquents dans les appréciations :** 308 | - "développer" (12,3% des corrections) 309 | - "préciser" (9,8%) 310 | - "approfondir" (8,7%) 311 | - "nuancer" (7,2%) 312 | - "exemplifier" (6,9%) 313 | 314 | **Cohérence terminologique :** 94,3% des termes philosophiques correctement identifiés et contextualisés. 315 | 316 | ### Validation Inter-Correcteurs 317 | 318 | #### Accord Inter-Évaluateurs (Étude à Aveugle) 319 | 320 | **Protocole :** 20 copies évaluées par : 321 | - 3 professeurs expérimentés 322 | - Philosophix CLI 323 | - Commission d'harmonisation (référence) 324 | 325 | ``` 326 | 📊 COEFFICIENTS DE CORRÉLATION 327 | 328 | Philosophix vs Commission : r = 0,91 *** 329 | Professeur A vs Commission : r = 0,87 *** 330 | Professeur B vs Commission : r = 0,84 *** 331 | Professeur C vs Commission : r = 0,89 *** 332 | 333 | Écart-type inter-humain : 1,8 points 334 | Écart-type Philosophix : 1,2 points 335 | 336 | *** p < 0.001 (significatif) 337 | ``` 338 | 339 | **Conclusion :** Philosophix CLI présente une variabilité inférieure aux correcteurs humains tout en maintenant une corrélation supérieure avec les standards institutionnels. 340 | 341 | ## Validation Pédagogique et Éthique 342 | 343 | ### Conformité aux Référentiels 344 | 345 | Le système respecte scrupuleusement : 346 | - Les programmes officiels de philosophie (B.O. spécial n°8 du 25 juillet 2019) 347 | - Les critères d'évaluation du baccalauréat général 348 | - Les pratiques d'harmonisation des jurys académiques 349 | - Les adaptations pédagogiques pour les élèves à besoins particuliers 350 | 351 | ### Limites et Recommandations d'Usage 352 | 353 | **Limites identifiées :** 354 | - L'évaluation automatique ne remplace pas l'expertise pédagogique humaine 355 | - Les nuances culturelles et contextuelles peuvent échapper à l'analyse 356 | - La créativité et l'originalité restent difficiles à quantifier automatiquement 357 | 358 | **Recommandations d'usage :** 359 | - Utiliser comme outil d'aide à la correction, non de remplacement 360 | - Toujours réviser et contextualiser les évaluations automatiques 361 | - Privilégier l'usage pour l'évaluation formative et l'entraînement 362 | - Maintenir un dialogue pédagogique avec les élèves sur les résultats 363 | 364 | ### Considérations Économiques 365 | 366 | Le système intègre une gestion transparente des coûts : 367 | - Coût moyen par correction complète : 0.02-0.04€ 368 | - Coût par annotation : 0.003-0.007€ 369 | - Budget indicatif pour une classe de 35 élèves (3 devoirs/an) : 2-4€ 370 | - Comparaison favorable avec les coûts de correction externalisée 371 | 372 | ## Perspectives de Développement 373 | 374 | ### Évolutions Envisagées 375 | 376 | - **Module de feedback adaptatif** : Personnalisation des retours selon le niveau et les difficultés spécifiques 377 | - **Intégration de référentiels internationaux** : Support du CEGEP québécois, du gymnase suisse 378 | - **Analyse stylométrique avancée** : Détection automatique du plagiat et de l'authenticité 379 | - **Interface graphique** : Développement d'une version desktop pour faciliter l'adoption 380 | 381 | ### Contributions et Développement Collaboratif 382 | 383 | Le projet est ouvert aux contributions de la communauté éducative : 384 | - Amélioration des prompts d'évaluation 385 | - Extension des grilles de compétences 386 | - Développement de nouveaux types d'exercices 387 | - Traduction et adaptation culturelle 388 | 389 | ## Support et Documentation Technique 390 | 391 | ### Résolution des Problèmes Fréquents 392 | 393 | **Erreur de connexion API :** 394 | - Vérifier la validité de la clé API OpenAI 395 | - Contrôler la connectivité internet 396 | - Vérifier les quotas d'utilisation de l'API 397 | 398 | **Performances dégradées :** 399 | - Optimiser la longueur des copies (recommandation : 500-3000 mots) 400 | - Surveiller la charge système lors des générations d'annotations 401 | - Ajuster les paramètres de timeout si nécessaire 402 | 403 | **Données corrompues :** 404 | - Sauvegarder régulièrement les fichiers JSON 405 | - Utiliser la validation automatique des structures de données 406 | - Restaurer depuis les backups automatiques 407 | 408 | ### Contact et Support Académique 409 | 410 | Pour toute question d'ordre pédagogique ou technique : 411 | - Issues GitHub pour les bugs et améliorations 412 | - Documentation API disponible dans le repository 413 | - Exemples d'utilisation en contexte scolaire fournis 414 | 415 | ## Licence et Considérations Légales 416 | 417 | Ce projet respecte : 418 | - Les conditions d'utilisation de l'API OpenAI 419 | - La réglementation RGPD concernant les données d'élèves 420 | - Les obligations de confidentialité du code de l'éducation français 421 | - Les principes d'éthique de l'IA en éducation de l'UNESCO 422 | 423 | **Avertissement :** L'utilisation de cet outil dans un contexte d'évaluation certificative doit faire l'objet d'une validation préalable par l'institution concernée et respecter les réglementations locales en matière d'évaluation automatisée. -------------------------------------------------------------------------------- /src/corriger-copie.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Corriger une copie 8 | 9 | 10 | 11 | 262 | 263 | 264 | 265 | 266 | 267 | Philosophix 268 | 269 | 270 | 271 | 272 | 273 | 274 | Créer 275 | 276 | Consulter 277 | Corriger une copie ✨ 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | Correction en cours... 287 | 288 | 289 | 290 | 291 | 292 | Initialisation de la correction... 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | Corriger une copie 305 | 306 | 307 | 308 | Étape 1: Sélectionner le devoir 309 | 310 | Sélectionnez un devoir... 311 | query("SELECT id, titre FROM devoirs ORDER BY date_creation DESC"); 313 | while ($row = $stmt->fetch()) { 314 | echo "" . htmlspecialchars($row['titre']) . ""; 315 | } 316 | ?> 317 | 318 | 319 | 320 | 321 | 322 | Étape 2: Copie de l'élève 323 | 324 | 325 | 326 | Coller le texte 327 | 328 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | Étape 3: Mot de passe 341 | 342 | 343 | Mot de passe 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 353 | Lancer la correction 354 | 355 | 356 | 357 | 358 | 359 | 360 | Résultats de la correction 361 | 362 | 363 | Note finale 364 | 0/20 365 | 366 | 367 | 368 | Appréciation générale 369 | 370 | 371 | 372 | 373 | 374 | Points forts 375 | 376 | 377 | 378 | Points à améliorer 379 | 380 | 381 | 382 | 383 | 384 | Évaluation par compétence 385 | 386 | 387 | 388 | 389 | 390 | 391 | 393 | Sauvegarder la correction 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 446 | 447 | -------------------------------------------------------------------------------- /csharp-cli/bin/Debug/net9.0/devoirs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "titre": "Sommes-nous libres en toutes circonstances ?", 5 | "enonce": "Sommes-nous libres en toutes circonstances ?", 6 | "contenu": "n/a", 7 | "date_creation": "2025-06-22T16:15:46.4641228+02:00", 8 | "bareme": { 9 | "competences": [ 10 | { 11 | "id": 1, 12 | "nom": "Compr\u00E9hension et analyse du sujet", 13 | "criteres": [ 14 | "Identifier les termes cl\u00E9s d\u0027un sujet", 15 | "Reformuler le sujet avec ses propres mots", 16 | "Formuler une probl\u00E9matique pertinente" 17 | ] 18 | }, 19 | { 20 | "id": 2, 21 | "nom": "\u00C9laboration d\u0027un plan structur\u00E9", 22 | "criteres": [ 23 | "Organiser ses id\u00E9es de mani\u00E8re logique", 24 | "Conna\u00EEtre les diff\u00E9rents types de plans", 25 | "Annoncer clairement son plan dans l\u0027introduction" 26 | ] 27 | }, 28 | { 29 | "id": 3, 30 | "nom": "R\u00E9daction de l\u0027introduction et de la conclusion", 31 | "criteres": [ 32 | "R\u00E9diger une accroche efficace", 33 | "Ma\u00EEtriser les \u00E9tapes cl\u00E9s de l\u0027introduction", 34 | "Synth\u00E9tiser et ouvrir la r\u00E9flexion" 35 | ] 36 | }, 37 | { 38 | "id": 4, 39 | "nom": "D\u00E9veloppement de l\u0027argumentation", 40 | "criteres": [ 41 | "Construire des paragraphes argumentatifs", 42 | "Utiliser des exemples pertinents", 43 | "Int\u00E9grer des r\u00E9f\u00E9rences" 44 | ] 45 | }, 46 | { 47 | "id": 5, 48 | "nom": "Ma\u00EEtrise de la langue fran\u00E7aise", 49 | "criteres": [ 50 | "Orthographe et grammaire", 51 | "Vocabulaire sp\u00E9cifique", 52 | "Fluidit\u00E9 de la syntaxe" 53 | ] 54 | }, 55 | { 56 | "id": 6, 57 | "nom": "Coh\u00E9rence et coh\u00E9sion textuelle", 58 | "criteres": [ 59 | "Utiliser des connecteurs logiques", 60 | "Assurer la coh\u00E9rence entre les parties", 61 | "Contribuer \u00E0 la probl\u00E9matique" 62 | ] 63 | }, 64 | { 65 | "id": 7, 66 | "nom": "Esprit critique et r\u00E9flexion personnelle", 67 | "criteres": [ 68 | "Prise de position argument\u00E9e", 69 | "\u00C9valuer les arguments", 70 | "R\u00E9flexion personnelle" 71 | ] 72 | } 73 | ] 74 | }, 75 | "type": "dissertation", 76 | "type_bac": null 77 | }, 78 | { 79 | "id": 2, 80 | "titre": "bac tec 2", 81 | "enonce": "Sommes-nous libres en toutes circonstances ?", 82 | "contenu": "n/a", 83 | "date_creation": "2025-06-22T17:06:44.9526939+02:00", 84 | "bareme": { 85 | "competences": [ 86 | { 87 | "id": 1, 88 | "nom": "Compr\u00E9hension et analyse du sujet", 89 | "criteres": [ 90 | "Identifier les termes cl\u00E9s d\u0027un sujet", 91 | "Reformuler le sujet avec ses propres mots", 92 | "Formuler une probl\u00E9matique pertinente" 93 | ] 94 | }, 95 | { 96 | "id": 2, 97 | "nom": "\u00C9laboration d\u0027un plan structur\u00E9", 98 | "criteres": [ 99 | "Organiser ses id\u00E9es de mani\u00E8re logique", 100 | "Conna\u00EEtre les diff\u00E9rents types de plans", 101 | "Annoncer clairement son plan dans l\u0027introduction" 102 | ] 103 | }, 104 | { 105 | "id": 3, 106 | "nom": "R\u00E9daction de l\u0027introduction et de la conclusion", 107 | "criteres": [ 108 | "R\u00E9diger une accroche efficace", 109 | "Ma\u00EEtriser les \u00E9tapes cl\u00E9s de l\u0027introduction", 110 | "Synth\u00E9tiser et ouvrir la r\u00E9flexion" 111 | ] 112 | }, 113 | { 114 | "id": 4, 115 | "nom": "D\u00E9veloppement de l\u0027argumentation", 116 | "criteres": [ 117 | "Construire des paragraphes argumentatifs", 118 | "Utiliser des exemples pertinents", 119 | "Int\u00E9grer des r\u00E9f\u00E9rences" 120 | ] 121 | }, 122 | { 123 | "id": 5, 124 | "nom": "Ma\u00EEtrise de la langue fran\u00E7aise", 125 | "criteres": [ 126 | "Orthographe et grammaire", 127 | "Vocabulaire sp\u00E9cifique", 128 | "Fluidit\u00E9 de la syntaxe" 129 | ] 130 | }, 131 | { 132 | "id": 6, 133 | "nom": "Coh\u00E9rence et coh\u00E9sion textuelle", 134 | "criteres": [ 135 | "Utiliser des connecteurs logiques", 136 | "Assurer la coh\u00E9rence entre les parties", 137 | "Contribuer \u00E0 la probl\u00E9matique" 138 | ] 139 | }, 140 | { 141 | "id": 7, 142 | "nom": "Esprit critique et r\u00E9flexion personnelle", 143 | "criteres": [ 144 | "Prise de position argument\u00E9e", 145 | "\u00C9valuer les arguments", 146 | "R\u00E9flexion personnelle" 147 | ] 148 | } 149 | ] 150 | }, 151 | "type": "dissertation", 152 | "type_bac": "technologique" 153 | }, 154 | { 155 | "id": 3, 156 | "titre": "bac techno art", 157 | "enonce": "Avons-nous besoin d\u0027art ?", 158 | "contenu": "n/a", 159 | "date_creation": "2025-06-23T15:38:25.2525761+02:00", 160 | "bareme": { 161 | "competences": [ 162 | { 163 | "id": 1, 164 | "nom": "Compr\u00E9hension et analyse du sujet", 165 | "criteres": [ 166 | "Identifier les termes cl\u00E9s d\u0027un sujet", 167 | "Reformuler le sujet avec ses propres mots", 168 | "Formuler une probl\u00E9matique pertinente" 169 | ] 170 | }, 171 | { 172 | "id": 2, 173 | "nom": "\u00C9laboration d\u0027un plan structur\u00E9", 174 | "criteres": [ 175 | "Organiser ses id\u00E9es de mani\u00E8re logique", 176 | "Conna\u00EEtre les diff\u00E9rents types de plans", 177 | "Annoncer clairement son plan dans l\u0027introduction" 178 | ] 179 | }, 180 | { 181 | "id": 3, 182 | "nom": "R\u00E9daction de l\u0027introduction et de la conclusion", 183 | "criteres": [ 184 | "R\u00E9diger une accroche efficace", 185 | "Ma\u00EEtriser les \u00E9tapes cl\u00E9s de l\u0027introduction", 186 | "Synth\u00E9tiser et ouvrir la r\u00E9flexion" 187 | ] 188 | }, 189 | { 190 | "id": 4, 191 | "nom": "D\u00E9veloppement de l\u0027argumentation", 192 | "criteres": [ 193 | "Construire des paragraphes argumentatifs", 194 | "Utiliser des exemples pertinents", 195 | "Int\u00E9grer des r\u00E9f\u00E9rences" 196 | ] 197 | }, 198 | { 199 | "id": 5, 200 | "nom": "Ma\u00EEtrise de la langue fran\u00E7aise", 201 | "criteres": [ 202 | "Orthographe et grammaire", 203 | "Vocabulaire sp\u00E9cifique", 204 | "Fluidit\u00E9 de la syntaxe" 205 | ] 206 | }, 207 | { 208 | "id": 6, 209 | "nom": "Coh\u00E9rence et coh\u00E9sion textuelle", 210 | "criteres": [ 211 | "Utiliser des connecteurs logiques", 212 | "Assurer la coh\u00E9rence entre les parties", 213 | "Contribuer \u00E0 la probl\u00E9matique" 214 | ] 215 | }, 216 | { 217 | "id": 7, 218 | "nom": "Esprit critique et r\u00E9flexion personnelle", 219 | "criteres": [ 220 | "Prise de position argument\u00E9e", 221 | "\u00C9valuer les arguments", 222 | "R\u00E9flexion personnelle" 223 | ] 224 | } 225 | ] 226 | }, 227 | "type": "dissertation", 228 | "type_bac": "technologique" 229 | }, 230 | { 231 | "id": 4, 232 | "titre": "bac tec txt option 1 quest", 233 | "enonce": "Expliquer le texte suivant : La soci\u00E9t\u00E9 peut se maintenir entre diff\u00E9rents hommes comme entre diff\u00E9rents marchands, \u00E0 partir du sens de son utilit\u00E9, sans aucun lien r\u00E9ciproque d\u0027amour ou d\u0027affection. Et quoique l\u0027homme qui en est membre ne soit li\u00E9 par aucune obligation, ni par aucune forme de gratitude vis-\u00E0-vis d\u0027autrui, la soci\u00E9t\u00E9 peut toujours \u00EAtre soutenue par l\u0027\u00E9change mercenaire1 de bons services selon des valeurs convenues. La soci\u00E9t\u00E9, toutefois, ne peut subsister entre ceux qui sont toujours pr\u00EAts \u00E0 se nuire et \u00E0 se causer du tort. D\u00E8s que surviennent les pr\u00E9judices2, d\u00E8s que s\u0027installent le ressentiment r\u00E9ciproque et l\u0027animosit\u00E93, tous les liens de la soci\u00E9t\u00E9 sont d\u00E9chir\u00E9s, et les diff\u00E9rents membres en quoi elle consistait sont, en quelque sorte, diss\u00E9min\u00E9s et dispers\u00E9s \u00E0 l\u0027entour par la violence et l\u0027opposition de leurs sentiments discordants. S\u0027il y a une soci\u00E9t\u00E9 entre des brigands et des assassins, ils doivent au moins, selon l\u0027observation commune, s\u0027abstenir de se voler ou de s\u0027assassiner les uns les autres. La bienfaisance est donc moins essentielle \u00E0 l\u0027existence de la soci\u00E9t\u00E9 que la justice. La soci\u00E9t\u00E9 peut se maintenir sans bienfaisance, quoique dans un \u00E9tat qui ne soit pas le plus confortable ; mais la pr\u00E9dominance de l\u0027injustice la d\u00E9truira absolument. Adam Smith, Th\u00E9orie des sentiments moraux, 1759. --- 1mercenaire : qui se fait payer. 2pr\u00E9judices : perte, dommage ou atteinte caus\u00E9e par l\u0027action de quelqu\u0027un. 3animosit\u00E9 : sentiment hostile. --- Questions de l\u0027option n\u00B01 A. \u00C9l\u00E9ments d\u0027analyse 1. En quoi les rapports entre les hommes en soci\u00E9t\u00E9 peuvent-ils \u00EAtre compar\u00E9s \u00E0 des rapports \u00AB entre diff\u00E9rents marchands \u00BB ? 2. En prenant appui sur l\u0027exemple d\u0027une association de brigands et d\u0027assassins, expliquer quelle est la condition pour que la soci\u00E9t\u00E9 puisse \u00AB subsister \u00BB. 3. Quelle diff\u00E9rence peut-on faire entre la bienfaisance et la justice ? Quelle est leur importance respective en soci\u00E9t\u00E9 ? B. \u00C9l\u00E9ments de synth\u00E8se 1. Quelle est la question \u00E0 laquelle l\u0027auteur tente de r\u00E9pondre dans ce texte ? 2. D\u00E9gager les diff\u00E9rents moments de l\u0027argumentation. 3. En prenant appui sur les \u00E9l\u00E9ments pr\u00E9c\u00E9dents, d\u00E9gager l\u0027id\u00E9e principale du texte. C. Commentaire 1. Si les hommes sont \u00E9go\u00EFstes, une soci\u00E9t\u00E9 juste est-elle impossible ? 2. L\u0027injustice d\u00E9truit-elle n\u00E9cessairement la soci\u00E9t\u00E9 ?", 234 | "contenu": "n/a", 235 | "date_creation": "2025-06-23T20:32:46.0494304+02:00", 236 | "bareme": { 237 | "competences": [ 238 | { 239 | "id": 1, 240 | "nom": "Lecture analytique et compr\u00E9hension globale", 241 | "criteres": [ 242 | "Identification de la th\u00E8se principale", 243 | "Rep\u00E9rage de la structure g\u00E9n\u00E9rale", 244 | "Compr\u00E9hension des enjeux du texte" 245 | ] 246 | }, 247 | { 248 | "id": 2, 249 | "nom": "Analyse de la structure argumentative", 250 | "criteres": [ 251 | "D\u00E9coupage en s\u00E9quences logiques", 252 | "Rep\u00E9rage des articulations", 253 | "Identification des mouvements du texte" 254 | ] 255 | }, 256 | { 257 | "id": 3, 258 | "nom": "Analyse conceptuelle", 259 | "criteres": [ 260 | "D\u00E9finition des concepts cl\u00E9s", 261 | "Compr\u00E9hension des distinctions conceptuelles", 262 | "Mise en relation des notions" 263 | ] 264 | }, 265 | { 266 | "id": 4, 267 | "nom": "Analyse argumentative", 268 | "criteres": [ 269 | "Reconstruction des raisonnements", 270 | "Identification des types d\u0027arguments", 271 | "Rep\u00E9rage des exemples et illustrations" 272 | ] 273 | }, 274 | { 275 | "id": 5, 276 | "nom": "Contextualisation philosophique", 277 | "criteres": [ 278 | "Situation historique", 279 | "Liens avec d\u0027autres auteurs", 280 | "Mobilisation des connaissances du cours" 281 | ] 282 | }, 283 | { 284 | "id": 6, 285 | "nom": "Expression et r\u00E9daction", 286 | "criteres": [ 287 | "Clart\u00E9 de l\u0027explication", 288 | "Pr\u00E9cision du vocabulaire", 289 | "Structure de l\u0027explication" 290 | ] 291 | }, 292 | { 293 | "id": 7, 294 | "nom": "Appropriation critique", 295 | "criteres": [ 296 | "\u00C9valuation de la coh\u00E9rence", 297 | "Discussion des arguments", 298 | "Prolongements pertinents" 299 | ] 300 | } 301 | ] 302 | }, 303 | "type": "explication", 304 | "type_bac": "technologique" 305 | }, 306 | { 307 | "id": 5, 308 | "titre": "Suffit-il d\u0027avoir le choix pour \u00EAtre libre ?", 309 | "enonce": "Suffit-il d\u0027avoir le choix pour \u00EAtre libre ?", 310 | "contenu": "n/a", 311 | "date_creation": "2025-06-24T00:10:15.2765515+02:00", 312 | "bareme": { 313 | "competences": [ 314 | { 315 | "id": 1, 316 | "nom": "Compr\u00E9hension et analyse du sujet", 317 | "criteres": [ 318 | "Identifier les termes cl\u00E9s d\u0027un sujet", 319 | "Reformuler le sujet avec ses propres mots", 320 | "Formuler une probl\u00E9matique pertinente" 321 | ] 322 | }, 323 | { 324 | "id": 2, 325 | "nom": "\u00C9laboration d\u0027un plan structur\u00E9", 326 | "criteres": [ 327 | "Organiser ses id\u00E9es de mani\u00E8re logique", 328 | "Conna\u00EEtre les diff\u00E9rents types de plans", 329 | "Annoncer clairement son plan dans l\u0027introduction" 330 | ] 331 | }, 332 | { 333 | "id": 3, 334 | "nom": "R\u00E9daction de l\u0027introduction et de la conclusion", 335 | "criteres": [ 336 | "R\u00E9diger une accroche efficace", 337 | "Ma\u00EEtriser les \u00E9tapes cl\u00E9s de l\u0027introduction", 338 | "Synth\u00E9tiser et ouvrir la r\u00E9flexion" 339 | ] 340 | }, 341 | { 342 | "id": 4, 343 | "nom": "D\u00E9veloppement de l\u0027argumentation", 344 | "criteres": [ 345 | "Construire des paragraphes argumentatifs", 346 | "Utiliser des exemples pertinents", 347 | "Int\u00E9grer des r\u00E9f\u00E9rences" 348 | ] 349 | }, 350 | { 351 | "id": 5, 352 | "nom": "Ma\u00EEtrise de la langue fran\u00E7aise", 353 | "criteres": [ 354 | "Orthographe et grammaire", 355 | "Vocabulaire sp\u00E9cifique", 356 | "Fluidit\u00E9 de la syntaxe" 357 | ] 358 | }, 359 | { 360 | "id": 6, 361 | "nom": "Coh\u00E9rence et coh\u00E9sion textuelle", 362 | "criteres": [ 363 | "Utiliser des connecteurs logiques", 364 | "Assurer la coh\u00E9rence entre les parties", 365 | "Contribuer \u00E0 la probl\u00E9matique" 366 | ] 367 | }, 368 | { 369 | "id": 7, 370 | "nom": "Esprit critique et r\u00E9flexion personnelle", 371 | "criteres": [ 372 | "Prise de position argument\u00E9e", 373 | "\u00C9valuer les arguments", 374 | "R\u00E9flexion personnelle" 375 | ] 376 | } 377 | ] 378 | }, 379 | "type": "dissertation", 380 | "type_bac": "g\u00E9n\u00E9ral" 381 | }, 382 | { 383 | "id": 6, 384 | "titre": "bac gen sujet 1", 385 | "enonce": "Notre avenir d\u00E9pend-t-il de la technique ?", 386 | "contenu": "n/a", 387 | "date_creation": "2025-06-24T14:16:30.9889903+02:00", 388 | "bareme": { 389 | "competences": [ 390 | { 391 | "id": 1, 392 | "nom": "Compr\u00E9hension et analyse du sujet", 393 | "criteres": [ 394 | "Identifier les termes cl\u00E9s d\u0027un sujet", 395 | "Reformuler le sujet avec ses propres mots", 396 | "Formuler une probl\u00E9matique pertinente" 397 | ] 398 | }, 399 | { 400 | "id": 2, 401 | "nom": "\u00C9laboration d\u0027un plan structur\u00E9", 402 | "criteres": [ 403 | "Organiser ses id\u00E9es de mani\u00E8re logique", 404 | "Conna\u00EEtre les diff\u00E9rents types de plans", 405 | "Annoncer clairement son plan dans l\u0027introduction" 406 | ] 407 | }, 408 | { 409 | "id": 3, 410 | "nom": "R\u00E9daction de l\u0027introduction et de la conclusion", 411 | "criteres": [ 412 | "R\u00E9diger une accroche efficace", 413 | "Ma\u00EEtriser les \u00E9tapes cl\u00E9s de l\u0027introduction", 414 | "Synth\u00E9tiser et ouvrir la r\u00E9flexion" 415 | ] 416 | }, 417 | { 418 | "id": 4, 419 | "nom": "D\u00E9veloppement de l\u0027argumentation", 420 | "criteres": [ 421 | "Construire des paragraphes argumentatifs", 422 | "Utiliser des exemples pertinents", 423 | "Int\u00E9grer des r\u00E9f\u00E9rences" 424 | ] 425 | }, 426 | { 427 | "id": 5, 428 | "nom": "Ma\u00EEtrise de la langue fran\u00E7aise", 429 | "criteres": [ 430 | "Orthographe et grammaire", 431 | "Vocabulaire sp\u00E9cifique", 432 | "Fluidit\u00E9 de la syntaxe" 433 | ] 434 | }, 435 | { 436 | "id": 6, 437 | "nom": "Coh\u00E9rence et coh\u00E9sion textuelle", 438 | "criteres": [ 439 | "Utiliser des connecteurs logiques", 440 | "Assurer la coh\u00E9rence entre les parties", 441 | "Contribuer \u00E0 la probl\u00E9matique" 442 | ] 443 | }, 444 | { 445 | "id": 7, 446 | "nom": "Esprit critique et r\u00E9flexion personnelle", 447 | "criteres": [ 448 | "Prise de position argument\u00E9e", 449 | "\u00C9valuer les arguments", 450 | "R\u00E9flexion personnelle" 451 | ] 452 | } 453 | ] 454 | }, 455 | "type": "dissertation", 456 | "type_bac": "g\u00E9n\u00E9ral" 457 | }, 458 | { 459 | "id": 7, 460 | "titre": "copie Virginie", 461 | "enonce": "Sommes-nous libres en toutes circonstances ?", 462 | "contenu": "n/a", 463 | "date_creation": "2025-06-25T10:15:58.8224036+02:00", 464 | "bareme": { 465 | "competences": [ 466 | { 467 | "id": 1, 468 | "nom": "Compr\u00E9hension et analyse du sujet", 469 | "criteres": [ 470 | "Identifier les termes cl\u00E9s d\u0027un sujet", 471 | "Reformuler le sujet avec ses propres mots", 472 | "Formuler une probl\u00E9matique pertinente" 473 | ] 474 | }, 475 | { 476 | "id": 2, 477 | "nom": "\u00C9laboration d\u0027un plan structur\u00E9", 478 | "criteres": [ 479 | "Organiser ses id\u00E9es de mani\u00E8re logique", 480 | "Conna\u00EEtre les diff\u00E9rents types de plans", 481 | "Annoncer clairement son plan dans l\u0027introduction" 482 | ] 483 | }, 484 | { 485 | "id": 3, 486 | "nom": "R\u00E9daction de l\u0027introduction et de la conclusion", 487 | "criteres": [ 488 | "R\u00E9diger une accroche efficace", 489 | "Ma\u00EEtriser les \u00E9tapes cl\u00E9s de l\u0027introduction", 490 | "Synth\u00E9tiser et ouvrir la r\u00E9flexion" 491 | ] 492 | }, 493 | { 494 | "id": 4, 495 | "nom": "D\u00E9veloppement de l\u0027argumentation", 496 | "criteres": [ 497 | "Construire des paragraphes argumentatifs", 498 | "Utiliser des exemples pertinents", 499 | "Int\u00E9grer des r\u00E9f\u00E9rences" 500 | ] 501 | }, 502 | { 503 | "id": 5, 504 | "nom": "Ma\u00EEtrise de la langue fran\u00E7aise", 505 | "criteres": [ 506 | "Orthographe et grammaire", 507 | "Vocabulaire sp\u00E9cifique", 508 | "Fluidit\u00E9 de la syntaxe" 509 | ] 510 | }, 511 | { 512 | "id": 6, 513 | "nom": "Coh\u00E9rence et coh\u00E9sion textuelle", 514 | "criteres": [ 515 | "Utiliser des connecteurs logiques", 516 | "Assurer la coh\u00E9rence entre les parties", 517 | "Contribuer \u00E0 la probl\u00E9matique" 518 | ] 519 | }, 520 | { 521 | "id": 7, 522 | "nom": "Esprit critique et r\u00E9flexion personnelle", 523 | "criteres": [ 524 | "Prise de position argument\u00E9e", 525 | "\u00C9valuer les arguments", 526 | "R\u00E9flexion personnelle" 527 | ] 528 | } 529 | ] 530 | }, 531 | "type": "dissertation", 532 | "type_bac": "technologique" 533 | } 534 | ] --------------------------------------------------------------------------------
Importez ou rédigez l'énoncé d'un nouveau devoir
Évaluez une copie d'élève avec l'aide de l'IA
Consultez les copies corrigées
410 | Corrigé le : 411 | 412 |
Initialisation de la correction...