Dependencies¶
In [ ]:
%pip install llama-index
%pip install llama-index-llms-ollama
%pip install llama-index-graph-stores-nebula
%pip install ipython-ngql
%pip install llama-index-embeddings-huggingface
References¶
Graph RAG, the naive version from LlamaIndex.
LLM with Ollama to leverage Gemma:7B
.
Graph Extraction with LLM.
Embedding.
Chinese Example.
Text2Cypher.(Broken now)
Full Graph RAG Workshop.
LLM¶
Let's take ollama gemma as an example.
In [17]:
from llama_index.llms.ollama import Ollama
llm = Ollama(model="gemma:7b", request_timeout=30.0)
Settings.llm = llm
In [2]:
print(llm.complete("Hi"))
Hi, hi! 👋 It's nice to hear from you. What would you like to talk about today?
Embeddings¶
In [16]:
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import Settings
embed_model = HuggingFaceEmbedding(
model_name="BAAI/bge-small-en-v1.5"
)
Settings.embed_model = embed_model
Graph¶
In [4]:
from llama_index.core import KnowledgeGraphIndex, SimpleDirectoryReader
from llama_index.core import StorageContext
from llama_index.graph_stores.nebula import NebulaGraphStore
In [5]:
%load_ext ngql
%ngql --address 192.168.8.128 --port 9669 --user root --password nebula
Connection Pool Created
Out[5]:
Name | |
---|---|
0 | basketballplayer |
1 | demo_fraud_detection |
2 | demo_movie_recommendation |
3 | k8s |
4 | langchain |
5 | nebula_node |
6 | paul_graham_essay |
7 | test |
In [7]:
%ngql CREATE SPACE IF NOT EXISTS paul_graham_essay(vid_type=FIXED_STRING(256), partition_num=1, replica_factor=1);
Out[7]:
In [8]:
%ngql USE paul_graham_essay;
Out[8]:
In [10]:
%ngql CREATE TAG IF NOT EXISTS entity(name string);
%ngql CREATE EDGE IF NOT EXISTS relationship(relationship string);
%ngql CREATE TAG INDEX IF NOT EXISTS entity_index ON entity(name(256));
Out[10]:
In [11]:
import os
os.environ["NEBULA_USER"] = "root"
os.environ["NEBULA_PASSWORD"] = "nebula"
os.environ["NEBULA_ADDRESS"] = "192.168.8.128:9669"
space_name = "paul_graham_essay"
edge_types, rel_prop_names = ["relationship"], ["relationship"] # default, could be omit if create from an empty kg
tags = ["entity"] # default, could be omit if create from an empty kg
graph_store = NebulaGraphStore(
space_name=space_name,
edge_types=edge_types,
rel_prop_names=rel_prop_names,
tags=tags)
storage_context = StorageContext.from_defaults(graph_store=graph_store)
Textual Data¶
In [18]:
!mkdir data
!wget -O data/paul_graham_essay.txt https://gist.github.com/wey-gu/75d49362d011a0f0354d39e396404ba2/raw/0844351171751ebb1ce54ea62232bf5e59445bb7/paul_graham_essay.txt
mkdir: cannot create directory ‘data’: File exists
huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks... To disable this warning, you can either: - Avoid using `tokenizers` before the fork if possible - Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
--2024-03-12 17:06:51-- https://gist.github.com/wey-gu/75d49362d011a0f0354d39e396404ba2/raw/0844351171751ebb1ce54ea62232bf5e59445bb7/paul_graham_essay.txt Resolving gist.github.com (gist.github.com)...
huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks... To disable this warning, you can either: - Avoid using `tokenizers` before the fork if possible - Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
140.82.121.3 Connecting to gist.github.com (gist.github.com)|140.82.121.3|:443... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: https://gist.githubusercontent.com/wey-gu/75d49362d011a0f0354d39e396404ba2/raw/0844351171751ebb1ce54ea62232bf5e59445bb7/paul_graham_essay.txt [following] --2024-03-12 17:06:53-- https://gist.githubusercontent.com/wey-gu/75d49362d011a0f0354d39e396404ba2/raw/0844351171751ebb1ce54ea62232bf5e59445bb7/paul_graham_essay.txt Resolving gist.githubusercontent.com (gist.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ... Connecting to gist.githubusercontent.com (gist.githubusercontent.com)|185.199.108.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 75040 (73K) [text/plain] Saving to: ‘data/paul_graham_essay.txt’ data/paul_graham_es 100%[===================>] 73.28K 168KB/s in 0.4s 2024-03-12 17:06:55 (168 KB/s) - ‘data/paul_graham_essay.txt’ saved [75040/75040]
KG Extraction¶
In [18]:
from llama_index.core import (
VectorStoreIndex,
SimpleDirectoryReader,
KnowledgeGraphIndex,
)
graph_store.query("SHOW HOSTS")
Settings.chunk_size = 512
documents = SimpleDirectoryReader(
"data"
).load_data()
In [62]:
kg_index = KnowledgeGraphIndex.from_documents(
documents,
storage_context=storage_context,
max_triplets_per_chunk=10,
space_name=space_name,
edge_types=edge_types,
rel_prop_names=rel_prop_names,
tags=tags,
max_knowledge_sequence=15,
)
# kg_index.storage_context.persist(persist_dir='./storage_graph')
In [ ]:
%pip install pyvis
In [12]:
%ngql MATCH ()-[e]->() RETURN e limit 100
Out[12]:
e | |
---|---|
0 | ("$300")-[:relationship@-665030298810534339{re... |
1 | ("A rent-controlled apartment")-[:relationship... |
2 | ("A taxi")-[:relationship@-1596976044960917955... |
3 | ("Ai")-[:relationship@-1616808746972502954{rel... |
4 | ("Ai")-[:relationship@6530114152937975026{rela... |
... | ... |
95 | ("I")-[:relationship@-424905891476928522{relat... |
96 | ("I")-[:relationship@-140659895455191590{relat... |
97 | ("I")-[:relationship@6420882631418233{relation... |
98 | ("I")-[:relationship@6420882631418233{relation... |
99 | ("I")-[:relationship@102882367881018206{relati... |
100 rows × 1 columns
In [13]:
%ng_draw
Out[13]:
<class 'pyvis.network.Network'> |N|=150 |E|=100
Challenges
- Only Triplet style Graph is supported, schema-full Property Graph is not supported
Graph RAG¶
In [21]:
# Pure Graph Based
In [19]:
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import KnowledgeGraphRAGRetriever
graph_rag_retriever = KnowledgeGraphRAGRetriever(
storage_context=storage_context,
verbose=True,
)
query_engine = RetrieverQueryEngine.from_args(
graph_rag_retriever,
)
In [20]:
response = query_engine.query("What's the relationship between Bob and Alice")
print(response)
Sure, here is the answer to the query: The relationship between Bob and Alice in the provided text is that Bob is Alice's mother.
In [22]:
# Example of Hybrid Vector and Graph
In [27]:
vector_index = VectorStoreIndex.from_documents(documents)
In [28]:
# import QueryBundle, NodeWithScore
from llama_index.core.schema import NodeWithScore, QueryBundle
# Retrievers
from llama_index.core.base.base_retriever import BaseRetriever
from llama_index.core.indices.vector_store.retrievers import VectorIndexRetriever
from llama_index.core.indices.knowledge_graph.retrievers import KGTableRetriever
from typing import List
class CustomRetriever(BaseRetriever):
"""Custom retriever that performs both Vector search and Knowledge Graph search"""
def __init__(
self,
vector_retriever: VectorIndexRetriever,
kg_retriever: KGTableRetriever,
mode: str = "OR"
) -> None:
"""Init params."""
self._vector_retriever = vector_retriever
self._kg_retriever = kg_retriever
if mode not in ("AND", "OR"):
raise ValueError("Invalid mode.")
self._mode = mode
def _retrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]:
"""Retrieve nodes given query."""
vector_nodes = self._vector_retriever.retrieve(query_bundle)
kg_nodes = self._kg_retriever.retrieve(query_bundle)
vector_ids = {n.node.node_id for n in vector_nodes}
kg_ids = {n.node.node_id for n in kg_nodes}
combined_dict = {n.node.node_id: n for n in vector_nodes}
combined_dict.update({n.node.node_id: n for n in kg_nodes})
if self._mode == "AND":
retrieve_ids = vector_ids.intersection(kg_ids)
else:
retrieve_ids = vector_ids.union(kg_ids)
retrieve_nodes = [combined_dict[rid] for rid in retrieve_ids]
return retrieve_nodes
In [30]:
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.response_synthesizers.base import BaseSynthesizer
from llama_index.core.retrievers import KnowledgeGraphRAGRetriever
graph_rag_retriever = KnowledgeGraphRAGRetriever(
storage_context=storage_context,
verbose=True,
)
# from llama_index.core import get_response_synthesizer
# create a custom retriever
vector_retriever = VectorIndexRetriever(index=vector_index)
kg_and_vec_retriever = CustomRetriever(vector_retriever, graph_rag_retriever)
# create a response synthesizer
#response_synthesizer = get_response_synthesizer()
query_engine = RetrieverQueryEngine(
retriever=kg_and_vec_retriever,
# synthesizer=response_synthesizer
)
In [33]:
response = query_engine.query("What is Hacker news")
In [34]:
print(response)
Hacker News is a news aggregator that was originally intended to be a news aggregator for startup founders. It was called Startup News at the time, but after a few months, the name was changed to Hacker News and the topic was changed to whatever engaged one's intellectual curiosity.
In [35]:
response.source_nodes[0].metadata
Out[35]:
{'kg_rel_map': {'News aggregator{name: News aggregator}': ['News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was}]-> At the mercy of investors{name: At the mercy of investors}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was bored with}]-> Philosophy courses{name: Philosophy courses}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was writing}]-> Dissertation{name: Dissertation}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} <-[relationship:{relationship: Offered unsolicited advice}]- Rtm{name: Rtm}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Was{name: Was}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Text{name: Text}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: Is}]-> File_path{name: File_path}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> /home/wey.gu/tutor/data/{name: /home/wey.gu/tutor/data/}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Wrote no more essays till}]-> Bel was done{name: Bel was done}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was at the mercy of}]-> Investors{name: Investors}'], 'Text{name: Text}': ['Text{name: Text} <-[relationship:{relationship: File_path}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Was{name: Was}', 'Text{name: Text} <-[relationship:{relationship: Is file_path of}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Text{name: Text}', 'Text{name: Text} -[relationship:{relationship: Is}]-> A coffee shop{name: A coffee shop}', 'Text{name: Text} <-[relationship:{relationship: Is}]- File_path{name: File_path}', 'Text{name: Text} <-[relationship:{relationship: Is file_path of}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'Text{name: Text} -[relationship:{relationship: Is}]-> File_path{name: File_path}', 'Text{name: Text} <-[relationship:{relationship: File_path}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: Was originally meant to be}]-> News aggregator{name: News aggregator}', 'Text{name: Text} -[relationship:{relationship: Is}]-> File_path{name: File_path} -[relationship:{relationship: Is}]-> Text{name: Text}', 'Text{name: Text} <-[relationship:{relationship: Is}]- File_path{name: File_path} <-[relationship:{relationship: Is}]- Text{name: Text}', 'Text{name: Text} <-[relationship:{relationship: File_path}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'Text{name: Text} -[relationship:{relationship: Is}]-> File_path{name: File_path} <-[relationship:{relationship: Is}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'Text{name: Text} <-[relationship:{relationship: Is file_path of}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: Is}]-> File_path{name: File_path}'], 'Hacker news{name: Hacker news}': ['Hacker news{name: Hacker news} -[relationship:{relationship: Was}]-> Coffee shop{name: Coffee shop} -[relationship:{relationship: Was}]-> Founded in{name: Founded in}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was}]-> Coffee shop{name: Coffee shop} <-[relationship:{relationship: Is}]- Philz{name: Philz}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was the biggest source of stress}]-> For me{name: For me}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was originally meant to be}]-> A news aggregator{name: A news aggregator}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was originally meant to be}]-> A news aggregator{name: A news aggregator} <-[relationship:{relationship: To be}]- Originally meant{name: Originally meant}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was}]-> Coffee shop{name: Coffee shop}']}, 'kg_rel_text': ['News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was}]-> At the mercy of investors{name: At the mercy of investors}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was bored with}]-> Philosophy courses{name: Philosophy courses}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was writing}]-> Dissertation{name: Dissertation}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} <-[relationship:{relationship: Offered unsolicited advice}]- Rtm{name: Rtm}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Was{name: Was}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Text{name: Text}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: Is}]-> File_path{name: File_path}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> /home/wey.gu/tutor/data/{name: /home/wey.gu/tutor/data/}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was originally meant to be}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Wrote no more essays till}]-> Bel was done{name: Bel was done}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul}', 'News aggregator{name: News aggregator} <-[relationship:{relationship: Was meant to be}]- Paul{name: Paul} -[relationship:{relationship: Was at the mercy of}]-> Investors{name: Investors}', 'Text{name: Text} <-[relationship:{relationship: File_path}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Was{name: Was}', 'Text{name: Text} <-[relationship:{relationship: Is file_path of}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: File_path}]-> Text{name: Text}', 'Text{name: Text} -[relationship:{relationship: Is}]-> A coffee shop{name: A coffee shop}', 'Text{name: Text} <-[relationship:{relationship: Is}]- File_path{name: File_path}', 'Text{name: Text} <-[relationship:{relationship: Is file_path of}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'Text{name: Text} -[relationship:{relationship: Is}]-> File_path{name: File_path}', 'Text{name: Text} <-[relationship:{relationship: File_path}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: Was originally meant to be}]-> News aggregator{name: News aggregator}', 'Text{name: Text} -[relationship:{relationship: Is}]-> File_path{name: File_path} -[relationship:{relationship: Is}]-> Text{name: Text}', 'Text{name: Text} <-[relationship:{relationship: Is}]- File_path{name: File_path} <-[relationship:{relationship: Is}]- Text{name: Text}', 'Text{name: Text} <-[relationship:{relationship: File_path}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'Text{name: Text} -[relationship:{relationship: Is}]-> File_path{name: File_path} <-[relationship:{relationship: Is}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt}', 'Text{name: Text} <-[relationship:{relationship: Is file_path of}]- Paul_graham_essay.txt{name: Paul_graham_essay.txt} -[relationship:{relationship: Is}]-> File_path{name: File_path}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was}]-> Coffee shop{name: Coffee shop} -[relationship:{relationship: Was}]-> Founded in{name: Founded in}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was}]-> Coffee shop{name: Coffee shop} <-[relationship:{relationship: Is}]- Philz{name: Philz}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was the biggest source of stress}]-> For me{name: For me}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was originally meant to be}]-> A news aggregator{name: A news aggregator}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was originally meant to be}]-> A news aggregator{name: A news aggregator} <-[relationship:{relationship: To be}]- Originally meant{name: Originally meant}', 'Hacker news{name: Hacker news} -[relationship:{relationship: Was}]-> Coffee shop{name: Coffee shop}'], 'kg_schema': {'schema': "Node properties: [{'tag': 'entity', 'properties': [('name', 'string')]}]\nEdge properties: [{'edge': 'relationship', 'properties': [('relationship', 'string')]}]\nRelationships: ['(:entity)-[:relationship]->(:entity)']\n"}}
In [38]:
print(response.source_nodes[1].text)
It solved one of the biggest problems faced by founders: the isolation. Now you not only had colleagues, but colleagues who understood the problems you were facing and could tell you how they were solving them. As YC grew, we started to notice other advantages of scale. The alumni became a tight community, dedicated to helping one another, and especially the current batch, whose shoes they remembered being in. We also noticed that the startups were becoming one another's customers. We used to refer jokingly to the "YC GDP," but as YC grows this becomes less and less of a joke. Now lots of startups get their initial set of customers almost entirely from among their batchmates. I had not originally intended YC to be a full-time job. I was going to do three things: hack, write essays, and work on YC. As YC grew, and I grew more excited about it, it started to take up a lot more than a third of my attention. But for the first few years I was still able to work on other things. In the summer of 2006, Robert and I started working on a new version of Arc. This one was reasonably fast, because it was compiled into Scheme. To test this new Arc, I wrote Hacker News in it. It was originally meant to be a news aggregator for startup founders and was called Startup News, but after a few months I got tired of reading about nothing but startups. Plus it wasn't startup founders we wanted to reach. It was future startup founders. So I changed the name to Hacker News and the topic to whatever engaged one's intellectual curiosity. HN was no doubt good for YC, but it was also by far the biggest source of stress for me. If all I'd had to do was select and help founders, life would have been so easy. And that implies that HN was a mistake. Surely the biggest source of stress in one's work should at least be something close to the core of the work. Whereas I was like someone who was in pain while running a marathon not from the exertion of running, but because I had a blister from an ill-fitting shoe.
Challenges:
- "Hacker news" has to exactly match with the "vid", or "name" prop of vertex!
- Complex questions will fail with SubGraph RAG
Text2Cypher¶
In [39]:
from llama_index.core.query_engine import KnowledgeGraphQueryEngine
In [54]:
from llama_index.core.prompts.base import (
BasePromptTemplate,
PromptTemplate,
PromptType,
)
LONG_NEBULAGRAPH_NL2CYPHER_PROMPT_TMPL_STR = """
Create a **NebulaGraph flavor Cypher query** based on provided schema and a question.
The query should be able to try best answer the question with the given graph schema.
NebulaGraph flavor Cypher differs from standard Cypher in the following ways:
- Fully qualify property references with the node's label.
```
// Standard Cypher(incorrect in NebulaGraph)
MATCH (p:person)-[:follow]->() RETURN p.name
// NebulaGraph Cypher, here we use p.person.name with Label specified
MATCH (p:person)-[:follow]->() RETURN p.person.name
```
- Use == for equality comparisons instead of =
```
// Standard Cypher(WRONG)
MATCH (p:person {{name: 'Alice'}}) RETURN p
// NebulaGraph flavor Cypher
MATCH (p:person) WHERE p.person.name == 'Alice' RETURN p
```
With these differentiations, construct a NebulaGraph Cypher query to answer the given question, only return the plain text query, no explanation, apologies, or other text.
NOTE:
0. Try to get as much graph data as possible to answer the question
1. Use valid NebulaGraph flavor Cypher syntax when referring vertex property like `... WHERE v.person.name == 'Alice'...`
2. Adhering strictly to the relationships and properties given in the schema
---
Question: {query_str}
---
Schema: {schema}
---
NebulaGraph flavor Query:
"""
T2C_PROMPT = PromptTemplate(
LONG_NEBULAGRAPH_NL2CYPHER_PROMPT_TMPL_STR,
prompt_type=PromptType.TEXT_TO_GRAPH_QUERY,
)
t2c_qe = KnowledgeGraphQueryEngine(
storage_context=storage_context,
graph_query_synthesis_prompt=T2C_PROMPT,
llm=llm,
verbose=True,
)
In [57]:
print(t2c_qe.generate_query("What is Hacker news"))
```cypher MATCH (n:entity) WHERE n.person.name == 'Alice' RETURN n.tag ```
Challenges:
- Small LLM failed to generate Proper Query