CommunityProgramación y desarrollogithub.com

UNC-RENCI-KGAI/croissant-semantics

Añade semántica (qué significan los datos) a un archivo de metadatos Croissant existente para una base de conocimiento biomédica — agrupa columnas en entidades tipadas (genes, enfermedades...), tipa filas como asociaciones Biolink, marca prefijos de identificadores, unidades y valores de código — usando solo constructos de Croissant 1.1, y verifica el resultado contra los datos reales. Se usa cuando se te pida añadir semántica, tipos Biolink, prefijos de identificadores o estructura de entidad/asociación a un croissant.json.

¿Qué es croissant-semantics?

Esta habilidad para agentes de IA se especializa en enriquecer semánticamente archivos de metadatos Croissant (RoboCroissant) para bases de conocimiento biomédicas, añadiendo capas de significado que permiten a los sistemas de IA comprender qué representan los datos: qué columnas describen genes, enfermedades u otras entidades; qué tipo de asociación Biolink representa cada fila; qué prefijo de identificador (basado en Bioregistry) usan las columnas de IDs; o qué significan los códigos, unidades y valores de vocabulario controlado. Está diseñada para las plataformas Claude Code (Anthropic), Cursor y Codex (similar a Claude Code). Funciona generando un plan (semantics_plan.json) estructurado en JSON, que luego scripts automatizados aplican y verifican. El agente produce un plan detallado donde especifica layouts (conjuntos distintos de columnas), asigna tipos de entidad y asociación Biolink, asocia prefijos de identificadores a columnas usando vocabulario.py, define unidades, valores de código y dialectos de archivo, y registra la confianza en cada decisión (alta/media/baja) con la fuente que la respalda (datos de ejemplo, documentación, preguntas al mantenedor, etc.). El plan luego se aplica con apply_plan.py para generar un croissant semántico enriquecido, y check.py lo verifica contra Biolink, contra los datos muestreados, ejecuta el validador MLCommons, y reporta cobertura y errores. La habilidad maneja formatos complejos (TSV, CSV, VCF, GAF, MITAB, CTD, XML, RDF, FASTA, hojas de cálculo Excel, bases de datos SQLite, archivos Parquet) y transfiere cuidadosamente entre URLs desactualizadas y nuevas, gestionando cachés de descarga y respetando límites de servidores. El agente también gestiona preguntas a mantenedores cuando no puede determinar semántica de forma autónoma, y propone nuevos IDs infores (identificadores de fuentes de información de Biolink) que deben registrarse mediante pull request en el registro infores. El resultado final incluye un croissant semántico verificado, un reporte de revisión (check_report.md) y notas (notes.md) con decisiones, preguntas sin respuesta y problemas del pipeline.

Compatible con~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 Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Añadir semántica a un croissant

Un archivo RoboCroissant indica qué archivos tiene una base de conocimiento y qué columnas contienen. Esta habilidad añade qué significan los datos: qué columnas juntas describen un gen o una enfermedad, qué afirma una fila, qué prefijo de identificador usan los ids de una columna, qué representan los códigos. Lo escribe en un nuevo croissant usando constructos de Croissant 1.1, y registra por qué se hizo cada afirmación.

Produces un plan (JSON, por layout), los scripts lo aplican y verifican. No editas el croissant manualmente.

Entradas y salidas

  • Entrada: un croissant (croissant.json o croissant.json.gz) y un directorio de salida, más el archivo semantics_answers.json de los mantenedores junto al croissant, si existe.
  • Salida, en el directorio de salida:
    • semantics_plan.json — el plan (formato: reference/plan-format.md)
    • croissant.semantic.json (o .json.gz si la entrada estaba comprimida con gzip) — el resultado
    • check_report.md — salida de check.py (y check_report.load_errors.txt, errores completos de mlcroissant, cuando los registros no se pudieron cargar)
    • notes.md — decisiones, layouts omitidos y por qué, y preguntas para los mantenedores de la base de conocimiento

El croissant de entrada nunca se modifica. Coloca las descargas, scripts auxiliares y otros trabajos temporales en OUT/work/, no en otro lugar.

Scripts

Todos en scripts/, se ejecutan directamente (son archivos uv run --script e instalan sus propias dependencias). Usa --help en cualquiera de ellos.

ScriptUso
inventory.py CROISSANT [--layout ID] [--json F] [--common-columns]Lista layouts (conjuntos de columnas distintos), los más grandes primero; describe las columnas de un layout, los conjuntos de registros y archivos; lista las columnas que comparten la mayoría de los conjuntos de registros
sample.py CROISSANT --layout IDLee filas reales de tres de los archivos del layout; muestra los valores de ejemplo de cada columna y su forma (CURIEs y sus prefijos, ids simples, listas, códigos)
dialects.py list/show/detect/readFormatos de archivo conocidos (VCF, GAF, MITAB, CTD, ...) como dialectos computables; cuál lee los archivos de un layout; lee registros usando solo lo que un croissant dice sobre el archivo
vocab.py class/slot/search/associations/prefix/identify/term/ols/inforesBusca clases y slots de Biolink (con sugerencias de aproximación), clases de asociación para un par sujeto/objeto, prefijos de identificador (Biolink + Bioregistry), qué prefijos se ajustan a ids simples, términos de ontología por id o texto, e ids infores para nombres de fuente
apply_plan.py CROISSANT PLAN OUTEscribe el plan en un nuevo croissant
check.py CROISSANT PLAN OUT --report R --load-records--plan-only primero: términos, prefijos, dialectos y unidades en segundos. Luego la verificación completa: verifica términos, prefijos, códigos y dialectos contra Biolink y los datos muestreados, ejecuta el validador MLCommons, lee algunos registros a través de mlcroissant (de las primeras líneas de cada archivo, no de descargas completas), y reporta cobertura

Flujo de trabajo

  1. Exploración. Si hay un semantics_answers.json junto al croissant, léelo primero: contiene las respuestas de los mantenedores de la base de conocimiento a preguntas anteriores (ver "Respuestas del mantenedor" más abajo). No hagas esas preguntas de nuevo; apply_plan.py y check.py aplican las respuestas a tu plan automáticamente. Luego inventory.py CROISSANT. Anota la base de conocimiento (nombre, descripción, url en el croissant) y cómo se distribuyen los conjuntos de registros entre los layouts. Las bases de conocimiento grandes tienen cientos de layouts; trabaja desde la parte superior de la lista.

    Encuentra el id infores propio de la base de conocimiento ahora (vocab.py infores NAME; prueba su nombre completo, su acrónimo y su url) y establécela como infores del plan. Identifica el recurso cuyos archivos son estos, y los constructores de grafos lo citan como la fuente de todo lo leído de ellos: sin él, la etapa de transformación no construirá la base de conocimiento en absoluto. Cuando coincidan varias entradas, elige la del recurso que publica estos archivos, no un servicio que los re-sirve (infores:reactome, no infores:automat-reactome). check.py lo compara con lo que dice el resto de tu plan: un único agregador o constante provided_by también nombra la base de conocimiento (los ortólogos de HCOP son agregados por infores:hgnc), y una discrepancia es una advertencia a resolver.

    Cuando ninguna coincida, propón una: infores: y el nombre corto de la base de conocimiento en minúsculas unido por guiones (infores:bioplex, infores:expression-atlas), con "infores_proposed": true en el plan. Luego escribe su entrada de catálogo con vocab.py infores-entry CROISSANT --id infores:NAME, añadiendo --knowledge-level y --agent-type cuando la documentación los haga claros, y colócala en notes.md bajo un encabezado Id infores a registrar, cerca del principio. Di allí que el usuario debe registrarlo con un pull request al registro infores (el comando imprime dónde), y que el id puede cambiar en la revisión. check.py mantiene una advertencia sobre un id propuesto hasta que esté registrado; no lo expliques.

  2. Elige los layouts a realizar. Apunta a los layouts que cubren la mayoría de los conjuntos de registros y el contenido central (asociaciones y las tablas de entidades principales) — típicamente los 5 a 15 principales, o hasta que los layouts restantes sean menores (archivos tipo readme, logs, recuentos por versión). Si hay muchos layouts pequeños (inventory.py lo dirá), los conjuntos de registros probablemente comparten columnas centrales: usa inventory.py --common-columns y planifica esas columnas una vez con match.has_columns. Todo lo que omitas va en la lista skipped del plan con una razón. Hacer menos layouts bien es mejor que muchos mal.

  3. Para cada layout, mira los datos antes de decidir nada.

    • inventory.py CROISSANT --layout ID para columnas, descripciones y nombres de archivo. Una columna marcada MIXED tiene diferentes tipos atómicos en diferentes conjuntos de registros (el pipeline los infiere por archivo); decide su tipo a partir de los datos y establece atomic.
    • Para tablas, dialects.py detect CROISSANT --layout ID encuentra cómo están escritos los archivos (líneas de comentario, cabecera o ninguna, delimitador) entre formatos conocidos. Los formatos conocidos (VCF, GAF, MITAB) tienen especificaciones publicadas; confía en ellas en lugar de redescubrir el formato. Si nada encaja, describe el dialecto en línea (reference/dialects.md). Luego muestra con --dialect NAME para que las filas se lean como dice el formato, no como se adivina.
    • sample.py CROISSANT --layout ID para valores reales. Lee tres archivos del layout (el de nombre más reciente, el más grande, el más pequeño), porque un solo archivo — a menudo una instantánea antigua o un subconjunto filtrado — puede ocultar valores (marcadores de posición N/A, valores de código adicionales, otros tipos de id). --files N muestra más de ellos; --record-set ID muestra un archivo en particular. Si el muestreo falla (un archivo enorme, un archivo comprimido, un conjunto de archivos), dilo en el basis del plan y baja la confianza.
    • Para columnas de código (tipos, evidencia, relaciones, fuentes), una muestra omite valores raros. sample.py CROISSANT --record-set ID --profile COL1,COL2 lee el archivo completo y cuenta cada valor distinto; repite --record-set para sumar varios archivos. Traza el mapa desde el perfil, no desde la muestra.
    • Sé amable con los servidores de la base de conocimiento. Ejecuta un comando de muestreo o verificación a la vez por base de conocimiento, nunca muchos en paralelo: los hosts bloquean ráfagas con un desafío de bot, y entonces cada solicitud posterior falla. Los scripts espacian sus propias solicitudes y almacenan en caché las descargas (en ~/.cache/croissant-semantics/downloads; --refresh descarga de nuevo), por lo que volver a ejecutar es barato (una copia almacenada bajo un --max-mb mayor sirve una más pequeña). Si un script reporta un desafío de bot o un HTTP 403, deja de muestrear ese host, no intentes sortearlo, y di en notes.md qué verificaciones no pudieron ejecutarse. Los scripts entonces rechazan ese host durante una hora, entre ejecuciones, y trabajan desde archivos en caché.
    • Las hojas de cálculo (xlsx y xls heredado), bases de datos SQLite y archivos parquet también se muestrean y perfilan: la hoja o tabla es aquella con la que termina el nombre del conjunto de registros ("archivo.xlsx — Hoja1", "archivo.xlsx: Hoja1"), y el muestreo falla en lugar de adivinar cuando no puede determinarlo. Se leen completos, así que aumenta --max-mb si es necesario (también en check.py). mlcroissant no puede leer hojas de cálculo o bases de datos, por lo que sus registros no se cargan.
    • Los archivos XML, RDF (Turtle, RDF/XML, OWL), FASTA y otros que no son tablas no se pueden muestrear: los scripts lo dicen. Si un layout es importante, verifica sus ids con un pequeño script en OUT/work/ (uv run --with rdflib para RDF; transmite XML con xml.etree.ElementTree.iterparse), y di cómo en notes.md. Sus campos normalmente no tienen extract, por lo que ninguna herramienta puede leerlos: un problema del generador a reportar.
    • --profile con --layout perfila --files conjuntos de registros del layout (por defecto 3, o all) en lugar de nombrar cada uno con --record-set. --prefixes cuenta el prefijo o etiqueta de cada valor, para todas las columnas perfiladas o solo las listadas (--prefixes COL1,COL2); --by COL tabula cruzadamente contra otra columna (con qué tipos de objeto ocurre cada código); --split SEP cuenta los elementos de celdas de lista; --per-file perfila cada conjunto de registros por separado (para verificar que los ids son únicos por archivo); --stop-mb N detiene cada archivo después de N MB, para archivos de muchos GB (los recuentos entonces cubren solo el inicio; en un archivo ordenado por especie o id eso puede ser solo un grupo, así que dilo).
    • Perfila las columnas de id de los layouts principales (--profile COL --shapes) antes de confiar en ellas: la verificación de datos lee las primeras filas de unos pocos archivos, por lo que una columna cuyas filas posteriores carecen de id, o contienen otra familia de id, la pasa. Varias bases de conocimiento tenían entre un 20 y un 30 % de filas sin id después de cientos de filas que todas tenían uno.
    • Una entrada match.has_columns que cubre muchos layouts es muestreada por check.py solo en unos pocos de sus archivos. Muestrea los layouts que abarca que difieren (--record-set-name, --files) antes de confiar en ella.
    • Los scripts usan el almacén de certificados del sistema operativo. Si las descargas aún fallan con un error de certificado, repórtalo con la salida; no desactives la verificación.
    • Si la documentación está detrás de una verificación de bot ("verifica que eres humano", un desafío de Cloudflare o ALTCHA), no intentes sortearlo; planifica a partir de datos y nombres, y limita la confianza a medium para significados que solo la documentación podría confirmar. La procedencia del croissant puede citar páginas que desde entonces se han puesto detrás de una verificación: cita solo lo que pudiste leer.
    • En un archivo enorme, las primeras filas pueden no ser representativas (el archivo genes_diseases de 3 GB de CTD comienza con miles de filas inferidas). Perfila un archivo más pequeño del mismo layout (el subconjunto curado) en lugar de transmitir todo.
    • Para elegir conjuntos de registros por nombre, usa --record-set-name REGEX (en lugar de --layout) en lugar de construir una lista de argumentos --record-set en el shell (zsh no divide variables en palabras). --per-file muestra cada archivo muestreado por separado, para layouts cuyos archivos difieren (un tipo de id por archivo).
    • La verificación de datos lee las primeras filas de unos pocos archivos. Las filas posteriores de una columna pueden diferir (nodos en blanco después de 200 IRIs, un código raro): confirma las formas de id y los códigos con --profile, que lee archivos completos.
    • inventory.py lista los archivos de documentación enviados con los datos (README.pdf dentro de un zip, un diccionario de datos) después de los layouts. Lee los relevantes: sample.py CROISSANT --dump FILE imprime un archivo como texto, --member NAME un miembro de un archivo comprimido (un zip se lee completo, así que aumenta --max-mb para uno grande) (lista los miembros de un zip cuando el nombre es incorrecto), --sheet NAME una hoja de una hoja de cálculo.
    • sample.py marca columnas cuyo tipo declarado no se ajusta a los valores (una columna sc:Integer que contiene 27152464|29518214) y archivos cuyas filas son más anchas o más estrechas que la cabecera. Ambos suelen ser problemas del pipeline: corrige los tipos con atomic, y repórtalos.
    • Cuando los scripts no pueden leer una fuente, obtén los archivos tú mismo (uno a la vez, en OUT/work/) y apunta los scripts a ellos con --url-map OLD=file:///abs/path/ para que sus verificaciones aún se ejecuten, en lugar de escribir tus propios perfiladores. Las descargas se almacenan en caché, y ~/.cache/croissant-semantics/downloads/index.tsv asigna cada archivo en caché a su URL.
    • Si los "nombres de columna" de un layout son realmente datos (sin fila de cabecera, por lo que el pipeline tomó la primera fila de datos como nombres, y cada archivo se convirtió en su propio layout), sáltalo y repórtalo en notes.md como un problema del pipeline.
    • Si las URLs de los datos ya no existen (HTTP 404), la base de conocimiento probablemente ha pasado a una versión más reciente. Encuentra las URLs actuales desde su página de descarga y pasa --url-map OLD=NEW a sample.py y check.py (por ejemplo, --url-map 202607=202610). Cuando ha cambiado más que la versión (otra ruta o nombre de archivo), asigna URLs completas, un --url-map OLD_URL=NEW_URL por archivo. Cuando las URLs mismas contienen = (cadenas de consulta), escribe OLD=>NEW. Dilo en notes.md; también es un problema del pipeline. Una URL de endpoint SPARQL que devuelve JSON donde el croissant describe una tabla normalmente necesita &format=csv (o text/csv) asignado.
    • Archivos comprimidos: se muestrean los miembros de archivos zip y tar. Un zip se descarga completo (hasta --max-mb); un tar se transmite hasta que se encuentra el miembro, por lo que un miembro profundamente anidado dentro de un tar enorme puede exceder --max-mb. Un archivo que falla una vez no se intenta de nuevo, y el muestreo se detiene después de fallos repetidos. Si es necesario, extrae un miembro en OUT/work/ tú mismo, y registra qué verificaste y cómo en notes.md.
    • Si los datos necesitan un inicio de sesión o clave API (HTTP 401/403, o el conditionsOfAccess del croissant lo dice), no busques credenciales. Planifica solo a partir de la documentación y los nombres de columna: source es documentation o agent, confidence como máximo medium, y notes.md dice que no se verificó nada contra los datos.
    • Busca un diccionario de datos (también llamado

Skills relacionados