class RelationshipIdentifier: """Identifies relationships between nodes in a graph database.""" RELATIONSHIP_EXAMPLE = [ ("NodeLabel1", "RelationshipLabel", "NodeLabel2"), ("NodeLabel1", "RelationshipLabel", "NodeLabel3"), ("NodeLabel2", "RelationshipLabel", "NodeLabel3"), ] PROMPT_TEMPLATE = PromptTemplate( input_variables=["structure", "node_definitions", "example"], template=""" Consider the following Dataset Structure:n{structure}nn Consider the following Node Definitions:n{node_definitions}nn Based on the dataset structure and node definitions, identify relationships (edges) between nodes.n Return the relationships as a list of triples where each triple contains the start node label, relationship label, and end node label, and each triple is a tuple.n Please return only the list of tuples. Please do not report triple backticks to identify a code block, just return the list of tuples.nn Example:n{example} """ ) def __init__(self, llm: Any, logger: logging.Logger = None): self.llm = llm self.logger = logger or logging.getLogger(__name__) self.chain = self.PROMPT_TEMPLATE | self.llm def validate_relationships(self, relationships: List[Tuple]) -> bool: """Validate relationship structure.""" return all( isinstance(rel, tuple) and len(rel) == 3 and all(isinstance(x, str) for x in rel) for rel in relationships ) @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10)) def identify_relationships(self, structure: str, node_definitions: Dict) -> List[Tuple]: """Identify relationships with retry logic.""" try: response = self.chain.invoke({ "structure": structure, "node_definitions": str(node_definitions), "example": str(self.RELATIONSHIP_EXAMPLE) }) relationships = ast.literal_eval(response) if not self.validate_relationships(relationships): raise ValueError("Invalid relationship structure") self.logger.info(f"Identified {len(relationships)} relationships") return relationships except Exception as e: self.logger.error(f"Error identifying relationships: {e}") raise def get_relationship_types(self) -> List[str]: """Extract unique relationship types.""" return list(set(rel[1] for rel in self.identify_relationships())) # Usage identifier = RelationshipIdentifier(llm=llm) relationships = identifier.identify_relationships(node_structure, node_definitions) print("Relationships:", relationships)