Skip to content

Commit 35470e6

Browse files
authored
Merge pull request #65 from FalkorDB/agent-from-graph
Ontology creation from Knowledge Graph
2 parents 58e02db + ad88b43 commit 35470e6

File tree

8 files changed

+786
-550
lines changed

8 files changed

+786
-550
lines changed

graphrag_sdk/attribute.py

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import re
12
import json
2-
from graphrag_sdk.fixtures.regex import *
33
import logging
4-
import re
4+
from graphrag_sdk.fixtures.regex import *
55

66
logger = logging.getLogger(__name__)
77

@@ -15,6 +15,23 @@ class AttributeType:
1515
NUMBER = "number"
1616
BOOLEAN = "boolean"
1717
LIST = "list"
18+
POINT = "point"
19+
MAP = "map"
20+
VECTOR = "vectorf32"
21+
22+
23+
# Synonyms for attribute types
24+
_SYNONYMS = {
25+
"string": STRING,
26+
"integer": NUMBER,
27+
"float": NUMBER,
28+
"number": NUMBER,
29+
"boolean": BOOLEAN,
30+
"list": LIST,
31+
"point": POINT,
32+
"map": MAP,
33+
"vectorf32": VECTOR,
34+
}
1835

1936
@staticmethod
2037
def from_string(txt: str):
@@ -25,21 +42,19 @@ def from_string(txt: str):
2542
txt (str): The string representation of the attribute type.
2643
2744
Returns:
28-
AttributeType: The corresponding AttributeType value.
45+
str: The corresponding AttributeType value.
2946
3047
Raises:
31-
Exception: If the provided attribute type is invalid.
48+
ValueError: If the provided attribute type is invalid.
3249
"""
33-
if txt.lower() == AttributeType.STRING:
34-
return AttributeType.STRING
35-
if txt.lower() == AttributeType.NUMBER:
36-
return AttributeType.NUMBER
37-
if txt.lower() == AttributeType.BOOLEAN:
38-
return AttributeType.BOOLEAN
39-
if txt.lower() == AttributeType.LIST:
40-
return AttributeType.LIST
41-
raise Exception(f"Invalid attribute type: {txt}")
42-
50+
# Graph representation of the attribute type
51+
normalized_txt = txt.lower()
52+
53+
# Find the matching attribute type
54+
if normalized_txt in AttributeType._SYNONYMS:
55+
return AttributeType._SYNONYMS[normalized_txt]
56+
57+
raise ValueError(f"Invalid attribute type: {txt}")
4358

4459
class Attribute:
4560
""" Represents an attribute of an entity or relation in the ontology.
@@ -57,15 +72,15 @@ class Attribute:
5772
"""
5873

5974
def __init__(
60-
self, name: str, attr_type: AttributeType, unique: bool, required: bool = False
75+
self, name: str, attr_type: AttributeType, unique: bool = False, required: bool = False
6176
):
6277
"""
6378
Initialize a new Attribute object.
6479
6580
Args:
6681
name (str): The name of the attribute.
6782
attr_type (AttributeType): The type of the attribute.
68-
unique (bool): Indicates whether the attribute should be unique.
83+
unique (bool, optional): Indicates whether the attribute should be unique. Defaults to False.
6984
required (bool, optional): Indicates whether the attribute is required. Defaults to False.
7085
"""
7186
self.name = re.sub(r"([^a-zA-Z0-9_])", "_", name)
@@ -120,14 +135,6 @@ def from_string(txt: str):
120135
unique = "!" in txt
121136
required = "*" in txt
122137

123-
if attr_type not in [
124-
AttributeType.STRING,
125-
AttributeType.NUMBER,
126-
AttributeType.BOOLEAN,
127-
AttributeType.LIST,
128-
]:
129-
raise Exception(f"Invalid attribute type: {attr_type}")
130-
131138
return Attribute(name, AttributeType.from_string(attr_type), unique, required)
132139

133140
def to_json(self):
@@ -142,13 +149,15 @@ def to_json(self):
142149
- "unique": A boolean indicating whether the attribute is unique.
143150
- "required": A boolean indicating whether the attribute is required.
144151
"""
145-
return {
152+
json_data = {
146153
"name": self.name,
147154
"type": self.type,
148155
"unique": self.unique,
149156
"required": self.required,
150157
}
151158

159+
return json_data
160+
152161
def __str__(self) -> str:
153162
"""
154163
Returns a string representation of the Attribute object.

graphrag_sdk/chat_session.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
from falkordb import Graph
23
from graphrag_sdk.ontology import Ontology
34
from graphrag_sdk.steps.qa_step import QAStep
@@ -45,8 +46,11 @@ def __init__(self, model_config: KnowledgeGraphModelConfig, ontology: Ontology,
4546
self.model_config = model_config
4647
self.graph = graph
4748
self.ontology = ontology
48-
cypher_system_instruction = cypher_system_instruction.format(ontology=str(ontology.to_json()))
49-
49+
50+
# Filter the ontology to remove unique and required attributes that are not needed for Q&A.
51+
ontology_prompt = self.clean_ontology_for_prompt(ontology)
52+
53+
cypher_system_instruction = cypher_system_instruction.format(ontology=ontology_prompt)
5054

5155
self.cypher_prompt = cypher_gen_prompt
5256
self.qa_prompt = qa_prompt
@@ -108,4 +112,31 @@ def send_message(self, message: str):
108112
"response": answer,
109113
"context": context,
110114
"cypher": cypher
111-
}
115+
}
116+
117+
def clean_ontology_for_prompt(self, ontology: dict) -> str:
118+
"""
119+
Cleans the ontology by removing 'unique' and 'required' keys and prepares it for use in a prompt.
120+
121+
Args:
122+
ontology (dict): The ontology to clean and transform.
123+
124+
Returns:
125+
str: The cleaned ontology as a JSON string.
126+
"""
127+
# Convert the ontology object to a JSON.
128+
ontology = ontology.to_json()
129+
130+
# Remove unique and required attributes from the ontology.
131+
for entity in ontology["entities"]:
132+
for attribute in entity["attributes"]:
133+
del attribute['unique']
134+
del attribute['required']
135+
136+
for relation in ontology["relations"]:
137+
for attribute in relation["attributes"]:
138+
del attribute['unique']
139+
del attribute['required']
140+
141+
# Return the transformed ontology as a JSON string
142+
return json.dumps(ontology)

graphrag_sdk/entity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def from_json(txt: dict | str):
8282
txt.get("description", ""),
8383
)
8484

85-
def to_json(self):
85+
def to_json(self) -> dict:
8686
"""
8787
Convert the entity object to a JSON representation.
8888

graphrag_sdk/kg.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,21 @@ def __init__(
5858
if not isinstance(name, str) or name == "":
5959
raise Exception("name should be a non empty string")
6060

61-
# connect to database
61+
# Connect to database
6262
self.db = FalkorDB(host=host, port=port, username=username, password=password)
6363
self.graph = self.db.select_graph(name)
6464
ontology_graph = self.db.select_graph("{" + name + "}" + "_schema")
6565

6666
# Load / Save ontology to database
6767
if ontology is None:
68-
# load ontology from DB
69-
ontology = Ontology.from_graph(ontology_graph)
68+
# Load ontology from DB
69+
ontology = Ontology.from_schema_graph(ontology_graph)
70+
71+
if len(ontology.entities) == 0:
72+
raise Exception("The ontology is empty. Load a valid ontology or create one using the ontology module.")
7073
else:
71-
# save ontology to DB
74+
# Save ontology to DB
7275
ontology.save_to_graph(ontology_graph)
73-
74-
if ontology is None:
75-
raise Exception("Ontology is not defined")
7676

7777
self._ontology = ontology
7878
self._name = name

0 commit comments

Comments
 (0)