visit
We’ve argued that
Loading documents into an entity-centric graph store like Neo4j was done using LangChain’s LLMGraphTransformer. The code is based on LangChain's
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")
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)
},
)
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")
Bottom-line: the entity-centric approach of extracting knowledge graphs from content using an LLM was both time and cost prohibitive at scale. On the other hand, using GraphVectorStore was fast and inexpensive.
Entity-centric used 7324 prompt tokens and cost $0.03 to produce basically useless answers, while content-centric used 450 prompt tokens and cost $0.002 to produce concise answers directly answering the questions.
> 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."}
Graph RAG is a useful tool for enabling generative AI RAG applications to retrieve more deeply relevant contexts. But using a fine-grained, entity-centric approach does not scale to production needs. If you're looking to add knowledge graph capabilities to your RAG application, try