EKG + RAG/LLM para retroalimentación de códigoTrabajo de Fin de Máster · UNED
Grafos de propiedades

Grafos de propiedades (Neo4j)

Cuento aquí cómo reexpresé el grafo de conocimiento, que en el proyecto vive en RDF/OWL, como un grafo de propiedades etiquetado (LPG) para Neo4j. Lo hice exportando el .ttl canónico a un guion de Cypher, sin tocar el RDF, de modo que ambas representaciones describan el mismo dominio desde dos paradigmas distintos.

Adrián Bueno JunqueroUNED · TFMPágina autocontenida, se abre sin conexión

1El export ekg_lpg.cypher

El artefacto ekg_lpg.cypher se genera desde ekg-python-150.ttl y no modifica el RDF. La idea es directa, cada concepto del grafo pasa a ser un nodo con etiqueta :Concepto y sus atributos (identificador, etiqueta legible, tema, dificultad) viven dentro del nodo como propiedades; las relaciones de prerrequisito y de contraste pasan a ser aristas tipadas entre nodos.

157
nodos :Concepto (sentencias CREATE)
174
aristas :REQUIERE (prerrequisitos)
14
aristas :CONTRASTA (contrastes)
2
tipos de relación exportados

Las cifras coinciden con el grafo canónico, que declara 157 conceptos y, en su malla de prerrequisitos y contrastes, las mismas relaciones que la visualización del EKG. Los conteos de arriba salen de contar las sentencias del propio fichero exportado.

Sentencias CREATE (nodos con propiedades)

Cada nodo se crea con sus propiedades entre llaves. Estos cuatro son literales del export y muestran el patrón completo, incluyendo el caso de python, que es el único concepto sin dificultad.

// EKG-Python como PROPERTY GRAPH (Neo4j/Cypher) — re-expresión del grafo RDF canónico.
// Generado desde ekg-python-150.ttl (no modifica el RDF). Las propiedades viven en el nodo;
// las relaciones de prerrequisito/contraste son aristas tipadas.

CREATE (:Concepto {id:'recursion', label:'Recursión', tema:'Recursión', dificultad:4});
CREATE (:Concepto {id:'busqueda_binaria', label:'Búsqueda binaria', tema:'Complejidad algorítmica', dificultad:4});
CREATE (:Concepto {id:'herencia', label:'Herencia', tema:'Programación orientada a objetos', dificultad:4});
CREATE (:Concepto {id:'python', label:'Python', tema:'Fundamentos'});

Aristas tipadas (MATCH … CREATE)

Las relaciones se crean emparejando dos nodos por su id y tendiendo una arista entre ellos. El export usa :REQUIERE para los prerrequisitos y :CONTRASTA para los contrastes. Estas líneas son literales del fichero.

// Prerrequisitos → aristas :REQUIERE
MATCH (a:Concepto{id:'recursion'}),(b:Concepto{id:'funcion'})
  CREATE (a)-[:REQUIERE]->(b);
MATCH (a:Concepto{id:'busqueda_binaria'}),(b:Concepto{id:'bucle_while'})
  CREATE (a)-[:REQUIERE]->(b);

// Contrastes → aristas :CONTRASTA
MATCH (a:Concepto{id:'recursion'}),(b:Concepto{id:'bucle_for'})
  CREATE (a)-[:CONTRASTA]->(b);
MATCH (a:Concepto{id:'busqueda_lineal'}),(b:Concepto{id:'busqueda_binaria'})
  CREATE (a)-[:CONTRASTA]->(b);

Ejemplos de MATCH para consultar el grafo

Una vez cargado el guion, el grafo de propiedades se interroga con consultas de patrón. Estas son ilustrativas y reproducen, en clave Cypher, recorridos que en el lado RDF resuelvo con SPARQL, por ejemplo los prerrequisitos directos de un concepto o sus contrastes.

// Prerrequisitos directos de la búsqueda binaria
MATCH (c:Concepto{id:'busqueda_binaria'})-[:REQUIERE]->(p:Concepto)
RETURN p.label, p.tema, p.dificultad;

// Cadena de prerrequisitos (transitiva) hacia un concepto base
MATCH (c:Concepto{id:'busqueda_binaria'})-[:REQUIERE*]->(p:Concepto)
RETURN DISTINCT p.label;

// Conceptos que conviene contrastar con la recursión
MATCH (a:Concepto{id:'recursion'})-[:CONTRASTA]->(b:Concepto)
RETURN b.label;

// Conceptos avanzados de cada tema (filtra por propiedad del nodo)
MATCH (c:Concepto)
WHERE c.dificultad >= 4
RETURN c.tema, count(c) AS n
ORDER BY n DESC;

2Un diagrama del grafo de propiedades

Este diagrama esquematiza cómo se ve un fragmento del grafo en el modelo LPG, con las propiedades anidadas en cada nodo y las relaciones tipadas como flechas. Es el mismo subgrafo de la recursión que muestro en la página del grafo, pero dibujado a la manera de Neo4j.

Fragmento del EKG como grafo de propiedades El nodo Concepto "recursion" (tema Recursión, dificultad 4) tiene una arista REQUIERE hacia el nodo "funcion" (tema Funciones, dificultad 2) y una arista CONTRASTA hacia el nodo "bucle_for" (tema Control de flujo, dificultad 2). Las propiedades viven dentro de cada nodo. :REQUIERE :CONTRASTA :Concepto id: 'recursion' tema: 'Recursión' dificultad: 4 :Concepto id: 'funcion' dificultad: 2 :Concepto id: 'bucle_for' dificultad: 2
Modelo LPG, las propiedades (id, tema, dificultad) viven dentro del nodo y las relaciones son aristas tipadas (:REQUIERE, :CONTRASTA). Representación esquemática con la paleta del proyecto.

3RDF frente a grafos de propiedades

Las dos representaciones modelan el mismo dominio, pero con compromisos distintos. En RDF todo es un triple sujeto–predicado–objeto y los atributos de un concepto son también triples; en un LPG los atributos son pares clave-valor que cuelgan del nodo o de la arista. Resumo las diferencias que más pesan en este proyecto.

RDF/OWL (representación canónica del EKG) frente a grafo de propiedades (export Neo4j).
AspectoRDF / OWL 2 RLGrafo de propiedades (LPG)
Unidad básicaTriple sujeto–predicado–objetoNodo y arista con propiedades clave-valor
Atributos de un conceptoTriples con literales (p. ej. pyedu:tieneDificultad 4)Propiedades dentro del nodo (dificultad:4)
Atributos sobre una relaciónRequiere reificación o entidad intermediaPropiedades directas en la arista
IdentificadoresIRIs globales (pyr:recursion)Identificadores locales del grafo (id:'recursion')
Inferencia formalRazonador OWL 2 RL (0 → 157 conceptos inferidos)Sin razonador estándar; recorridos por consulta
Validación de formaSHACL (conforme, 0 violaciones)Restricciones del motor (no exportadas aquí)
Enlazado externoskos:exactMatch a Wikidata (30 enlaces)No se materializa en este export
Lenguaje de consultaSPARQL (incluida consulta federada)Cypher (MATCH … RETURN)
Qué se conserva y qué no en el viaje a LPG

El export traslada la espina dorsal del grafo, los conceptos con sus propiedades y la malla de prerrequisitos y contrastes. No reproduce la inferencia OWL 2 RL, la validación SHACL ni el enlazado skos:exactMatch a Wikidata, que son fortalezas propias del lado RDF y que documento en la página del grafo. El LPG, a cambio, hace cómodo poner atributos sobre las propias relaciones y recorrer caminos con consultas de patrón.

4Reproducir el grafo de propiedades

El fichero ekg_lpg.cypher está preparado para cargarse tal cual en Neo4j o en arrows.app y dibujar el grafo de propiedades: sus 157 sentencias CREATE y las aristas :REQUIERE y :CONTRASTA reconstruyen el modelo completo. El diagrama de la sección 2 es un esquema de ese mismo modelo, trazado con la paleta del proyecto.

Ver también

El grafo de conocimiento

La representación canónica en RDF/OWL, con la grafoteca interactiva, la malla SKOS, la inferencia OWL 2 RL y el enlazado a Wikidata.

El sistema RAG

Cómo se recupera el subgrafo de un concepto y se inyecta en el prompt de los sistemas C y D.

Recursos y artefactos

Ficheros del proyecto, entre ellos las serializaciones del grafo y los guiones de exportación.

Cómo citar

Si este trabajo te resulta útil y quieres referenciarlo, esta es la cita recomendada.

Bueno Junquero, A. (2026). Integración de grafos de conocimiento educativos con modelos de lenguaje masivos mediante arquitecturas RAG para evaluación personalizada en la enseñanza de programación. Trabajo Fin de Máster, Máster Universitario en Investigación en Inteligencia Artificial, UNED. Director, José Luis Fernández Vindel.