Source code for langchain_community.graphs.networkx_graph
"""Networkx wrapper for graph operations."""from__future__importannotationsfromtypingimportAny,List,NamedTuple,Optional,TupleKG_TRIPLE_DELIMITER="<|>"
[docs]classKnowledgeTriple(NamedTuple):"""Knowledge triple in the graph."""subject:strpredicate:strobject_:str
[docs]@classmethoddeffrom_string(cls,triple_string:str)->"KnowledgeTriple":"""Create a KnowledgeTriple from a string."""subject,predicate,object_=triple_string.strip().split(", ")subject=subject[1:]object_=object_[:-1]returncls(subject,predicate,object_)
[docs]defparse_triples(knowledge_str:str)->List[KnowledgeTriple]:"""Parse knowledge triples from the knowledge string."""knowledge_str=knowledge_str.strip()ifnotknowledge_strorknowledge_str=="NONE":return[]triple_strs=knowledge_str.split(KG_TRIPLE_DELIMITER)results=[]fortriple_strintriple_strs:try:kg_triple=KnowledgeTriple.from_string(triple_str)exceptValueError:continueresults.append(kg_triple)returnresults
[docs]defget_entities(entity_str:str)->List[str]:"""Extract entities from entity string."""ifentity_str.strip()=="NONE":return[]else:return[w.strip()forwinentity_str.split(",")]
[docs]classNetworkxEntityGraph:"""Networkx wrapper for entity graph operations. *Security note*: Make sure that the database connection uses credentials that are narrowly-scoped to only include necessary permissions. Failure to do so may result in data corruption or loss, since the calling code may attempt commands that would result in deletion, mutation of data if appropriately prompted or reading sensitive data if such data is present in the database. The best way to guard against such negative outcomes is to (as appropriate) limit the permissions granted to the credentials used with this tool. See https://python.langchain.com/docs/security for more information. """
[docs]def__init__(self,graph:Optional[Any]=None)->None:"""Create a new graph."""try:importnetworkxasnxexceptImportError:raiseImportError("Could not import networkx python package. ""Please install it with `pip install networkx`.")ifgraphisnotNone:ifnotisinstance(graph,nx.DiGraph):raiseValueError("Passed in graph is not of correct shape")self._graph=graphelse:self._graph=nx.DiGraph()
[docs]@classmethoddeffrom_gml(cls,gml_path:str)->NetworkxEntityGraph:try:importnetworkxasnxexceptImportError:raiseImportError("Could not import networkx python package. ""Please install it with `pip install networkx`.")graph=nx.read_gml(gml_path)returncls(graph)
[docs]defadd_triple(self,knowledge_triple:KnowledgeTriple)->None:"""Add a triple to the graph."""# Creates nodes if they don't exist# Overwrites existing edgesifnotself._graph.has_node(knowledge_triple.subject):self._graph.add_node(knowledge_triple.subject)ifnotself._graph.has_node(knowledge_triple.object_):self._graph.add_node(knowledge_triple.object_)self._graph.add_edge(knowledge_triple.subject,knowledge_triple.object_,relation=knowledge_triple.predicate,)
[docs]defdelete_triple(self,knowledge_triple:KnowledgeTriple)->None:"""Delete a triple from the graph."""ifself._graph.has_edge(knowledge_triple.subject,knowledge_triple.object_):self._graph.remove_edge(knowledge_triple.subject,knowledge_triple.object_)
[docs]defget_triples(self)->List[Tuple[str,str,str]]:"""Get all triples in the graph."""return[(u,v,d["relation"])foru,v,dinself._graph.edges(data=True)]
[docs]defget_entity_knowledge(self,entity:str,depth:int=1)->List[str]:"""Get information about an entity."""importnetworkxasnx# TODO: Have more information-specific retrieval methodsifnotself._graph.has_node(entity):return[]results=[]forsrc,sinkinnx.dfs_edges(self._graph,entity,depth_limit=depth):relation=self._graph[src][sink]["relation"]results.append(f"{src}{relation}{sink}")returnresults
[docs]defclear(self)->None:"""Clear the graph."""self._graph.clear()
[docs]defclear_edges(self)->None:"""Clear the graph edges."""self._graph.clear_edges()
[docs]defadd_node(self,node:str)->None:"""Add node in the graph."""self._graph.add_node(node)
[docs]defremove_node(self,node:str)->None:"""Remove node from the graph."""ifself._graph.has_node(node):self._graph.remove_node(node)
[docs]defhas_node(self,node:str)->bool:"""Return if graph has the given node."""returnself._graph.has_node(node)
[docs]defremove_edge(self,source_node:str,destination_node:str)->None:"""Remove edge from the graph."""self._graph.remove_edge(source_node,destination_node)
[docs]defhas_edge(self,source_node:str,destination_node:str)->bool:"""Return if graph has an edge between the given nodes."""ifself._graph.has_node(source_node)andself._graph.has_node(destination_node):returnself._graph.has_edge(source_node,destination_node)else:returnFalse
[docs]defget_neighbors(self,node:str)->List[str]:"""Return the neighbor nodes of the given node."""returnself._graph.neighbors(node)
[docs]defget_number_of_nodes(self)->int:"""Get number of nodes in the graph."""returnself._graph.number_of_nodes()
[docs]defget_topological_sort(self)->List[str]:"""Get a list of entity names in the graph sorted by causal dependence."""importnetworkxasnxreturnlist(nx.topological_sort(self._graph))
[docs]defdraw_graphviz(self,**kwargs:Any)->None:""" Provides better drawing Usage in a jupyter notebook: >>> from IPython.display import SVG >>> self.draw_graphviz_svg(layout="dot", filename="web.svg") >>> SVG('web.svg') """fromnetworkx.drawing.nx_agraphimportto_agraphtry:importpygraphviz# noqa: F401exceptImportErrorase:ife.name=="_graphviz":""" >>> e.msg # pygraphviz throws this error ImportError: libcgraph.so.6: cannot open shared object file """raiseImportError("Could not import graphviz debian package. ""Please install it with:""`sudo apt-get update`""`sudo apt-get install graphviz graphviz-dev`")else:raiseImportError("Could not import pygraphviz python package. ""Please install it with:""`pip install pygraphviz`.")graph=to_agraph(self._graph)# --> pygraphviz.agraph.AGraph# pygraphviz.github.io/documentation/stable/tutorial.html#layout-and-drawinggraph.layout(prog=kwargs.get("prog","dot"))graph.draw(kwargs.get("path","graph.svg"))