Spaces:
Runtime error
Runtime error
| import asyncio | |
| import logging | |
| from pathlib import Path | |
| import pandas as pd | |
| logger = logging.getLogger(__name__) | |
| class GraphRAGEngine: | |
| def __init__(self, root_dir: str): | |
| self.root_dir = Path(root_dir) | |
| self.global_search = None | |
| self.local_search = None | |
| self._loaded = False | |
| self._load_error = None | |
| def load(self): | |
| try: | |
| self._build_search_engines() | |
| self._loaded = True | |
| logger.info("GraphRAG engine loaded into memory") | |
| except Exception as e: | |
| self._load_error = str(e) | |
| logger.error(f"Engine load failed: {e}") | |
| raise | |
| def query_sync(self, question: str, method: str) -> str: | |
| if not self._loaded: | |
| raise RuntimeError(f"Engine not loaded: {self._load_error}") | |
| async def _run(): | |
| if method == "global": | |
| result = await self.global_search.search(question) | |
| else: | |
| result = await self.local_search.search(question) | |
| return result.response | |
| return asyncio.run(_run()) | |
| def _build_search_engines(self): | |
| from graphrag.config.load_config import load_config | |
| from graphrag.query.factory import get_global_search_engine, get_local_search_engine | |
| from graphrag.query.indexer_adapters import ( | |
| read_indexer_communities, | |
| read_indexer_entities, | |
| read_indexer_relationships, | |
| read_indexer_reports, | |
| read_indexer_text_units, | |
| ) | |
| from graphrag.vector_stores.lancedb import LanceDBVectorStore | |
| config = load_config(root_dir=self.root_dir) | |
| reduce_prompt_path = self.root_dir / "prompts" / "global_search_reduce_system_prompt.txt" | |
| reduce_prompt = reduce_prompt_path.read_text(encoding="utf-8") if reduce_prompt_path.exists() else None | |
| map_prompt_path = self.root_dir / "prompts" / "global_search_map_system_prompt.txt" | |
| map_prompt = map_prompt_path.read_text(encoding="utf-8") if map_prompt_path.exists() else None | |
| out = self.root_dir / "output" | |
| entities_df = pd.read_parquet(out / "entities.parquet") | |
| communities_df = pd.read_parquet(out / "communities.parquet") | |
| community_reports_df = pd.read_parquet(out / "community_reports.parquet") | |
| relationships_df = pd.read_parquet(out / "relationships.parquet") | |
| text_units_df = pd.read_parquet(out / "text_units.parquet") | |
| COMMUNITY_LEVEL = 2 | |
| entities = read_indexer_entities(entities_df, communities_df, COMMUNITY_LEVEL) | |
| relationships = read_indexer_relationships(relationships_df) | |
| communities = read_indexer_communities(communities_df, community_reports_df) | |
| reports = read_indexer_reports(community_reports_df, communities_df, COMMUNITY_LEVEL) | |
| text_units = read_indexer_text_units(text_units_df) | |
| logger.info( | |
| f"Loaded: {len(entities)} entities, {len(relationships)} relationships, " | |
| f"{len(communities)} communities, {len(reports)} reports, {len(text_units)} text units" | |
| ) | |
| lancedb_uri = str(self.root_dir / "output" / "lancedb") | |
| collection = self._detect_entity_collection(lancedb_uri) | |
| logger.info(f"Using LanceDB collection: {collection}") | |
| entity_embedding_store = LanceDBVectorStore(collection_name=collection) | |
| entity_embedding_store.connect(db_uri=lancedb_uri) | |
| self.global_search = get_global_search_engine( | |
| config=config, | |
| reports=reports, | |
| entities=entities, | |
| communities=communities, | |
| response_type="multiple paragraphs", | |
| map_system_prompt=map_prompt, | |
| reduce_system_prompt=reduce_prompt, | |
| ) | |
| self.local_search = get_local_search_engine( | |
| config=config, | |
| reports=reports, | |
| text_units=text_units, | |
| entities=entities, | |
| relationships=relationships, | |
| covariates={}, | |
| description_embedding_store=entity_embedding_store, | |
| response_type="multiple paragraphs", | |
| ) | |
| def _detect_entity_collection(lancedb_uri: str) -> str: | |
| try: | |
| import lancedb | |
| db = lancedb.connect(lancedb_uri) | |
| tables = db.table_names() | |
| logger.info(f"LanceDB tables found: {tables}") | |
| for candidate in tables: | |
| if "entity" in candidate.lower(): | |
| return candidate | |
| if tables: | |
| return tables[0] | |
| except Exception as e: | |
| logger.warning(f"LanceDB detection failed: {e}") | |
| return "default-entity-description" | |
| _engine = None | |
| def get_engine(): | |
| global _engine | |
| if _engine is None: | |
| raise RuntimeError("Engine not initialised. Call init_engine() first.") | |
| return _engine | |
| def init_engine(root_dir: str): | |
| global _engine | |
| if _engine is None: | |
| _engine = GraphRAGEngine(root_dir) | |
| _engine.load() | |
| return _engine |