| """ |
| 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") |
|
|
| |
| 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", "") |
|
|
| |
| 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, |
| ) |
|
|
| |
| 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() |
|
|
| |
| 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: |
| |
| 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: |
| |
| url = f"{args.server}/#/graph" |
| print(f"Opening LightRAG WebUI graph explorer: {url}") |
| webbrowser.open(url) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|