diff --git a/src/handlers/api.py b/src/handlers/api.py index cc0a89ad..732ff3bc 100644 --- a/src/handlers/api.py +++ b/src/handlers/api.py @@ -560,14 +560,14 @@ def write(self, chunk): class MetaKGPathFinderHandler(QueryHandler): """ - A handler for querying paths in a knowledge graph using MetaKGPathFinder. + A handler for querying paths in a knowledge graph using the custom MetaKGPathFinder module. Attributes: - name: Unique identifier for this handler. - kwargs: Configuration for GET request parameters. - The primary GET method accepts 'subject', 'object', and 'cutoff' parameters, then retrieves - and returns paths in JSON format between the specified entities up to the given 'cutoff' length. + The primary GET method accepts the required 'subject', 'object', and 'cutoff'(default=3) parameters, then retrieves + and returns paths in JSON format between the specified nodes up to the given 'cutoff' length. """ name = "metakgpathfinder" @@ -632,6 +632,11 @@ def setup_pathfinder_rawquery(self, expanded_fields): @capture_exceptions async def get(self, *args, **kwargs): + + # Check if subject and object are the same - not allowed + if self.args.subject == self.args.object: + raise ValueError("Subject and object must be different.") + query_data = {"q": self.args.q} # Initialize with the original subject and object, and setup for expansion @@ -675,6 +680,10 @@ async def get(self, *args, **kwargs): bte=self.args.bte ) + # # Error check path results + if "error" in paths_with_edges: + raise HTTPError(400, reason=str(paths_with_edges["error"])) + # Check if rawquery parameter is true -- respond with correct output if self.args.rawquery: raw_query_output = self.setup_pathfinder_rawquery(expanded_fields) diff --git a/src/index.py b/src/index.py index b8a3110a..1008630c 100644 --- a/src/index.py +++ b/src/index.py @@ -20,7 +20,8 @@ def run_routine(): class WebAppHandler(RequestHandler): def get(self): - self.render("../web-app/dist/index.html") + if os.path.exists("../web-app/dist/index.html"): + self.render("../web-app/dist/index.html") if __name__ == "__main__": diff --git a/src/utils/metakg/path_finder.py b/src/utils/metakg/path_finder.py index 8d8aa438..f72ea8c3 100644 --- a/src/utils/metakg/path_finder.py +++ b/src/utils/metakg/path_finder.py @@ -1,12 +1,8 @@ -import logging - import networkx as nx + from controller.metakg import MetaKG from model import ConsolidatedMetaKGDoc -logger = logging.basicConfig(level=logging.INFO, filename="missing_bte.log") - - class MetaKGPathFinder: def __init__(self, query_data=None, expanded_fields=None): """ @@ -104,7 +100,8 @@ def get_paths(self, cutoff=2, api_details=False, predicate_filter=None, bte=Fals If True, includes full details of the 'api' in the result. - predicate_filter: list (default=None) A list of predicates to filter the results by. - + - bte: bool (default=False) + If True, includes BTE information in the result. Returns: - all_paths_with_edges: list of dict A list containing paths and their edge information for all subject-object pairs. @@ -112,35 +109,42 @@ def get_paths(self, cutoff=2, api_details=False, predicate_filter=None, bte=Fals all_paths_with_edges = [] - # Predicate Filter Setup predicate_filter_set = set(predicate_filter) if predicate_filter else None + if 'predicate' in self.expanded_fields and self.expanded_fields['predicate']: predicate_filter_set.update(self.expanded_fields['predicate']) - # Graph iteration over subject-object pairs - for subject in self.expanded_fields["subject"]: - for object in self.expanded_fields["object"]: - try: - # Check if a path exists between the subject and object - if nx.has_path(self.G, subject, object): - raw_paths = nx.all_simple_paths(self.G, source=subject, target=object, cutoff=cutoff) - for path in raw_paths: - paths_data = {"path": path, "edges": []} - edge_added = False - for i in range(len(path) - 1): - source_node = path[i] - target_node = path[i + 1] - edge_key = f"{source_node}-{target_node}" - edge_data = self.predicates.get(edge_key, []) - - for data in edge_data: - if predicate_filter_set and data["predicate"] not in predicate_filter_set: - continue - paths_data = self.build_edge_results(paths_data, data, api_details, source_node, target_node, bte) - edge_added = True - if edge_added: - all_paths_with_edges.append(paths_data) - except Exception: - continue - - return all_paths_with_edges + try: + # Graph iteration over subject-object pairs + for subject in self.expanded_fields["subject"]: + for object in self.expanded_fields["object"]: + if subject not in self.G: + return { "error": f"Subject node {subject} is not found in the MetaKG" } + if object not in self.G: + return { "error": f"Object node {object} is not found in the MetaKG" } + try: + # Check if a path exists between the subject and object + if nx.has_path(self.G, subject, object): + raw_paths = nx.all_simple_paths(self.G, source=subject, target=object, cutoff=cutoff) + for path in raw_paths: + paths_data = {"path": path, "edges": []} + edge_added = False + for i in range(len(path) - 1): + source_node = path[i] + target_node = path[i + 1] + edge_key = f"{source_node}-{target_node}" + edge_data = self.predicates.get(edge_key, []) + + for data in edge_data: + if predicate_filter_set and data["predicate"] not in predicate_filter_set: + continue + paths_data = self.build_edge_results(paths_data, data, api_details, source_node, target_node, bte) + edge_added = True + if edge_added: + all_paths_with_edges.append(paths_data) + except nx.exception.NodeNotFound as node_err: + return { "error": node_err } + return all_paths_with_edges + + except Exception as e: + return { "error": e }