paint-brush
Com estalviar 70.000 dòlars Construint un gràfic de coneixement per a RAG a 6 milions de pàgines de Viquipèdiaper@datastax
824 lectures
824 lectures

Com estalviar 70.000 dòlars Construint un gràfic de coneixement per a RAG a 6 milions de pàgines de Viquipèdia

per DataStax4m2024/10/15
Read on Terminal Reader

Massa Llarg; Per llegir

Hem argumentat que els gràfics de coneixement centrats en el contingut, una botiga de vectors que permeten enllaços entre fragments, són un enfocament més fàcil d'utilitzar i més eficient per millorar els resultats RAG. Aquí, ho posem a prova.
featured image - Com estalviar 70.000 dòlars Construint un gràfic de coneixement per a RAG a 6 milions de pàgines de Viquipèdia
DataStax HackerNoon profile picture
0-item



L'ús de gràfics de coneixement per millorar els resultats de les aplicacions de generació augmentada amb recuperació (RAG) s'ha convertit en un tema candent. La majoria dels exemples demostren com crear un gràfic de coneixement utilitzant un nombre relativament petit de documents. Això podria ser perquè l'enfocament típic -extreure informació detallada i centrada en l'entitat- simplement no s'escala. L'execució de cada document a través d'un model per extreure les entitats (nodes) i les relacions (vores) triga massa (i costa massa) a executar-se en grans conjunts de dades.


Ho hem argumentat gràfics de coneixement centrats en el contingut - una botiga de vectors que permet enllaços entre trossos - són un enfocament més fàcil d'utilitzar i més eficient. Aquí, ho posem a prova. Carreguem un subconjunt dels articles de la Viquipèdia del 2wikimultihop conjunt de dades utilitzant ambdues tècniques i discuteix què significa això per carregar tot el conjunt de dades. Mostrem els resultats d'algunes preguntes sobre les dades carregades. També carregarem tot el conjunt de dades (prop de 6 milions de documents) en un contingut centrat GraphVectorStore .

Centrat en l'entitat: LLMGraphTransformer

La càrrega de documents a una botiga de gràfics centrada en l'entitat com Neo4j es va fer mitjançant LLMGraphTransformer de LangChain. El codi es basa en LangChain "Com construir gràfics de coneixement".

 from langchain_core.documents import Document from langchain_experimental.graph_transformers import LLMGraphTransformer from langchain_openai import ChatOpenAI llm = ChatOpenAI(temperature=0, model_name="gpt-4-turbo") llm_transformer = LLMGraphTransformer(llm=llm) from time import perf_counter start = perf_counter() documents_to_load = [Document(page_content=line) for line in lines_to_load] graph_documents = llm_transformer.convert_to_graph_documents(documents_to_load) end = perf_counter() print(f"Loaded (but NOT written) {NUM_LINES_TO_LOAD} in {end - start:0.2f}s")

Centrat en el contingut: GraphVectorStore

Carregar les dades a GraphVectorStore és aproximadament el mateix que carregar-les a una botiga de vectors. L'únic afegit és que calculem metadades que indiquen com cada pàgina enllaça amb altres pàgines.


 import json from langchain_core.graph_vectorstores.links import METADATA_LINKS_KEY, Link def parse_document(line: str) -> Document:    para = json.loads(line)    id = para["id"]    links = {        Link.outgoing(kind="href", tag=id)        for m in para["mentions"]        if m["ref_ids"] is not None        for id in m["ref_ids"]    }    links.add(Link.incoming(kind="href", tag=id))    return Document(        id = id,        page_content = " ".join(para["sentences"]),        metadata = {            "content_id": para["id"],            METADATA_LINKS_KEY: list(links)        },    )


Aquest també és un bon exemple de com podeu afegir els vostres propis enllaços entre nodes.


 from langchain_openai import OpenAIEmbeddings from langchain_community.graph_vectorstores.cassandra import CassandraGraphVectorStore import cassio cassio.init(auto=True) TABLE_NAME = "wiki_load" store = CassandraGraphVectorStore( embedding = OpenAIEmbeddings(), node_table=TABLE_NAME, insert_timeout = 1000.0, ) from time import perf_counter start = perf_counter() from datasets.wikimultihop.load import parse_document kg_documents = [parse_document(line) for line in lines_to_load] store.add_documents(kg_documents) end = perf_counter() print(f"Loaded (and written) {NUM_LINES_TO_LOAD} in {end - start:0.2f}s")

Càrrega de benchmarks

Amb 100 files, l'enfocament centrat en l'entitat utilitzant GPT-4o va trigar 405,93 s per extreure els GraphDocuments i 10,99 s per escriure'ls a Neo4j, mentre que l'enfocament centrat en el contingut va trigar 1,43 s. En extrapolar, es trigarien 41 setmanes a carregar les 5.989.847 pàgines amb l'enfocament centrat en l'entitat i unes 24 hores amb l'enfocament centrat en el contingut. Però gràcies al paral·lelisme, l'enfocament centrat en el contingut s'executa en només 2,5 hores! Suposant els mateixos beneficis del paral·lelisme, encara trigarien més de quatre setmanes a carregar-ho tot utilitzant l'enfocament centrat en l'entitat. No ho vaig provar, ja que el cost estimat seria de 58.700 dòlars, suposant que tot funcionés la primera vegada!



Conclusió: l'enfocament centrat en l'entitat d'extreure gràfics de coneixement del contingut mitjançant un LLM era prohibitiu tant en temps com en cost a escala. D'altra banda, utilitzar GraphVectorStore era ràpid i econòmic.

Exemples de respostes

En aquesta secció, es fan algunes preguntes, extretes del subconjunt de documents carregats, per abordar la qualitat de les respostes.


Entity-centric va utilitzar 7324 fitxes d'avís i va costar 0,03 dòlars per produir respostes bàsicament inútils, mentre que el centrat en contingut va utilitzar 450 fitxes d'avís i va costar 0,002 dòlars per produir respostes concises responent directament a les preguntes.


Pot ser sorprenent que el gràfic Neo4j de gra fi retorni respostes inútils. Mirant el registre de la cadena, veiem alguns dels motius pels quals passa això:


 > Entering new GraphCypherQAChain chain... Generated Cypher: cypher MATCH (a:Album {id: 'The Circle'})-[:RELEASED_BY]->(r:Record_label) RETURN a.id, r.id Full Context: [{'a.id': 'The Circle', 'r.id': 'Restless'}] > Finished chain. {'query': "When was 'The Circle' released?", 'result': "I don't know the answer."}


Per tant, l'esquema detallat només retornava informació sobre el segell discogràfic. Té sentit que el LLM no hagi pogut respondre la pregunta a partir de la informació recuperada.

Conclusió

L'extracció de gràfics de coneixement detallats i específics de l'entitat és prohibitiu de temps i costos a escala. Quan es van fer preguntes sobre el subconjunt de dades que es va carregar, la granularitat addicional (i el cost addicional de carregar el gràfic detallat) va retornar més fitxes per incloure el missatge, però va generar respostes inútils!


GraphVectorStore adopta un enfocament de gra gruixut i centrat en el contingut que fa que sigui ràpid i senzill crear un gràfic de coneixement. Podeu començar amb el vostre codi existent per emplenar un VectorStore mitjançant LangChain i afegir enllaços (vores) entre fragments per millorar el procés de recuperació.


Graph RAG és una eina útil per permetre que les aplicacions generatives AI RAG recuperin contextos més rellevants. Però utilitzar un enfocament detallat i centrat en l'entitat no s'ajusta a les necessitats de producció. Si voleu afegir capacitats de gràfics de coneixement a la vostra aplicació RAG, proveu-ho GraphVectorStore .


Per Ben Chambers , DataStax