La ontología EKG
Cuento aquí cómo diseñé la ontología educativa que sostiene el resto del proyecto. Es un modelo del dominio "programación en Python" pensado para enseñar, no para inventariar. Lo construí con un perfil OWL 2 RL sobrio, me apoyé en SKOS para la red de conceptos y delegué la integridad de los datos en SHACL, una decisión que me recomendó el profesor y que explico más abajo.
1Cómo diseñé la ontología
El grafo educativo de conocimiento (EKG, por sus siglas en inglés) modela lo que un estudiante de Python necesita aprender y en qué orden. Reúne 157 conceptos repartidos en 16 temas, desde los fundamentos hasta algoritmos, programación orientada a objetos y concurrencia. Lo formalicé en RDF/OWL bajo el perfil OWL 2 RL, que me da la inferencia que necesito (sobre todo el cierre de relaciones transitivas como los prerrequisitos) sin pagar el coste de un razonamiento más expresivo que aquí no hacía falta.
La idea de partida fue mantener el esquema pequeño y legible. Un puñado de clases bien elegidas y una colección de propiedades con nombres en español me bastan para describir el dominio. Cada concepto declara su tema, su nivel de dominio, su dificultad estimada en una escala de 1 a 5 y sus prerrequisitos, y muchos llevan además su enlace a Wikidata. Sobre esa base se montan después los sistemas C y D, que recuperan subgrafos de este modelo para dar contexto al lenguaje generador.
Elegí OWL 2 RL porque es el perfil que mejor se lleva con un razonamiento basado en reglas y con grafos grandes. Me permite materializar la inferencia (por ejemplo, los prerrequisitos indirectos a partir de los directos) de forma eficiente, que es justo lo que el recuperador del RAG aprovecha al expandir el subgrafo de un concepto.
2El esquema: clases y propiedades
El vocabulario propio vive bajo el espacio de nombres pyedu:
(https://w3id.org/ekg-python/schema#). Está deliberadamente contenido, con
20 clases, 21 propiedades de objeto y 7 propiedades de datos.
Las cifras de la tabla siguiente son las del artefacto canónico recertificado con rdflib, owlrl y pyshacl.
| Elemento del esquema | Cantidad |
|---|---|
Clases (owl:Class) | 20 |
Propiedades de objeto (owl:ObjectProperty) | 21 |
Propiedades de datos (owl:DatatypeProperty) | 7 |
Conceptos modelados (skos:Concept) | 157 |
Temas curriculares (pyedu:Tema) | 16 |
Errores conceptuales (pyedu:ErrorConceptual) | 16 |
Las clases se dividen en dos familias. Por un lado están las que describen conocimiento —subclases de
pyedu:Concepto, que a su vez es subclase de skos:Concept—, como los tipos de dato, las
estructuras de datos, las estructuras de control, los módulos, los paradigmas y los principios transversales. Por
otro lado están las que describen el contexto educativo —subclases de pyedu:EntidadEducativa—,
como el tema curricular, el ejercicio, el estudiante, el envío de código o el error conceptual. Las propiedades de
objeto enlazan unas con otras (por ejemplo pyedu:requierePrerrequisito, pyedu:perteneceATema
o pyedu:contrastaCon) y las de datos llevan los literales (dificultad, número de líneas, fecha, nota).
3La jerarquía conceptual
El corazón del modelo es pyedu:Concepto. Lo declaré como subclase de skos:Concept
para poder colgar de él la red conceptual de SKOS sin reinventarla. De Concepto cuelgan
siete subclases que clasifican cada unidad de conocimiento según su naturaleza, y en paralelo
pyedu:EntidadEducativa agrupa las entidades del entorno docente que no son conceptos en sí. El diagrama
siguiente resume esa doble jerarquía.
pyedu:Concepto hereda de skos:Concept
y se subdivide en siete tipos de conocimiento; la rama de pyedu:EntidadEducativa recoge las entidades
del entorno docente. Representación esquemática con la paleta del proyecto.4La red SKOS
Al heredar de skos:Concept, cada concepto admite la malla de relaciones de SKOS sin que yo tenga que
definirlas. Uso las tres clásicas. skos:broader y skos:narrower dan la jerarquía
conceptual (lo general frente a lo específico) y skos:related marca las asociaciones laterales entre
conceptos que no son uno más amplio que el otro. Esta capa SKOS convive con las relaciones propias del dominio,
como los prerrequisitos o los contrastes, y le da al grafo una estructura navegable y reutilizable.
| Relación | Papel | Recuento |
|---|---|---|
skos:broader / skos:narrower | jerarquía conceptual (general ↔ específico) | 19 |
skos:related | asociación lateral entre conceptos | 16 |
skos:exactMatch | enlace verificado a Wikidata | 30 |
El enlazado externo lo hago con skos:exactMatch y no con owl:sameAs, también a
propósito. Con exactMatch el razonador OWL 2 RL no fusiona mi concepto con la entidad de Wikidata, de
modo que la consulta de conceptos propios sigue devolviendo exactamente 157 y el modelo no se contamina con las
aserciones externas.
5Por qué la integridad la lleva SHACL
Una decisión de diseño importante, que me indicó el profesor, fue no cargar el esquema OWL con dominios
y rangos rígidos y delegar la validación de integridad en SHACL. La razón es que en OWL un
rdfs:domain o un rdfs:range no actúan como una restricción que rechace datos. Bajo
semántica de mundo abierto, el razonador los infiere en lugar de avisar de un fallo. Si los uso de forma
estricta, en vez de detectar un dato mal puesto acabo deduciendo clasificaciones que no quería.
SHACL hace justo lo contrario y es lo que necesito para validar. Las formas SHACL describen qué debe cumplir un dato conforme y, cuando algo no encaja, lo señalan como violación en lugar de inferir en silencio. Por eso la integridad del grafo se comprueba con ese mecanismo y el esquema OWL queda más ligero y centrado en el significado.
La frontera es clara. OWL 2 RL se ocupa del significado y de la inferencia que sí quiero (prerrequisitos transitivos, jerarquía de conceptos). SHACL se ocupa de la integridad y comprueba la conformidad de los datos para reportar lo que no cumple. El grafo canónico pasa esa validación sin violaciones, mientras que un ejemplo deliberadamente mal construido sí dispara violaciones. Mantener ambas capas separadas hace el modelo más sano que apretar todo dentro de OWL.
6El fichero canónico
Todo lo anterior vive en un único fichero Turtle, ekg-python-150.ttl, que es el entregable canónico
del grafo. Contiene 1772 triples afirmados; al aplicar el cierre OWL 2 RL crecen hasta
4786, que es donde aparecen los prerrequisitos indirectos y el resto de la inferencia. Existe
además un grafo base más pequeño y didáctico que conservo como núcleo legible, pero el modelo que sostiene el
proyecto es este.
| Magnitud | Valor | Objetivo del anteproyecto |
|---|---|---|
| Conceptos (sin inferencia) | 157 | ≥150 |
| Triples afirmados | 1772 | ≥600 |
| Triples tras cierre OWL 2 RL | 4786 | ≥1500 |
| Validación SHACL | Conforme (0 violaciones) | Sí |
Enlaces skos:exactMatch a Wikidata | 30 | ≥15 |
Con 157 conceptos y 1772 triples afirmados, el grafo cumple el objetivo O1 del anteproyecto (al menos 150 conceptos y un volumen amplio de relaciones) y supera con holgura los mínimos de triples, conceptos enlazados y validación. Es la cifra del artefacto vigente; la recalculo tras cada cambio del grafo.
7Ver también
El grafo de conocimiento
La grafoteca interactiva, las consultas SPARQL, las serializaciones y el grafo completo de los 157 conceptos.
El sistema RAG
Cómo los sistemas C y D recuperan subgrafos de esta ontología para dar contexto al modelo generador.
Resultados
Las métricas de evaluación de los cuatro sistemas, en distribución y sobre código real de estudiantes.
Si este trabajo te resulta útil y quieres referenciarlo, esta es la cita recomendada.
Bueno Junquero, A. (2026). Integración de un grafo de conocimiento educativo con un LLM mediante RAG. Trabajo Fin de Máster, Máster Universitario en Investigación en Inteligencia Artificial, UNED. Director, José Luis Fernández Vindel.