UNC-RENCI-KGAI/croissant-semantics

Ajoute de la sémantique (ce que signifient les données) à un fichier de métadonnées Croissant existant pour une base de connaissances biomédicale — regroupe les colonnes en entités typées (gènes, maladies, ...), type les lignes comme des associations Biolink, marque les préfixes d'identifiants, unités et valeurs de codes — en utilisant uniquement les constructions Croissant 1.1, et vérifie le résultat par rapport aux données réelles.

Qu'est-ce que croissant-semantics ?

Cette compétence transforme un fichier Croissant décrivant la structure (colonnes, fichiers) d'une base de connaissances en un fichier sémantiquement enrichi utilisant Croissant 1.1 et les types Biolink. Elle permet de définir ce que signifient les données : quelles colonnes décrivent une entité comme un gène ou une maladie, ce qu'affirme chaque ligne (association), quels préfixes d'identifiants sont utilisés, et ce que représentent les codes. La compétence fonctionne via un plan JSON généré par l'IA, qui est ensuite appliqué et vérifié par des scripts dédiés sans édition manuelle du fichier Croissant. Supportée par une suite de scripts (inventaire, échantillonnage, détection des dialectes de fichiers, recherche dans Biolink), elle vérifie la cohérence sémantique par rapport aux données réelles et produit un rapport de vérification. Elle s'applique particulièrement aux bases de connaissances biomédicales utilisant des formats comme CSV, TSV, VCF, GAF ou MITAB.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/UNC-RENCI-KGAI/KGB-CIA/tree/HEAD/.agents/skills/metadata/croissant-semantics

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Ajouter de la sémantique à un croissant

Un fichier RoboCroissant liste les fichiers d'une base de connaissances et les colonnes qu'ils contiennent. Cette compétence ajoute ce que les données signifient : quelles colonnes décrivent ensemble un gène ou une maladie, ce qu'affirme une ligne, quel préfixe d'identifiant les identifiants d'une colonne utilisent, ce que représentent les codes. Elle écrit cela dans un nouveau croissant en utilisant les constructions Croissant 1.1, et enregistre pourquoi chaque déclaration a été faite.

Vous produisez un plan (JSON, par disposition), les scripts l'appliquent et le vérifient. Vous ne modifiez pas le croissant à la main.

Entrées et sorties

  • Entrée : un croissant (croissant.json ou croissant.json.gz) et un répertoire de sortie, plus le fichier semantics_answers.json des mainteneurs à côté du croissant, s'il existe.
  • Sortie, dans le répertoire de sortie :
    • semantics_plan.json — le plan (format : reference/plan-format.md)
    • croissant.semantic.json (ou .json.gz si l'entrée était compressée) — le résultat
    • check_report.md — la sortie de check.py (et check_report.load_errors.txt, erreurs mlcroissant complètes, lorsque le chargement des enregistrements a échoué)
    • notes.md — décisions, dispositions omises et pourquoi, et questions pour les mainteneurs de la base de connaissances

Le croissant d'entrée n'est jamais modifié. Placez les téléchargements, scripts d'aide et autres travaux temporaires dans OUT/work/, pas ailleurs.

Scripts

Tous dans scripts/, exécutés directement (ce sont des fichiers uv run --script qui installent leurs propres dépendances). Utilisez --help sur n'importe lequel d'entre eux.

ScriptUtilisation
inventory.py CROISSANT [--layout ID] [--json F] [--common-columns]Lister les dispositions (ensembles de colonnes distincts), du plus grand au plus petit ; décrire les colonnes d'une disposition, les jeux d'enregistrements et les fichiers ; lister les colonnes que la plupart des jeux d'enregistrements partagent
sample.py CROISSANT --layout IDLire des lignes réelles de trois fichiers de la disposition ; montrer les valeurs d'exemple de chaque colonne et leur forme (CURIE et leurs préfixes, identifiants nus, listes, codes)
dialects.py list/show/detect/readFormats de fichiers connus (VCF, GAF, MITAB, CTD, ...) sous forme de dialectes calculables ; lequel lit les fichiers d'une disposition ; lire les enregistrements en utilisant uniquement ce qu'un croissant dit du fichier
vocab.py class/slot/search/associations/prefix/identify/term/ols/inforesRechercher des classes et slots Biolink (avec suggestions de quasi-correspondance), classes d'association pour une paire sujet/objet, préfixes d'identifiants (Biolink + Bioregistry), quels préfixes correspondent à des identifiants nus, termes d'ontologie par identifiant ou texte, et identifiants infores pour les noms de sources
apply_plan.py CROISSANT PLAN OUTÉcrire le plan dans un nouveau croissant
check.py CROISSANT PLAN OUT --report R --load-records--plan-only d'abord : termes, préfixes, dialectes et unités en secondes. Puis la vérification complète : vérifie les termes, préfixes, codes et dialectes par rapport à Biolink et aux données échantillonnées, exécute le validateur MLCommons, lit quelques enregistrements via mlcroissant (à partir des premières lignes de chaque fichier, pas des téléchargements complets), et rapporte la couverture

Workflow

  1. Enquête. S'il existe un fichier semantics_answers.json à côté du croissant, lisez-le d'abord : il contient les réponses des mainteneurs de la base de connaissances aux questions précédentes (voir "Réponses des mainteneurs" ci-dessous). Ne reposez pas ces questions ; apply_plan.py et check.py appliquent les réponses à votre plan automatiquement. Ensuite, lancez inventory.py CROISSANT. Notez la base de connaissances (nom, description, URL dans le croissant) et comment les jeux d'enregistrements sont répartis entre les dispositions. Les grandes bases de connaissances ont des centaines de dispositions ; travaillez à partir du haut de la liste.

    Trouvez l'identifiant infores de la base de connaissances maintenant (vocab.py infores NOM ; essayez son nom complet, son acronyme et son URL) et définissez-le comme infores du plan. Il nomme la ressource dont ces fichiers sont issus, et les constructeurs de graphes la citent comme source de tout ce qui est lu à partir d'eux : sans elle, l'étape de transformation ne construira pas la base de connaissances du tout. Lorsque plusieurs entrées correspondent, choisissez celle pour la ressource qui publie ces fichiers, pas un service qui la rediffuse (infores:reactome, pas infores:automat-reactome). check.py la compare avec ce que le reste de votre plan dit : un agrégateur unique ou une constante provided_by nomme la base de connaissances aussi (les orthologues de HCOP sont agrégés par infores:hgnc), et une discordance est un avertissement à résoudre.

    Lorsqu'aucune ne correspond, proposez-en une : infores: et le nom court de la base de connaissances en minuscules mots séparés par des tirets (infores:bioplex, infores:expression-atlas), avec "infores_proposed": true dans le plan. Ensuite, écrivez son entrée de catalogue avec vocab.py infores-entry CROISSANT --id infores:NOM, en ajoutant --knowledge-level et --agent-type lorsque la documentation les rend clairs, et placez-la dans notes.md sous un en-tête Identifiant infores à enregistrer, près du haut. Dites-y que l'utilisateur doit l'enregistrer avec une pull request vers le registre infores (la commande imprime où), et que l'identifiant peut changer lors de la relecture. check.py conserve un avertissement sur un identifiant proposé jusqu'à ce qu'il soit enregistré ; ne l'expliquez pas.

  2. Choisissez les dispositions à traiter. Visez les dispositions qui couvrent le plus de jeux d'enregistrements et le contenu central (associations et les principales tables d'entités) — généralement les 5 à 15 premières, ou jusqu'à ce que les dispositions restantes soient mineures (fichiers de type readme, logs, comptages par version). S'il y a de nombreuses petites dispositions (inventory.py le dira), les jeux d'enregistrements partagent probablement des colonnes centrales : utilisez inventory.py --common-columns et planifiez ces colonnes une fois avec match.has_columns. Tout ce que vous omettez va dans la liste skipped du plan avec une raison. Faire moins de dispositions bien est mieux que beaucoup mal.

  3. Pour chaque disposition, regardez les données avant de décider quoi que ce soit.

    • inventory.py CROISSANT --layout ID pour les colonnes, descriptions et noms de fichiers. Une colonne marquée MIXED a des types atomiques différents dans différents jeux d'enregistrements (le pipeline les infère par fichier) ; décidez de son type à partir des données et définissez atomic.
    • Pour les tables, dialects.py detect CROISSANT --layout ID trouve comment les fichiers sont écrits (lignes de commentaire, en-tête ou non, délimiteur) parmi les formats connus. Les formats bien connus (VCF, GAF, MITAB) ont des spécifications publiées ; appuyez-vous sur elles plutôt que de redécouvrir le format. Si rien ne correspond, décrivez le dialecte en ligne (reference/dialects.md). Ensuite, échantillonnez avec --dialect NOM afin que les lignes soient lues comme le format le dit, pas deviné.
    • sample.py CROISSANT --layout ID pour les valeurs réelles. Il lit trois fichiers de la disposition (le plus récent par son nom, le plus grand, le plus petit), car un seul fichier — souvent un ancien instantané ou un sous-ensemble filtré — peut cacher des valeurs (placeholders N/A, valeurs de code supplémentaires, autres types d'identifiants). --files N en échantillonne davantage ; --record-set ID échantillonne un fichier particulier. Si l'échantillonnage échoue (un fichier énorme, une archive, un ensemble de fichiers), dites-le dans la basis du plan et réduisez la confiance.
    • Pour les colonnes de code (types, preuves, relations, sources), un échantillon manque les valeurs rares. sample.py CROISSANT --record-set ID --profile COL1,COL2 lit le fichier entier et compte chaque valeur distincte ; répétez --record-set pour additionner plusieurs fichiers. Mappez à partir du profil, pas de l'échantillon.
    • Soyez gentil avec les serveurs de la base de connaissances. Exécutez une commande d'échantillonnage ou de vérification à la fois par base de connaissances, jamais plusieurs en parallèle : les hôtes bloquent les rafales avec un défi anti-bot, puis chaque requête ultérieure échoue. Les scripts espacent leurs propres requêtes et mettent en cache les téléchargements (dans ~/.cache/croissant-semantics/downloads ; --refresh télécharge à nouveau), donc ré-exécuter est peu coûteux (une copie mise en cache sous un plus grand --max-mb sert un plus petit). Si un script signale un défi anti-bot ou une erreur HTTP 403, arrêtez d'échantillonner cet hôte, n'essayez pas de le contourner, et dites dans notes.md quelles vérifications n'ont pas pu être exécutées. Les scripts refusent alors cet hôte pendant une heure, entre les exécutions, et travaillent à partir des fichiers en cache.
    • Les feuilles de calcul (xlsx et legacy xls), les bases de données SQLite et les fichiers parquet sont également échantillonnés et profilés : la feuille ou la table est celle dont le nom du jeu d'enregistrements se termine ("fichier.xlsx — Sheet1", "fichier.xlsx : Sheet1"), et l'échantillonnage échoue plutôt que de deviner quand il ne peut pas dire. Ils sont lus en entier, donc augmentez --max-mb si nécessaire (sur check.py également). mlcroissant ne peut pas lire les feuilles de calcul ou les bases de données, donc leurs enregistrements ne sont pas chargés.
    • XML, RDF (Turtle, RDF/XML, OWL), FASTA et autres fichiers qui ne sont pas des tables ne peuvent pas être échantillonnés : les scripts le disent. Si une disposition est importante, vérifiez ses identifiants avec un petit script dans OUT/work/ (uv run --with rdflib pour RDF ; diffusez XML avec xml.etree.ElementTree.iterparse), et dites comment dans notes.md. Leurs champs n'ont généralement pas d'extract, donc aucun outil ne peut les lire : un problème de générateur à signaler.
    • --profile avec --layout profile --files jeux d'enregistrements de la disposition (par défaut 3, ou all) au lieu de nommer chacun avec --record-set. --prefixes compte le préfixe ou la balise de chaque valeur, pour toutes les colonnes profilées ou seulement celles listées (--prefixes COL1,COL2) ; --by COL tabule croisé avec une autre colonne (quels types d'objets chaque code apparaît avec) ; --split SEP compte les éléments des cellules de liste ; --per-file profile chaque jeu d'enregistrements séparément (pour vérifier que les identifiants sont uniques par fichier) ; --stop-mb N arrête chaque fichier après N Mo, pour des fichiers de plusieurs Go (les comptages ne couvrent alors que le début ; dans un fichier trié par espèce ou identifiant, cela peut être un seul groupe, donc dites-le).
    • Profilez les colonnes d'identifiants des dispositions principales (--profile COL --shapes) avant de leur faire confiance : la vérification des données lit les premières lignes de quelques fichiers, donc une colonne dont les lignes ultérieures manquent d'identifiants, ou contiennent une autre famille d'identifiants, la passe. Plusieurs bases de connaissances avaient 20 à 30 % de lignes sans identifiant après des centaines de lignes qui en avaient toutes un.
    • Une entrée match.has_columns qui couvre de nombreuses dispositions est échantillonnée par check.py sur seulement quelques-uns de ses fichiers. Échantillonnez les dispositions qu'elle couvre qui diffèrent (--record-set-name, --files) avant de lui faire confiance.
    • Les scripts utilisent le magasin de certificats du système d'exploitation. Si les téléchargements échouent encore avec une erreur de certificat, signalez-la avec la sortie ; ne désactivez pas la vérification.
    • Si la documentation est derrière une vérification anti-bot ("verify you are human", un défi Cloudflare ou ALTCHA), n'essayez pas de la contourner ; planifiez à partir des données et des noms, et plafonnez la confiance à medium pour les significations que seule la documentation pourrait confirmer. La provenance du croissant peut citer des pages qui ont depuis été mises derrière une vérification : citez seulement ce que vous avez pu lire.
    • Dans un fichier volumineux, les premières lignes peuvent ne pas être représentatives (le fichier genes_diseases de 3 Go de CTD commence avec des milliers de lignes inférées). Profilez un fichier plus petit de la même disposition (le sous-ensemble curé) plutôt que de diffuser l'ensemble.
    • Pour sélectionner des jeux d'enregistrements par nom, utilisez --record-set-name REGEX (au lieu de --layout) plutôt que de construire une liste d'arguments --record-set dans le shell (zsh ne divise pas les variables en mots). --per-file montre chaque fichier échantillonné séparément, pour les dispositions dont les fichiers diffèrent (un type d'identifiant par fichier).
    • La vérification des données lit les premières lignes de quelques fichiers. Les lignes ultérieures d'une colonne peuvent différer (nœuds blancs après 200 IRI, un code rare) : confirmez les formes d'identifiants et les codes avec --profile, qui lit les fichiers entiers.
    • inventory.py liste les fichiers de documentation livrés avec les données (README.pdf dans un zip, un dictionnaire de données) après les dispositions. Lisez ceux qui sont pertinents : sample.py CROISSANT --dump FICHIER imprime un fichier sous forme de texte, --member NOM un membre d'une archive (un zip est lu en entier, donc augmentez --max-mb pour un gros) (il liste les membres d'un zip lorsque le nom est incorrect), --sheet NOM une feuille d'un tableur.
    • sample.py signale les colonnes dont le type déclaré ne correspond pas aux valeurs (une colonne sc:Integer contenant 27152464|29518214) et les fichiers dont les lignes sont plus larges ou plus étroites que l'en-tête. Les deux sont généralement des problèmes de pipeline : corrigez les types avec atomic, et signalez-les.
    • Lorsque les scripts ne peuvent pas lire une source, récupérez les fichiers vous-même (un à la fois, dans OUT/work/) et pointez les scripts vers eux avec --url-map OLD=file:///abs/path/ afin que leurs vérifications puissent toujours s'exécuter, plutôt que d'écrire vos propres profileurs. Les téléchargements sont mis en cache, et ~/.cache/croissant-semantics/downloads/index.tsv mappe chaque fichier en cache à son URL.
    • Si les "noms de colonnes" d'une disposition sont en réalité des données (pas de ligne d'en-tête, donc le pipeline a pris la première ligne de données comme noms, et chaque fichier est devenu sa propre disposition), ignorez-la et signalez-la dans notes.md comme un problème de pipeline.
    • Si les URL des données sont absentes (HTTP 404), la base de connaissances est probablement passée à une version plus récente. Trouvez les URL actuelles depuis sa page de téléchargement et passez --url-map OLD=NEW à sample.py et check.py (par exemple --url-map 202607=202610). Lorsque plus que la version a changé (un autre chemin ou nom de fichier), mappez les URL entières, un --url-map OLD_URL=NEW_URL par fichier. Lorsque les URL elles-mêmes contiennent = (chaînes de requête), écrivez OLD=>NEW. Dites-le dans notes.md ; c'est aussi un problème de pipeline. Une URL de point d'accès SPARQL qui renvoie du JSON alors que le croissant décrit une table nécessite généralement &format=csv (ou text/csv) mappé.
    • Archives : les membres des archives zip et tar sont échantillonnés. Un zip est téléchargé en entier (jusqu'à --max-mb) ; un tar est diffusé jusqu'à ce que le membre soit trouvé, donc un membre profondément dans un énorme tar peut dépasser --max-mb. Une archive qui échoue une fois n'est pas réessayée, et l'échantillonnage s'arrête après des échecs répétés. Si vous le devez, extrayez un membre dans OUT/work/ vous-même, et enregistrez ce que vous avez vérifié et comment dans notes.md.
    • Si les données nécessitent une connexion ou une clé API (HTTP 401/403, ou le conditionsOfAccess du croissant le dit), ne cherchez pas d'identifiants. Planifiez à partir de la documentation et des noms de colonnes uniquement : source est documentation ou agent, confidence au plus medium, et notes.md dit que rien n'a été vérifié par rapport aux données.
    • Cherchez un da

[Le contenu a été tronqué pour la traduction]

Skills associés