La construcción de gráficos de conocimiento a partir de texto ha sido un área de investigación fascinante durante bastante tiempo. Con la llegada de los grandes modelos de lenguaje (LLM), este campo ha ganado más atención. Sin embargo, los LLM pueden ser bastante costosos. Un enfoque alternativo es ajustar los modelos más pequeños, lo que ha sido respaldado por la investigación académica y ha producido soluciones más eficientes. Hoy, exploraremos Relik , un marco para ejecutar modelos de extracción de información ultrarrápidos y livianos, desarrollado por el grupo NLP de la Universidad La Sapienza de Roma.
Un proceso típico de extracción de información sin un LLM se parece al siguiente:
La imagen ilustra un proceso de extracción de información que comienza con datos de entrada que consisten en un texto que menciona “A Tomaz le gusta escribir artículos de blog. Está particularmente interesado en dibujar diagramas”. El proceso comienza con la resolución de correferencia para identificar a “Tomaz” y “Él” como la misma entidad. El reconocimiento de entidades nombradas (NER) luego identifica entidades como “Tomaz”, “Blog” y “Diagrama”.
La vinculación de entidades es el proceso que sigue a NER, donde las entidades reconocidas se asignan a las entradas correspondientes en una base de datos o base de conocimiento. Por ejemplo, “Tomaz” está vinculado a “Tomaz Bratanic (Q12345)” y “Blog” a “Blog (Q321)”, pero “Diagrama” no tiene ninguna coincidencia en la base de conocimiento.
La extracción de relaciones es el paso siguiente en el que el sistema identifica y extrae relaciones significativas entre las entidades reconocidas. Este ejemplo identifica que “Tomaz” tiene una relación con “Blog” caracterizada por “WRITES”, lo que indica que Tomaz escribe blogs. Además, identifica que “Tomaz” tiene una relación con “Diagram” caracterizada por “INTERESTED_IN”, lo que indica que Tomaz está interesado en los diagramas.
Finalmente, esta información estructurada, incluidas las entidades y sus relaciones, se almacena en un gráfico de conocimiento, lo que permite disponer de datos organizados y accesibles para su posterior análisis o recuperación.
Tradicionalmente, sin la potencia de los LLM, todo este proceso se basa en un conjunto de modelos especializados, cada uno de los cuales se encarga de una tarea específica, desde la resolución de correferencias hasta la extracción de relaciones. Si bien la integración de estos modelos exige más esfuerzo y coordinación, ofrece una ventaja significativa: menores costos. Al ajustar modelos más pequeños y específicos para cada tarea, se puede mantener bajo control el gasto general de creación y mantenimiento del sistema.
El código está disponible en GitHub .
Te sugiero que uses un entorno Python independiente como Google Colab , ya que tendremos que experimentar un poco con las dependencias. Los modelos son más rápidos en la GPU, por lo que puedes usar un entorno de ejecución con tecnología GPU si tienes la versión Pro.
Además, necesitamos configurar Neo4j, una base de datos gráfica nativa, para almacenar la información extraída. Hay muchas formas de configurar la instancia de la base de datos . Sin embargo, recomiendo usar Neo4j Aura , que proporciona una instancia en la nube gratuita a la que se puede acceder fácilmente desde un notebook de Google Colab.
Neo4j Aura: una solución en la nube totalmente gestionada
Una vez creada la base de datos, podemos definir una conexión utilizando LlamaIndex:
from llama_index.graph_stores.neo4j import Neo4jPGStore username="neo4j" password="rubber-cuffs-radiator" url="bolt://54.89.19.156:7687" graph_store = Neo4jPGStore( username=username, password=password, url=url, refresh_schema=False )
Usaremos un conjunto de datos de noticias que obtuve a través de la API de Diffbot hace algún tiempo. El conjunto de datos está disponible en GitHub para que podamos reutilizarlo:
import pandas as pd NUMBER_OF_ARTICLES = 100 news = pd.read_csv( "https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/news_articles.csv" ) news = news.head(NUMBER_OF_ARTICLES)
El primer paso del proceso es un modelo de resolución de correferencias. La resolución de correferencias es la tarea de identificar todas las expresiones de un texto que hacen referencia a la misma entidad.
Hasta donde yo sé, no hay muchos modelos de código abierto disponibles para la resolución de correferencias. Probé maverick-coref , pero en mis pruebas funcionó mejor Coreferee de spaCy, así que lo usaremos. La única desventaja de usar Coreferee es que tenemos que lidiar con el infierno de dependencias, que se resuelve en el cuaderno, pero no lo analizaremos aquí.
Puede cargar el modelo de correferencia en spaCy con el siguiente código:
import spacy, coreferee coref_nlp = spacy.load('en_core_web_lg') coref_nlp.add_pipe('coreferee')
El modelo Coreferee detecta grupos de expresiones que hacen referencia a la misma entidad o entidades. Para reescribir el texto en función de estos grupos, tenemos que implementar nuestra propia función:
def coref_text(text): coref_doc = coref_nlp(text) resolved_text = "" for token in coref_doc: repres = coref_doc._.coref_chains.resolve(token) if repres: resolved_text += " " + " and ".join( [ t.text if t.ent_type_ == "" else [e.text for e in coref_doc.ents if t in e][0] for t in repres ] ) else: resolved_text += " " + token.text return resolved_text
Probemos la función para asegurarnos de que los modelos y las dependencias estén configurados correctamente:
print( coref_text("Tomaz is so cool. He can solve various Python dependencies and not cry") ) # Tomaz is so cool . Tomaz can solve various Python dependencies and not cry
En este ejemplo, el modelo identificó que “Tomaz” y “Él” hacen referencia a la misma entidad. Mediante la función coref_text, reemplazamos “Él” por “Tomaz”.
Tenga en cuenta que la reescritura no siempre devuelve oraciones gramaticalmente correctas debido al uso de una lógica de reemplazo simple para las entidades dentro del clúster. Sin embargo, debería ser suficiente para la mayoría de los escenarios.
Ahora aplicamos la resolución de correferencia a nuestro conjunto de datos de noticias y envolvemos los resultados como documentos LlamaIndex:
from llama_index.core import Document news["coref_text"] = news["text"].apply(coref_text) documents = [ Document(text=f"{row['title']}: {row['coref_text']}") for i, row in news.iterrows() ]
Relik es una biblioteca con modelos para la vinculación de entidades (EL) y la extracción de relaciones (RE), y también admite modelos que combinan ambos. En la vinculación de entidades, se utiliza Wikipedia como base de conocimiento de destino para asignar entidades en el texto a sus entradas correspondientes en la enciclopedia.
Por otro lado, la extracción de relaciones implica identificar y categorizar las relaciones entre entidades dentro de un texto, lo que permite la extracción de información estructurada de datos no estructurados.
Si está utilizando una versión gratuita de Colab, utilice el modelo relik-ie/relik-relation-extraction-small, que solo realiza la extracción de relaciones. Si tiene una versión Pro o la va a utilizar en una máquina local más potente, puede probar el modelo relik-ie/relik-cie-small, que realiza la vinculación de entidades y la extracción de relaciones.
from llama_index.extractors.relik.base import RelikPathExtractor relik = RelikPathExtractor( model="relik-ie/relik-relation-extraction-small" ) # Use on Pro Collab with GPU # relik = RelikPathExtractor( # model="relik-ie/relik-cie-small", model_config={"skip_metadata": True, "device":"cuda"} # )
Además, tenemos que definir el modelo de incrustación que se utilizará para incrustar entidades y el LLM para el flujo de preguntas y respuestas:
import os from llama_index.embeddings.openai import OpenAIEmbedding from llama_index.llms.openai import OpenAI os.environ["OPENAI_API_KEY"] = "sk-" llm = OpenAI(model="gpt-4o", temperature=0.0) embed_model = OpenAIEmbedding(model_name="text-embedding-3-small")
Tenga en cuenta que el LLM no se utilizará durante la construcción del gráfico.
Ahora que tenemos todo en su lugar, podemos crear una instancia de PropertyGraphIndex y usar los documentos de noticias como datos de entrada para un gráfico de conocimiento.
Además, necesitamos pasar el modelo relik como valor kg_extractors para extraer las relaciones:
from llama_index.core import PropertyGraphIndex index = PropertyGraphIndex.from_documents( documents, kg_extractors=[relik], llm=llm, embed_model=embed_model, property_graph_store=graph_store, show_progress=True, )
Después de construir el gráfico, puede abrir el navegador Neo4j para validar el gráfico importado. Debería obtener una visualización similar ejecutando la siguiente declaración Cypher:
MATCH p=(:__Entity__)--(:__Entity__) RETURN p LIMIT 250
Resultados
Con LlamaIndex, ahora es fácil responder preguntas. Para usar los recuperadores de gráficos predeterminados, puede hacer preguntas tan sencillas como:
query_engine = index.as_query_engine(include_text=True) response = query_engine.query("What happened at Ryanair?") print(str(response))
Aquí es donde entran en juego el modelo LLM y el modelo de incrustación definidos. Por supuesto, también puede implementar recuperadores personalizados para lograr una precisión potencialmente mejor.
La creación de gráficos de conocimiento sin depender de LLM no solo es factible, sino también rentable y eficiente. Al ajustar modelos más pequeños y específicos para cada tarea, como los del marco Relik, puede lograr una extracción de información de alto rendimiento para sus aplicaciones de generación aumentada por recuperación (RAG).
La vinculación de entidades, un paso fundamental en este proceso, garantiza que las entidades reconocidas se asignen con precisión a las entradas correspondientes en una base de conocimiento, manteniendo así la integridad y la utilidad del gráfico de conocimiento.
Al utilizar marcos como Relik y plataformas como Neo4j, es posible construir gráficos de conocimiento avanzados que facilitan tareas complejas de análisis y recuperación de datos, todo ello sin los altos costos que suelen asociarse con la implementación de LLM. Este método no solo hace que las potentes herramientas de procesamiento de datos sean más accesibles, sino que también promueve la innovación y la eficiencia en los flujos de trabajo de extracción de información.
Asegúrate de darle una estrella a la biblioteca Relik . El código está disponible en GitHub .
Para obtener más información sobre este tema, únase a nosotros en NODES 2024 el 7 de noviembre, nuestra conferencia virtual gratuita para desarrolladores sobre aplicaciones inteligentes, gráficos de conocimiento e IA. ¡Regístrese AHORA !