Skip to content

Feature V11: Extension du pilotage de Khiops via les scénarios

Marc edited this page Dec 3, 2024 · 2 revisions

Extension du pilotage de Khiops via les scénarios

Résumé

On propose dans ce document une extension du pilotage de Khiops via des scénarios.

Khiops peut-être piloté via la ligne de commande via des scénarios

  • option -i: pour passer un fichier scenario en paramètre
  • option -r: pour faire des search/replace, permettant une variabilité via des scenarios rendus génériques

Ce mode de contrôle est intéressant pour intégrer rapidement des traitements Khiops et les lancer depuis n'importe quel langage de programmation. Par contre, cela est limité dans le cas de paramétrage plus complexe, comme par exemple l'ensemble des tables d'un schéma en flocon. Dans ce cas, on doit passer un un algorithme de création de scénario comportant potentiellement des boucles de search/replace.

On propose d'étendre d'étendre le pilotage de khiops via les scénarios:

  • extension du formalisme des scénarios pour avoir quelques structures de contrôle
  • extension du search/replace (-r) pour avoir une structure de donnée en entrée plutôt que des paires (key/value)

L'intérêt de cette extension fonctionnelle est multiple:

  • étend la facilité de pilotage de Khiops pour tous les utilisateurs/intégrateurs
  • facilite l'interfaçage avec tout langage de programmation
  • facilite la mise au point d'une API "officielle"
  • simplifie les évolutions d'AutoML

Spécification fonctionnelle

Structure de contrôle dans les scénarios

On ajoute quelques structures de contrôle dans les scénario pour permettre un pilotage complet des opérations de search/replace.

Les structures de contrôle sont matérialisées par des instructions en UPPER CASE sur des lignes dédiées.

Boucle

Une structure de boucle permet d'entourer un bloc de lignes de scenario entre deux instructions

  • LOOP <loop key>
  • END LOOP

Toutes les lignes d'un bloc de boucle sont répétées autant de fois que nécessaire.

Test

Une structure de test permet d'entourer un bloc de lignes de scenario entre deux instructions

  • IF <if key>
  • END IF

Toutes les lignes d'un bloc de test sont prise en compte conditionnellement au test.

Paramétrage par une structure de données

Ajout d'un option sur la ligne de commande des outils Khiops: -j \<file\> json file used to set replay parameters

Le fichier json contient une série de paires clé/valeur:

  • valeur de type string ou number
    • clé dans le scénario a remplacer par la valeur
  • valeur de type array
    • la clé du tableau permet d'identifier (loop key) un bloc de lignes dans le scenario, pour une structure de boucle (LOOP)
    • la valeur est associée dans le json à un array contenant des object json, tous de la même structure, avec la même liste de paires clé/valeur de type string ou number
    • on duplique les lignes de la boucle autant de fois qu'il y d'objets dans le tableau, en effectuant les search/replace selon les clés/valeur de l'objet courant
  • valeur de type boolean
    • la clé du boolean permet d'identifier (if key) un bloc de lignes dans le scenario, pour une structure de test (IF)
    • on prend en compte les lignes du test selon la valeur true ou false associée à la clé

Format json: https://www.json.org/json-en.html

Contraintes sur les options de la ligne de commande

Pour faciliter la mise au point du pilotage par scenario, on rajoute l'option suivante: -O \<file\> same as -o option, but without replay

Contraintes:

  • les options -r (search/replace basique) et -j (search/replace piloté par un fichier json) sont exclusives.
  • les options -o et -O sont exclusives.

Contraintes sur la structure du json

Seule une petite partie de l'expressivité du format json est gérée

  • pas de valeur nul
  • pas de récursion dans la structure: la seul usage autorisé et celui d'un array contenant des object

Contraintes sur les clés

  • les clés utilisées dans le json doivent être distinctes
    • pour l'object à la racine d'objet json principal
    • pour chaque tableau, localement au tableau, et entre les clé du tableau et celle de l'objet englobant
  • les clés ont une syntaxe de variables de langage: uniquement des caractères alpha-numériques
  • aucune clé ne doit être une sous-partie d'une autre clé
    • évite les ambiguités selon l'ordre de remplacement dans les search/replace

Liens entre clés dans le json et dans le scénario

  • chaque clé dans le scenario est utilisable dans le json si elle est entourée de '__' (double tiret du 8)
    • exemple, une clé name dans le json est utilisable avec la valeur à remplacer name dans le scenario
  • chaque clé dans le json doit être utilisée dans le scénario, et réciproquement
    • exception: si une clé de tableau peut être absent du json, cela equivaut à un tableau vide
  • chaque clé dans un array du json ne peut être utilisée que dans la boucle correspondante du scénario
  • dans le cas d'une clé dont la valeur est une string, la ligne du scenario utilisant cette clé devra être terminée par " // commentaire" afin d'autoriser les valeurs contenant la sous-chaine '//'

Remarque:

  • l'option -j avec un json sans valeur de type array (LOOP) ou boolean (IF) est équivalente à l'option -r utilisée autant de fois qu'il y a de paires clé/valeur dans le json
    • cela permet de passer très simplement du paramétrage basique par -r au paramétrage avancé par -j

Exemple d'utilisation

Scénario en entrée:

ClassManagement.OpenFile // Open...
ClassFileName __dictionaryFile__ // Dictionary file
OK // Open
ClassManagement.ClassName __dictionaryName__

LOOP __dataTables__
TrainDatabase.DatabaseFiles.List.Key __dataPath__
TrainDatabase.DatabaseFiles.DataTableName __dataFile__
END LOOP

TrainDatabase.SampleNumberPercentage __trainPercentage__  // Sample percentage

IF __detectFormat__
TrainDatabase.DatabaseFormatDetector.DetectFileFormat
END IF

AnalysisSpec.TargetAttributeName __targetName__
ComputeStats // Analyse database

Exit // Close
OK // Close

Fichier json en entrée:

{
  "dictionaryFile": "./SpliceJunction/SpliceJunction.kdic",
  "dictionaryName": "SpliceJunction",
  "dataTables": [
    {
      "dataPath": "SpliceJunction",
      "dataFile": "./SpliceJunction/SpliceJunction.txt"
    },
    {
      "dataPath": "SpliceJunction`DNA",
      "dataFile": "./SpliceJunction/SpliceJunctionDNA.txt"
    }
  ],
  "detectFormat": true,
  "trainPercentage": 10,
  "targetName": "Class"
}

Scénario en sortie:

ClassManagement.OpenFile // Open...
ClassFileName ./SpliceJunction/SpliceJunction.kdic // Dictionary file
OK // Open
ClassManagement.ClassName SpliceJunction

TrainDatabase.DatabaseFiles.List.Key SpliceJunction
TrainDatabase.DatabaseFiles.DataTableName ./SpliceJunction/SpliceJunction.txt
TrainDatabase.DatabaseFiles.List.Key SpliceJunction`DNA
TrainDatabase.DatabaseFiles.DataTableName ./SpliceJunction/SpliceJunctionDNA.txt

TrainDatabase.SampleNumberPercentage 10  // Sample percentage

TrainDatabase.DatabaseFormatDetector.DetectFileFormat

AnalysisSpec.TargetAttributeName Class
ComputeStats // Analyse database

Exit // Close
OK // Close

Encodage des valeurs dans le json

Analyse des besoins et contraintes

Khiops accepte tout types de valeurs en entrée, ce qui permet d'être applicable à toutes sources de données. Cela impose des scénario qui sont sont encodés sous formes de bytes (et non UTF-8 par exemple), ce qui permet par exemple:

  • de gérer des noms de fichiers quelconques (par exemple, sous linux, un nom de fichier est une séquence de bytes)
  • de gérer des noms de variables de base de données ou de valeurs encodées en Ansi étendu, et non en UTF-8

Comme la structure json comporte une liste de clés/valeurs, les valeurs doivent donc pouvoir comporter n'importe quelle séquence de bytes.

Khiops doit décoder les valeurs des clés du json en paramètre pour les transformer en chaines de caractères C++, qui sont des tableau de bytes. Il est donc nécessaire de spécifier comment les valeurs sont encodées, au dela du format UTF-8.

Selon la spécification de json https://datatracker.ietf.org/doc/html/rfc8259#section-8.1, on peut éventuellement utiliser le format json sans respecter l'encodage UTF-8, puisque l'on se trouve dans l'éco-système fermé Khiops.

8.1. Character Encoding

JSON text exchanged between systems that are not part of a closed ecosystem MUST be encoded using UTF-8 [RFC3629].

Previous specifications of JSON have not required the use of UTF-8 when transmitting JSON text. However, the vast majority of JSON- based software implementations have chosen to use the UTF-8 encoding, to the extent that it is the only encoding that achieves interoperability.

Choix d'encodage

On choisit un encodage UTF-8 systématique pour le json en paramètre de Khiops, selon la norme Json. Dans le cas de paramètres dont les valeurs peuvent être soit des strings UTF-8, soit des chaines de bytes, on étend le format json de la façon suivantes. Pour un paramètre concerné (ex: dataPath):

  • le fichier scénario reste inchangé, avec utilisation de __dataPath__
  • le fichier json en paramètre peut comporter les deux variantes de la valeurs
    • chaine de caractères UTF-8: nom de la variable et valeur sans encodage
      • exemple: "dataPath" = "UTF-8 string value"
    • chaine de bytes: nom de la variable préfixé par byte, la première lettre du nom de la variable en majuscule, et valeur avec encodage Base64

Au moment de l'écriture du scénario en sortie, on recherche la clé correspondante dans le json ou sa variante avec préfixe byte pour décoder ou non la valeur dans le search/replace.

Contraintes spécifique sur la structure du json:

  • chaque clé associé à une valeur chaine de caractères, et présente dans le scénario, doit exister sous une seule des deux variantes, avec ou sans préfixe byte.

Choix d'implémentation principaux

Choix techniques avec impacts utilisateur:

  • le fichier de paramètre json est lu et traite en entier de façon préalable, avec une taille limitée à 1 Mb
  • le fichier de commande est traite en flux, ce qui permet de n'avoir aucune limite de taille
    • le nombre de liges non vides d'une structure LOOP ou IF est limité à 1000
  • toute ligne de commande peut être commentée, y compris les lignes du langage de pilotage de type IF ou LOOP
  • les lignes d'un fichier de commande template n'ont pas besoin de se terminer par un commentaire
  • toute key du fichier de commande doit se trouver dans le fichier json
  • toute key du fichier json doit être utilisée dans le fichier de commande
  • les key de paramétrage json ne peuvent concerner que la partie paramétrage utilisateur d'une valeur
  • toute erreur ou incohérence dans les fichiers de commande et de paramétrage json provoquent une erreur fatale

Remarques

Liens avec protobuf

  • cf. https://protobuf.dev/
  • les choix effectués pour le pilotage de Khiops via des scénarios et json ont été évalués avec l'utilisation de protobuf
  • une sous-utilisation de protobuf compatible avec la spécification ci-dessous parait pertinente
    • permet de produire une API de sérialisation de paramètres de méthode utilisable en pratique
    • permet de produire des json dans un format directement utilisable