LangChainWiseAgentGraphDB

Bases: WiseAgentGraphDB

An abstract class that makes use of a LangChain graph database.

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class LangChainWiseAgentGraphDB(WiseAgentGraphDB):
    """
    An abstract class that makes use of a LangChain graph database.
    """

    def __init__(self, embedding_model_name: Optional[str] = DEFAULT_EMBEDDING_MODEL_NAME):
        """
        Initialize a new instance of LangChainWiseAgentGraphDB.


        Args:
            embedding_model_name (Optional[str]): the optional name of the embedding model to use 
        """
        self._embedding_model_name = embedding_model_name
        self._embedding_function = HuggingFaceEmbeddings(model_name=self.embedding_model_name)

    @property
    def embedding_model_name(self):
        """Get the name of the embedding model."""
        return self._embedding_model_name

    def convert_to_lang_chain_node(self, entity: Entity) -> Node:
        return Node(id=entity.id, type=entity.label, properties=entity.metadata)

    def convert_to_lang_chain_relationship(self, relationship: Relationship) -> LangChainRelationship:
        return LangChainRelationship(source=self.convert_to_lang_chain_node(relationship.source),
                                     target=self.convert_to_lang_chain_node(relationship.target),
                                     type=relationship.label,
                                     properties=relationship.metadata)

    def convert_to_lang_chain_graph_document(self, graph_document: GraphDocument) -> LangChainGraphDocument:
        return LangChainGraphDocument(nodes=[self.convert_to_lang_chain_node(entity)
                                             for entity in graph_document.entities],
                                      relationships=[self.convert_to_lang_chain_relationship(relationship)
                                                     for relationship in graph_document.relationships],
                                      source=self.convert_to_lang_chain_document(graph_document.source))

    def convert_to_lang_chain_document(self, source: Source) -> LangChainDocument:
        return LangChainDocument(id=source.id, page_content=source.content, metadata=source.metadata)

    @abstractmethod
    def get_schema(self) -> str:
        ...

    @abstractmethod
    def refresh_schema(self):
        ...

    @abstractmethod
    def query(self, query: str, params: Optional[dict] = None):
        ...

    @abstractmethod
    def insert_entity(self, entity: Entity, source: Source):
        ...

    @abstractmethod
    def insert_relationship(self, relationship: Relationship, source: Source):
        ...

    @abstractmethod
    def insert_graph_documents(self, graph_documents: List[GraphDocument]):
        ...

    @abstractmethod
    def create_vector_db_from_graph_db(self, retrieval_query: str = ""):
        ...

embedding_model_name property

Get the name of the embedding model.

__init__(embedding_model_name=DEFAULT_EMBEDDING_MODEL_NAME)

Initialize a new instance of LangChainWiseAgentGraphDB.

Parameters:
  • embedding_model_name (Optional[str], default: DEFAULT_EMBEDDING_MODEL_NAME ) –

    the optional name of the embedding model to use

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
21
22
23
24
25
26
27
28
29
30
def __init__(self, embedding_model_name: Optional[str] = DEFAULT_EMBEDDING_MODEL_NAME):
    """
    Initialize a new instance of LangChainWiseAgentGraphDB.


    Args:
        embedding_model_name (Optional[str]): the optional name of the embedding model to use 
    """
    self._embedding_model_name = embedding_model_name
    self._embedding_function = HuggingFaceEmbeddings(model_name=self.embedding_model_name)

Neo4jLangChainWiseAgentGraphDB

Bases: LangChainWiseAgentGraphDB

A LangChainWiseAgentGraphDB implementation that makes use of a LangChain Neo4j graph database and a corresponding Neo4j vector database.

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
class Neo4jLangChainWiseAgentGraphDB(LangChainWiseAgentGraphDB):
    """
    A LangChainWiseAgentGraphDB implementation that makes use of a LangChain Neo4j graph database
    and a corresponding Neo4j vector database.
    """
    yaml_tag = u'!Neo4jLangChainWiseAgentGraphDB'

    def __init__(self, properties: List[str], collection_name: str, url: Optional[str] = None,
                 refresh_graph_schema: Optional[bool] = True,
                 embedding_model_name: Optional[str] = DEFAULT_EMBEDDING_MODEL_NAME,
                 entity_label: Optional[str] = "entity"):
        """
        Initialize a new instance of Neo4jLangChainWiseAgent


        Args:
            properties (List[str]): the properties to be used as text node properties for the graph database
            collection_name (str): the collection name to use for the vector database
            url (Optional[str]): the URL of the Neo4j database (the username, password, and database name to be used
            will be obtained from the NEO4J_USERNAME, NEO4J_PASSWORD, and NEO4J_DATABASE environment variables)
            refresh_graph_schema (Optional[bool]): whether to refresh the graph schema
            embedding_model_name (Optional[str]): the optional name of the embedding model to use
            entity_label (Optional[str]): the label to use for entities in the graph database
        """
        super().__init__(embedding_model_name)
        self._properties = properties
        self._collection_name = collection_name
        self._url = url
        self._refresh_graph_schema = refresh_graph_schema
        self._entity_label = entity_label
        self._neo4j_graph_db = None
        self._neo4j_vector_db = None

    def __repr__(self):
        """Return a string representation of the graph DB."""
        return (f"{self.__class__.__name__}(properties={self.properties}, url={self.url}, refresh_schema={self.refresh_graph_schema},"
                f"embedding_model_name={self.embedding_model_name}, collection_name={self.collection_name},"
                f"entity_label={self._entity_label}")

    def __getstate__(self) -> object:
        """Return the state of the graph DB. Removing the instance variable neo4j_graph_db to avoid it being serialized/deserialized by pyyaml."""
        state = self.__dict__.copy()
        del state['_neo4j_graph_db']
        del state['_neo4j_vector_db']
        del state['_embedding_function']
        return state

    @classmethod
    def from_yaml(cls, loader, node):
        data = loader.construct_mapping(node, deep=True)
        url = data.get('_url', None)
        refresh_graph_schema = data.get('_refresh_graph_schema', True)
        embedding_model_name = data.get('_embedding_model_name', DEFAULT_EMBEDDING_MODEL_NAME)
        entity_label = data.get('_entity_label', "entity")
        return cls(properties=data.get('_properties'), collection_name=data.get('_collection_name'),
                   url=url, refresh_graph_schema=refresh_graph_schema, embedding_model_name=embedding_model_name,
                   entity_label=entity_label)

    @property
    def properties(self):
        """Get the properties to be used as text node properties for the graph database."""
        return self._properties

    @property
    def collection_name(self):
        """Get the collection name to use for the vector database."""
        return self._collection_name

    @property
    def entity_label(self):
        """Get the label to use for entities in the graph database."""
        return self._entity_label

    @property
    def url(self):
        """Get the URL of the Neo4j database."""
        return self._url

    @property
    def refresh_graph_schema(self):
        """Get whether to refresh the graph schema."""
        return self._refresh_graph_schema

    def connect(self):
        if self._neo4j_graph_db is None:
            self._neo4j_graph_db = Neo4jGraph(url=self.url, refresh_schema=self.refresh_graph_schema)

    def get_schema(self) -> str:
        self.connect()
        return self._neo4j_graph_db.get_schema

    def refresh_schema(self):
        self.connect()
        self._neo4j_graph_db.refresh_schema()

    def query(self, query: str, params: Optional[dict] = None):
        self.connect()
        return self._neo4j_graph_db.query(query=query, params=params)

    def insert_entity(self, entity: Entity, source: Source):
        self.connect()
        self.insert_graph_documents([GraphDocument(entities=[entity],
                                                   relationships=[],
                                                   source=source)])

    def insert_relationship(self, relationship: Relationship, source: Source):
        self.connect()
        self.insert_graph_documents([GraphDocument(entities=[],
                                                   relationships=[relationship],
                                                   source=source)])

    def insert_graph_documents(self, graph_documents: List[GraphDocument]):
        self.connect()
        self._neo4j_graph_db.add_graph_documents([self.convert_to_lang_chain_graph_document(graph_document)
                                                  for graph_document in graph_documents])

    def create_vector_db_from_graph_db(self, retrieval_query: str = ""):
        """
        Create a vector database from the graph database.


        Args:
            retrieval_query (str): the retrieval query to use for the vector database
        """
        self.connect()
        self._neo4j_vector_db = Neo4jVector.from_existing_graph(embedding=self._embedding_function,
                                                                node_label=self.entity_label,
                                                                embedding_node_property="embedding",
                                                                text_node_properties=self.properties,
                                                                url=self.url,
                                                                index_name=self.collection_name,
                                                                retrieval_query=retrieval_query)

    def query_with_embeddings(self, query: str, k: int, retrieval_query: str = "") -> List[Document]:
        """
        Query the vector database that corresponds to this graph database using the given query and
        retrieve the top k documents.


        Args:
            query (str): the query to execute
            k (int): the number of documents to retrieve
            retrieval_query (str): the retrieval query to use for the vector database

        Returns:
            List[Document]: the list of documents retrieved from the vector database
        """
        if self._neo4j_vector_db is None:
            # this assumes that the vector DB has already been created prior to attempting to query it
            # and we are simply retrieving the existing index here
            self.get_vector_db_from_existing_index(embedding_node_property="embedding", retrieval_query=retrieval_query)
        return [Document(content=doc.page_content, metadata=doc.metadata)
                for doc in self._neo4j_vector_db.similarity_search(query, k)]

    def get_vector_db_from_existing_index(self, embedding_node_property: str,
                                          retrieval_query: str = ""):
        # Neo4jVector.from_existing_graph doesn't currently work when using HuggingFaceEmbeddings
        # and trying to retrieve an existing graph (see https://github.com/langchain-ai/langchain/issues/24401).
        # We'll work around this using Neo4jVector.from_existing_index instead.
        self.connect()
        if not retrieval_query:
            retrieval_query = (
                    f"RETURN reduce(str='', k IN {self.properties} |"
                    " str + '\\n' + k + ': ' + coalesce(node[k], '')) AS text, "
                    "node {.*, `"
                    + embedding_node_property
                    + "`: Null, id: Null, "
                    + ", ".join([f"`{prop}`: Null" for prop in self.properties])
                    + "} AS metadata, score"
            )
        self._neo4j_vector_db = Neo4jVector.from_existing_index(embedding=self._embedding_function,
                                                                node_label=self.entity_label,
                                                                embedding_node_property="embedding",
                                                                url=self.url,
                                                                index_name=self.collection_name,
                                                                retrieval_query=retrieval_query,
                                                                keyword_index_name="keyword")

    def delete_vector_db(self):
        """
        Delete the vector database that corresponds to this graph database.
        """
        if self._neo4j_vector_db is not None:
            self._neo4j_vector_db.delete_index()
            self._neo4j_vector_db = None

    def close(self):
        """
        Close the Neo4j driver.
        """
        if self._neo4j_graph_db is not None:
            self._neo4j_graph_db._driver.close()
        if self._neo4j_vector_db is not None:
            self._neo4j_vector_db._driver.close()

collection_name property

Get the collection name to use for the vector database.

entity_label property

Get the label to use for entities in the graph database.

properties property

Get the properties to be used as text node properties for the graph database.

refresh_graph_schema property

Get whether to refresh the graph schema.

url property

Get the URL of the Neo4j database.

__getstate__()

Return the state of the graph DB. Removing the instance variable neo4j_graph_db to avoid it being serialized/deserialized by pyyaml.

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
124
125
126
127
128
129
130
def __getstate__(self) -> object:
    """Return the state of the graph DB. Removing the instance variable neo4j_graph_db to avoid it being serialized/deserialized by pyyaml."""
    state = self.__dict__.copy()
    del state['_neo4j_graph_db']
    del state['_neo4j_vector_db']
    del state['_embedding_function']
    return state

__init__(properties, collection_name, url=None, refresh_graph_schema=True, embedding_model_name=DEFAULT_EMBEDDING_MODEL_NAME, entity_label='entity')

Initialize a new instance of Neo4jLangChainWiseAgent

Parameters:
  • properties (List[str]) –

    the properties to be used as text node properties for the graph database

  • collection_name (str) –

    the collection name to use for the vector database

  • url (Optional[str], default: None ) –

    the URL of the Neo4j database (the username, password, and database name to be used

  • refresh_graph_schema (Optional[bool], default: True ) –

    whether to refresh the graph schema

  • embedding_model_name (Optional[str], default: DEFAULT_EMBEDDING_MODEL_NAME ) –

    the optional name of the embedding model to use

  • entity_label (Optional[str], default: 'entity' ) –

    the label to use for entities in the graph database

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
def __init__(self, properties: List[str], collection_name: str, url: Optional[str] = None,
             refresh_graph_schema: Optional[bool] = True,
             embedding_model_name: Optional[str] = DEFAULT_EMBEDDING_MODEL_NAME,
             entity_label: Optional[str] = "entity"):
    """
    Initialize a new instance of Neo4jLangChainWiseAgent


    Args:
        properties (List[str]): the properties to be used as text node properties for the graph database
        collection_name (str): the collection name to use for the vector database
        url (Optional[str]): the URL of the Neo4j database (the username, password, and database name to be used
        will be obtained from the NEO4J_USERNAME, NEO4J_PASSWORD, and NEO4J_DATABASE environment variables)
        refresh_graph_schema (Optional[bool]): whether to refresh the graph schema
        embedding_model_name (Optional[str]): the optional name of the embedding model to use
        entity_label (Optional[str]): the label to use for entities in the graph database
    """
    super().__init__(embedding_model_name)
    self._properties = properties
    self._collection_name = collection_name
    self._url = url
    self._refresh_graph_schema = refresh_graph_schema
    self._entity_label = entity_label
    self._neo4j_graph_db = None
    self._neo4j_vector_db = None

__repr__()

Return a string representation of the graph DB.

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
118
119
120
121
122
def __repr__(self):
    """Return a string representation of the graph DB."""
    return (f"{self.__class__.__name__}(properties={self.properties}, url={self.url}, refresh_schema={self.refresh_graph_schema},"
            f"embedding_model_name={self.embedding_model_name}, collection_name={self.collection_name},"
            f"entity_label={self._entity_label}")

close()

Close the Neo4j driver.

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
271
272
273
274
275
276
277
278
def close(self):
    """
    Close the Neo4j driver.
    """
    if self._neo4j_graph_db is not None:
        self._neo4j_graph_db._driver.close()
    if self._neo4j_vector_db is not None:
        self._neo4j_vector_db._driver.close()

create_vector_db_from_graph_db(retrieval_query='')

Create a vector database from the graph database.

Parameters:
  • retrieval_query (str, default: '' ) –

    the retrieval query to use for the vector database

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def create_vector_db_from_graph_db(self, retrieval_query: str = ""):
    """
    Create a vector database from the graph database.


    Args:
        retrieval_query (str): the retrieval query to use for the vector database
    """
    self.connect()
    self._neo4j_vector_db = Neo4jVector.from_existing_graph(embedding=self._embedding_function,
                                                            node_label=self.entity_label,
                                                            embedding_node_property="embedding",
                                                            text_node_properties=self.properties,
                                                            url=self.url,
                                                            index_name=self.collection_name,
                                                            retrieval_query=retrieval_query)

delete_vector_db()

Delete the vector database that corresponds to this graph database.

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
263
264
265
266
267
268
269
def delete_vector_db(self):
    """
    Delete the vector database that corresponds to this graph database.
    """
    if self._neo4j_vector_db is not None:
        self._neo4j_vector_db.delete_index()
        self._neo4j_vector_db = None

query_with_embeddings(query, k, retrieval_query='')

Query the vector database that corresponds to this graph database using the given query and retrieve the top k documents.

Parameters:
  • query (str) –

    the query to execute

  • k (int) –

    the number of documents to retrieve

  • retrieval_query (str, default: '' ) –

    the retrieval query to use for the vector database

Returns:
  • List[Document]

    List[Document]: the list of documents retrieved from the vector database

Source code in wiseagents/graphdb/lang_chain_wise_agent_graph_db.py
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
def query_with_embeddings(self, query: str, k: int, retrieval_query: str = "") -> List[Document]:
    """
    Query the vector database that corresponds to this graph database using the given query and
    retrieve the top k documents.


    Args:
        query (str): the query to execute
        k (int): the number of documents to retrieve
        retrieval_query (str): the retrieval query to use for the vector database

    Returns:
        List[Document]: the list of documents retrieved from the vector database
    """
    if self._neo4j_vector_db is None:
        # this assumes that the vector DB has already been created prior to attempting to query it
        # and we are simply retrieving the existing index here
        self.get_vector_db_from_existing_index(embedding_node_property="embedding", retrieval_query=retrieval_query)
    return [Document(content=doc.page_content, metadata=doc.metadata)
            for doc in self._neo4j_vector_db.similarity_search(query, k)]