Files
hkuds--lightrag/examples/graph_visual_with_opensearch.py
2026-07-13 12:08:54 +08:00

167 lines
5.0 KiB
Python

"""
Knowledge Graph Visualization with OpenSearch + LightRAG WebUI
This script demonstrates two ways to visualize the knowledge graph
stored in OpenSearch:
1. **WebUI (recommended)**: Opens the LightRAG WebUI in your browser
for interactive graph exploration with search, filtering, and
force-directed layout.
2. **Standalone HTML**: Fetches graph data from the LightRAG Server API
and generates an interactive HTML file using Pyvis, similar to
graph_visual_with_html.py but reading from OpenSearch instead of
a local .graphml file.
Prerequisites:
1. LightRAG Server running with OpenSearch storage:
lightrag-server --host 0.0.0.0 --port 9621
2. Documents already indexed (e.g., via the WebUI or API)
Usage:
# Open WebUI for interactive exploration
python examples/graph_visual_with_opensearch.py
# Generate standalone HTML file
python examples/graph_visual_with_opensearch.py --html
# Custom server URL and output file
python examples/graph_visual_with_opensearch.py --html --server http://localhost:9621 --output my_graph.html
"""
import argparse
import os
import sys
import webbrowser
import pipmaster as pm
if not pm.is_installed("requests"):
pm.install("requests")
if not pm.is_installed("pyvis"):
pm.install("pyvis")
import requests
from pyvis.network import Network
def fetch_graph(server_url: str, label: str = "*", max_nodes: int = 300) -> dict:
"""Fetch knowledge graph data from LightRAG Server API."""
url = f"{server_url}/graphs"
params = {"label": label, "max_nodes": max_nodes}
resp = requests.get(url, params=params, timeout=30)
resp.raise_for_status()
return resp.json()
def generate_html(graph_data: dict, output_file: str) -> str:
"""Generate an interactive HTML visualization from graph data."""
nodes = graph_data.get("nodes", [])
edges = graph_data.get("edges", [])
if not nodes:
print("No nodes found in the graph. Index some documents first.")
sys.exit(1)
print(f"Building visualization: {len(nodes)} nodes, {len(edges)} edges")
net = Network(height="100vh", notebook=False, cdn_resources="in_line")
# Add nodes with colors based on entity type
import hashlib
for node in nodes:
node_id = node.get("id", "")
props = node.get("properties", {})
entity_type = props.get("entity_type", "unknown")
description = props.get("description", "")
# Deterministic color from entity type
color_hash = int(hashlib.md5(entity_type.encode()).hexdigest()[:6], 16)
color = f"#{color_hash:06x}"
net.add_node(
node_id,
label=node_id,
title=f"[{entity_type}] {description[:200]}"
if description
else entity_type,
color=color,
)
# Add edges
for edge in edges:
source = edge.get("source", "")
target = edge.get("target", "")
props = edge.get("properties", {})
rel_type = edge.get("type", "")
description = props.get("description", "")
net.add_edge(
source,
target,
title=f"[{rel_type}] {description[:200]}" if description else rel_type,
label=rel_type,
)
net.save_graph(output_file)
print(f"Graph saved to {output_file}")
return output_file
def main():
parser = argparse.ArgumentParser(
description="Visualize LightRAG knowledge graph from OpenSearch"
)
parser.add_argument(
"--html",
action="store_true",
help="Generate standalone HTML file instead of opening WebUI",
)
parser.add_argument(
"--server",
default="http://localhost:9621",
help="LightRAG Server URL (default: http://localhost:9621)",
)
parser.add_argument(
"--output",
default="knowledge_graph_opensearch.html",
help="Output HTML file (default: knowledge_graph_opensearch.html)",
)
parser.add_argument(
"--label",
default="*",
help="Starting node label, or '*' for all nodes (default: *)",
)
parser.add_argument(
"--max-nodes",
type=int,
default=300,
help="Maximum nodes to fetch (default: 300)",
)
args = parser.parse_args()
# Verify server is running
try:
requests.get(f"{args.server}/health", timeout=5)
except requests.ConnectionError:
print(f"Error: Cannot connect to LightRAG Server at {args.server}")
print("Start the server first: lightrag-server --host 0.0.0.0 --port 9621")
sys.exit(1)
if args.html:
# Generate standalone HTML
graph_data = fetch_graph(args.server, args.label, args.max_nodes)
output = generate_html(graph_data, args.output)
webbrowser.open(f"file://{os.path.abspath(output)}")
else:
# Open WebUI graph explorer
url = f"{args.server}/#/graph"
print(f"Opening LightRAG WebUI graph explorer: {url}")
webbrowser.open(url)
if __name__ == "__main__":
main()