| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- """
- 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()
|