Revert "Cleanup of code"
Browse files- lightrag/api/lightrag_server.py +5 -0
- lightrag/base.py +4 -0
- lightrag/kg/age_impl.py +7 -0
- lightrag/kg/gremlin_impl.py +3 -0
- lightrag/kg/mongo_impl.py +18 -0
- lightrag/kg/neo4j_impl.py +25 -0
- lightrag/kg/networkx_impl.py +3 -0
- lightrag/kg/oracle_impl.py +3 -0
- lightrag/kg/postgres_impl.py +8 -3
- lightrag/kg/tidb_impl.py +3 -0
- lightrag/lightrag.py +4 -0
- lightrag/tools/lightrag_visualizer/graph_visualizer.py +1 -4
lightrag/api/lightrag_server.py
CHANGED
@@ -1682,6 +1682,11 @@ def create_app(args):
|
|
1682 |
trace_exception(e)
|
1683 |
raise HTTPException(status_code=500, detail=str(e))
|
1684 |
|
|
|
|
|
|
|
|
|
|
|
1685 |
# query all graph
|
1686 |
@app.get("/graphs")
|
1687 |
async def get_knowledge_graph(label: str):
|
|
|
1682 |
trace_exception(e)
|
1683 |
raise HTTPException(status_code=500, detail=str(e))
|
1684 |
|
1685 |
+
# query all graph labels
|
1686 |
+
@app.get("/graph/label/list")
|
1687 |
+
async def get_graph_labels():
|
1688 |
+
return await rag.get_graph_labels()
|
1689 |
+
|
1690 |
# query all graph
|
1691 |
@app.get("/graphs")
|
1692 |
async def get_knowledge_graph(label: str):
|
lightrag/base.py
CHANGED
@@ -198,6 +198,10 @@ class BaseGraphStorage(StorageNameSpace, ABC):
|
|
198 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
199 |
"""Get all labels in the graph."""
|
200 |
|
|
|
|
|
|
|
|
|
201 |
@abstractmethod
|
202 |
async def get_knowledge_graph(
|
203 |
self, node_label: str, max_depth: int = 5
|
|
|
198 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
199 |
"""Get all labels in the graph."""
|
200 |
|
201 |
+
@abstractmethod
|
202 |
+
async def get_all_labels(self) -> list[str]:
|
203 |
+
"""Get a knowledge graph of a node."""
|
204 |
+
|
205 |
@abstractmethod
|
206 |
async def get_knowledge_graph(
|
207 |
self, node_label: str, max_depth: int = 5
|
lightrag/kg/age_impl.py
CHANGED
@@ -60,6 +60,10 @@ class AGEQueryException(Exception):
|
|
60 |
@final
|
61 |
@dataclass
|
62 |
class AGEStorage(BaseGraphStorage):
|
|
|
|
|
|
|
|
|
63 |
def __init__(self, namespace, global_config, embedding_func):
|
64 |
super().__init__(
|
65 |
namespace=namespace,
|
@@ -616,6 +620,9 @@ class AGEStorage(BaseGraphStorage):
|
|
616 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
617 |
raise NotImplementedError
|
618 |
|
|
|
|
|
|
|
619 |
async def get_knowledge_graph(
|
620 |
self, node_label: str, max_depth: int = 5
|
621 |
) -> KnowledgeGraph:
|
|
|
60 |
@final
|
61 |
@dataclass
|
62 |
class AGEStorage(BaseGraphStorage):
|
63 |
+
@staticmethod
|
64 |
+
def load_nx_graph(file_name):
|
65 |
+
print("no preloading of graph with AGE in production")
|
66 |
+
|
67 |
def __init__(self, namespace, global_config, embedding_func):
|
68 |
super().__init__(
|
69 |
namespace=namespace,
|
|
|
620 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
621 |
raise NotImplementedError
|
622 |
|
623 |
+
async def get_all_labels(self) -> list[str]:
|
624 |
+
raise NotImplementedError
|
625 |
+
|
626 |
async def get_knowledge_graph(
|
627 |
self, node_label: str, max_depth: int = 5
|
628 |
) -> KnowledgeGraph:
|
lightrag/kg/gremlin_impl.py
CHANGED
@@ -403,6 +403,9 @@ class GremlinStorage(BaseGraphStorage):
|
|
403 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
404 |
raise NotImplementedError
|
405 |
|
|
|
|
|
|
|
406 |
async def get_knowledge_graph(
|
407 |
self, node_label: str, max_depth: int = 5
|
408 |
) -> KnowledgeGraph:
|
|
|
403 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
404 |
raise NotImplementedError
|
405 |
|
406 |
+
async def get_all_labels(self) -> list[str]:
|
407 |
+
raise NotImplementedError
|
408 |
+
|
409 |
async def get_knowledge_graph(
|
410 |
self, node_label: str, max_depth: int = 5
|
411 |
) -> KnowledgeGraph:
|
lightrag/kg/mongo_impl.py
CHANGED
@@ -601,6 +601,24 @@ class MongoGraphStorage(BaseGraphStorage):
|
|
601 |
# -------------------------------------------------------------------------
|
602 |
#
|
603 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
604 |
async def get_knowledge_graph(
|
605 |
self, node_label: str, max_depth: int = 5
|
606 |
) -> KnowledgeGraph:
|
|
|
601 |
# -------------------------------------------------------------------------
|
602 |
#
|
603 |
|
604 |
+
async def get_all_labels(self) -> list[str]:
|
605 |
+
"""
|
606 |
+
Get all existing node _id in the database
|
607 |
+
Returns:
|
608 |
+
[id1, id2, ...] # Alphabetically sorted id list
|
609 |
+
"""
|
610 |
+
# Use MongoDB's distinct and aggregation to get all unique labels
|
611 |
+
pipeline = [
|
612 |
+
{"$group": {"_id": "$_id"}}, # Group by _id
|
613 |
+
{"$sort": {"_id": 1}}, # Sort alphabetically
|
614 |
+
]
|
615 |
+
|
616 |
+
cursor = self.collection.aggregate(pipeline)
|
617 |
+
labels = []
|
618 |
+
async for doc in cursor:
|
619 |
+
labels.append(doc["_id"])
|
620 |
+
return labels
|
621 |
+
|
622 |
async def get_knowledge_graph(
|
623 |
self, node_label: str, max_depth: int = 5
|
624 |
) -> KnowledgeGraph:
|
lightrag/kg/neo4j_impl.py
CHANGED
@@ -628,6 +628,31 @@ class Neo4JStorage(BaseGraphStorage):
|
|
628 |
await traverse(label, 0)
|
629 |
return result
|
630 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
631 |
async def delete_node(self, node_id: str) -> None:
|
632 |
raise NotImplementedError
|
633 |
|
|
|
628 |
await traverse(label, 0)
|
629 |
return result
|
630 |
|
631 |
+
async def get_all_labels(self) -> list[str]:
|
632 |
+
"""
|
633 |
+
Get all existing node labels in the database
|
634 |
+
Returns:
|
635 |
+
["Person", "Company", ...] # Alphabetically sorted label list
|
636 |
+
"""
|
637 |
+
async with self._driver.session(database=self._DATABASE) as session:
|
638 |
+
# Method 1: Direct metadata query (Available for Neo4j 4.3+)
|
639 |
+
# query = "CALL db.labels() YIELD label RETURN label"
|
640 |
+
|
641 |
+
# Method 2: Query compatible with older versions
|
642 |
+
query = """
|
643 |
+
MATCH (n)
|
644 |
+
WITH DISTINCT labels(n) AS node_labels
|
645 |
+
UNWIND node_labels AS label
|
646 |
+
RETURN DISTINCT label
|
647 |
+
ORDER BY label
|
648 |
+
"""
|
649 |
+
|
650 |
+
result = await session.run(query)
|
651 |
+
labels = []
|
652 |
+
async for record in result:
|
653 |
+
labels.append(record["label"])
|
654 |
+
return labels
|
655 |
+
|
656 |
async def delete_node(self, node_id: str) -> None:
|
657 |
raise NotImplementedError
|
658 |
|
lightrag/kg/networkx_impl.py
CHANGED
@@ -168,6 +168,9 @@ class NetworkXStorage(BaseGraphStorage):
|
|
168 |
if self._graph.has_edge(source, target):
|
169 |
self._graph.remove_edge(source, target)
|
170 |
|
|
|
|
|
|
|
171 |
async def get_knowledge_graph(
|
172 |
self, node_label: str, max_depth: int = 5
|
173 |
) -> KnowledgeGraph:
|
|
|
168 |
if self._graph.has_edge(source, target):
|
169 |
self._graph.remove_edge(source, target)
|
170 |
|
171 |
+
async def get_all_labels(self) -> list[str]:
|
172 |
+
raise NotImplementedError
|
173 |
+
|
174 |
async def get_knowledge_graph(
|
175 |
self, node_label: str, max_depth: int = 5
|
176 |
) -> KnowledgeGraph:
|
lightrag/kg/oracle_impl.py
CHANGED
@@ -670,6 +670,9 @@ class OracleGraphStorage(BaseGraphStorage):
|
|
670 |
async def delete_node(self, node_id: str) -> None:
|
671 |
raise NotImplementedError
|
672 |
|
|
|
|
|
|
|
673 |
async def get_knowledge_graph(
|
674 |
self, node_label: str, max_depth: int = 5
|
675 |
) -> KnowledgeGraph:
|
|
|
670 |
async def delete_node(self, node_id: str) -> None:
|
671 |
raise NotImplementedError
|
672 |
|
673 |
+
async def get_all_labels(self) -> list[str]:
|
674 |
+
raise NotImplementedError
|
675 |
+
|
676 |
async def get_knowledge_graph(
|
677 |
self, node_label: str, max_depth: int = 5
|
678 |
) -> KnowledgeGraph:
|
lightrag/kg/postgres_impl.py
CHANGED
@@ -178,10 +178,12 @@ class PostgreSQLDB:
|
|
178 |
asyncpg.exceptions.UniqueViolationError,
|
179 |
asyncpg.exceptions.DuplicateTableError,
|
180 |
) as e:
|
181 |
-
if
|
182 |
-
|
|
|
|
|
183 |
except Exception as e:
|
184 |
-
logger.error(f"PostgreSQL database
|
185 |
raise
|
186 |
|
187 |
|
@@ -1085,6 +1087,9 @@ class PGGraphStorage(BaseGraphStorage):
|
|
1085 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
1086 |
raise NotImplementedError
|
1087 |
|
|
|
|
|
|
|
1088 |
async def get_knowledge_graph(
|
1089 |
self, node_label: str, max_depth: int = 5
|
1090 |
) -> KnowledgeGraph:
|
|
|
178 |
asyncpg.exceptions.UniqueViolationError,
|
179 |
asyncpg.exceptions.DuplicateTableError,
|
180 |
) as e:
|
181 |
+
if upsert:
|
182 |
+
print("Key value duplicate, but upsert succeeded.")
|
183 |
+
else:
|
184 |
+
logger.error(f"Upsert error: {e}")
|
185 |
except Exception as e:
|
186 |
+
logger.error(f"PostgreSQL database,\nsql:{sql},\ndata:{data},\nerror:{e}")
|
187 |
raise
|
188 |
|
189 |
|
|
|
1087 |
) -> tuple[np.ndarray[Any, Any], list[str]]:
|
1088 |
raise NotImplementedError
|
1089 |
|
1090 |
+
async def get_all_labels(self) -> list[str]:
|
1091 |
+
raise NotImplementedError
|
1092 |
+
|
1093 |
async def get_knowledge_graph(
|
1094 |
self, node_label: str, max_depth: int = 5
|
1095 |
) -> KnowledgeGraph:
|
lightrag/kg/tidb_impl.py
CHANGED
@@ -560,6 +560,9 @@ class TiDBGraphStorage(BaseGraphStorage):
|
|
560 |
async def delete_node(self, node_id: str) -> None:
|
561 |
raise NotImplementedError
|
562 |
|
|
|
|
|
|
|
563 |
async def get_knowledge_graph(
|
564 |
self, node_label: str, max_depth: int = 5
|
565 |
) -> KnowledgeGraph:
|
|
|
560 |
async def delete_node(self, node_id: str) -> None:
|
561 |
raise NotImplementedError
|
562 |
|
563 |
+
async def get_all_labels(self) -> list[str]:
|
564 |
+
raise NotImplementedError
|
565 |
+
|
566 |
async def get_knowledge_graph(
|
567 |
self, node_label: str, max_depth: int = 5
|
568 |
) -> KnowledgeGraph:
|
lightrag/lightrag.py
CHANGED
@@ -458,6 +458,10 @@ class LightRAG:
|
|
458 |
self._storages_status = StoragesStatus.FINALIZED
|
459 |
logger.debug("Finalized Storages")
|
460 |
|
|
|
|
|
|
|
|
|
461 |
async def get_knowledge_graph(
|
462 |
self, nodel_label: str, max_depth: int
|
463 |
) -> KnowledgeGraph:
|
|
|
458 |
self._storages_status = StoragesStatus.FINALIZED
|
459 |
logger.debug("Finalized Storages")
|
460 |
|
461 |
+
async def get_graph_labels(self):
|
462 |
+
text = await self.chunk_entity_relation_graph.get_all_labels()
|
463 |
+
return text
|
464 |
+
|
465 |
async def get_knowledge_graph(
|
466 |
self, nodel_label: str, max_depth: int
|
467 |
) -> KnowledgeGraph:
|
lightrag/tools/lightrag_visualizer/graph_visualizer.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
from typing import Optional, Tuple, Dict, List
|
2 |
import numpy as np
|
3 |
-
|
4 |
import pipmaster as pm
|
5 |
|
6 |
# Added automatic libraries install using pipmaster
|
@@ -12,10 +12,7 @@ if not pm.is_installed("pyglm"):
|
|
12 |
pm.install("pyglm")
|
13 |
if not pm.is_installed("python-louvain"):
|
14 |
pm.install("python-louvain")
|
15 |
-
if not pm.is_installed("networkx"):
|
16 |
-
pm.install("networkx")
|
17 |
|
18 |
-
import networkx as nx
|
19 |
import moderngl
|
20 |
from imgui_bundle import imgui, immapp, hello_imgui
|
21 |
import community
|
|
|
1 |
from typing import Optional, Tuple, Dict, List
|
2 |
import numpy as np
|
3 |
+
import networkx as nx
|
4 |
import pipmaster as pm
|
5 |
|
6 |
# Added automatic libraries install using pipmaster
|
|
|
12 |
pm.install("pyglm")
|
13 |
if not pm.is_installed("python-louvain"):
|
14 |
pm.install("python-louvain")
|
|
|
|
|
15 |
|
|
|
16 |
import moderngl
|
17 |
from imgui_bundle import imgui, immapp, hello_imgui
|
18 |
import community
|