yangdx commited on
Commit
5e539c5
Β·
2 Parent(s): 7cce235 c4f9db4

Merge branch 'main' into handle-stream-cancel-error

Browse files
README.md CHANGED
@@ -36,6 +36,7 @@ This repository hosts the code of LightRAG. The structure of this code is based
36
  </div>
37
 
38
  ## πŸŽ‰ News
 
39
  - [x] [2025.01.13]πŸŽ―πŸ“’Our team has released [MiniRAG](https://github.com/HKUDS/MiniRAG) making RAG simpler with small models.
40
  - [x] [2025.01.06]πŸŽ―πŸ“’You can now [use PostgreSQL for Storage](#using-postgresql-for-storage).
41
  - [x] [2024.12.31]πŸŽ―πŸ“’LightRAG now supports [deletion by document ID](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#delete).
@@ -1058,6 +1059,12 @@ LightRag can be installed with API support to serve a Fast api interface to perf
1058
 
1059
  The documentation can be found [here](lightrag/api/README.md)
1060
 
 
 
 
 
 
 
1061
  ## Star History
1062
 
1063
  <a href="https://star-history.com/#HKUDS/LightRAG&Date">
 
36
  </div>
37
 
38
  ## πŸŽ‰ News
39
+ - [x] [2025.02.05]πŸŽ―πŸ“’Our team has released [VideoRAG](https://github.com/HKUDS/VideoRAG) for processing and understanding extremely long-context videos.
40
  - [x] [2025.01.13]πŸŽ―πŸ“’Our team has released [MiniRAG](https://github.com/HKUDS/MiniRAG) making RAG simpler with small models.
41
  - [x] [2025.01.06]πŸŽ―πŸ“’You can now [use PostgreSQL for Storage](#using-postgresql-for-storage).
42
  - [x] [2024.12.31]πŸŽ―πŸ“’LightRAG now supports [deletion by document ID](https://github.com/HKUDS/LightRAG?tab=readme-ov-file#delete).
 
1059
 
1060
  The documentation can be found [here](lightrag/api/README.md)
1061
 
1062
+ ## Graph viewer
1063
+ LightRag can be installed with Tools support to add extra tools like the graphml 3d visualizer.
1064
+
1065
+ The documentation can be found [here](lightrag/tools/lightrag_visualizer/README.md)
1066
+
1067
+
1068
  ## Star History
1069
 
1070
  <a href="https://star-history.com/#HKUDS/LightRAG&Date">
{extra β†’ external_bindings}/OpenWebuiTool/openwebui_tool.py RENAMED
File without changes
lightrag/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
  from .lightrag import LightRAG as LightRAG, QueryParam as QueryParam
2
 
3
- __version__ = "1.1.4"
4
  __author__ = "Zirui Guo"
5
  __url__ = "https://github.com/HKUDS/LightRAG"
 
1
  from .lightrag import LightRAG as LightRAG, QueryParam as QueryParam
2
 
3
+ __version__ = "1.1.5"
4
  __author__ = "Zirui Guo"
5
  __url__ = "https://github.com/HKUDS/LightRAG"
lightrag/api/__init__.py CHANGED
@@ -1 +1 @@
1
- __api_version__ = "1.0.3"
 
1
+ __api_version__ = "1.0.4"
lightrag/api/lightrag_server.py CHANGED
@@ -557,7 +557,14 @@ class DocumentManager:
557
  def __init__(
558
  self,
559
  input_dir: str,
560
- supported_extensions: tuple = (".txt", ".md", ".pdf", ".docx", ".pptx", "xlsx"),
 
 
 
 
 
 
 
561
  ):
562
  self.input_dir = Path(input_dir)
563
  self.supported_extensions = supported_extensions
 
557
  def __init__(
558
  self,
559
  input_dir: str,
560
+ supported_extensions: tuple = (
561
+ ".txt",
562
+ ".md",
563
+ ".pdf",
564
+ ".docx",
565
+ ".pptx",
566
+ ".xlsx",
567
+ ),
568
  ):
569
  self.input_dir = Path(input_dir)
570
  self.supported_extensions = supported_extensions
lightrag/kg/mongo_impl.py CHANGED
@@ -2,11 +2,14 @@ import os
2
  from tqdm.asyncio import tqdm as tqdm_async
3
  from dataclasses import dataclass
4
  import pipmaster as pm
5
- import np
6
 
7
  if not pm.is_installed("pymongo"):
8
  pm.install("pymongo")
9
 
 
 
 
10
  from pymongo import MongoClient
11
  from motor.motor_asyncio import AsyncIOMotorClient
12
  from typing import Union, List, Tuple
 
2
  from tqdm.asyncio import tqdm as tqdm_async
3
  from dataclasses import dataclass
4
  import pipmaster as pm
5
+ import numpy as np
6
 
7
  if not pm.is_installed("pymongo"):
8
  pm.install("pymongo")
9
 
10
+ if not pm.is_installed("motor"):
11
+ pm.install("motor")
12
+
13
  from pymongo import MongoClient
14
  from motor.motor_asyncio import AsyncIOMotorClient
15
  from typing import Union, List, Tuple
lightrag/kg/postgres_impl.py CHANGED
@@ -447,7 +447,7 @@ class PGDocStatusStorage(DocStatusStorage):
447
  sql = "select * from LIGHTRAG_DOC_STATUS where workspace=$1 and id=$2"
448
  params = {"workspace": self.db.workspace, "id": id}
449
  result = await self.db.query(sql, params, True)
450
- if result is None:
451
  return None
452
  else:
453
  return DocProcessingStatus(
 
447
  sql = "select * from LIGHTRAG_DOC_STATUS where workspace=$1 and id=$2"
448
  params = {"workspace": self.db.workspace, "id": id}
449
  result = await self.db.query(sql, params, True)
450
+ if result is None or result == []:
451
  return None
452
  else:
453
  return DocProcessingStatus(
lightrag/lightrag.py CHANGED
@@ -372,12 +372,23 @@ class LightRAG:
372
 
373
  # 3. Filter out already processed documents
374
  # _add_doc_keys = await self.doc_status.filter_keys(list(new_docs.keys()))
375
- _add_doc_keys = {
376
- doc_id
377
- for doc_id in new_docs.keys()
378
- if (current_doc := await self.doc_status.get_by_id(doc_id)) is None
379
- or current_doc.status == DocStatus.FAILED
380
- }
 
 
 
 
 
 
 
 
 
 
 
381
  new_docs = {k: v for k, v in new_docs.items() if k in _add_doc_keys}
382
 
383
  if not new_docs:
 
372
 
373
  # 3. Filter out already processed documents
374
  # _add_doc_keys = await self.doc_status.filter_keys(list(new_docs.keys()))
375
+ _add_doc_keys = set()
376
+ for doc_id in new_docs.keys():
377
+ current_doc = await self.doc_status.get_by_id(doc_id)
378
+
379
+ if current_doc is None:
380
+ _add_doc_keys.add(doc_id)
381
+ continue # skip to the next doc_id
382
+
383
+ status = None
384
+ if isinstance(current_doc, dict):
385
+ status = current_doc["status"]
386
+ else:
387
+ status = current_doc.status
388
+
389
+ if status == DocStatus.FAILED:
390
+ _add_doc_keys.add(doc_id)
391
+
392
  new_docs = {k: v for k, v in new_docs.items() if k in _add_doc_keys}
393
 
394
  if not new_docs:
extra/VisualizationTool/assets/place_font_here β†’ lightrag/tools/__init__.py RENAMED
File without changes
{extra/VisualizationTool β†’ lightrag/tools/lightrag_visualizer}/README-zh.md RENAMED
@@ -38,8 +38,8 @@
38
 
39
  1. **ε―εŠ¨η¨‹εΊ**:
40
  ```bash
41
- python -m pip install -r requirements.txt
42
- python graph_visualizer.py
43
  ```
44
 
45
  2. **εŠ θ½½ε­—δ½“**:
 
38
 
39
  1. **ε―εŠ¨η¨‹εΊ**:
40
  ```bash
41
+ pip install lightrag-hku[tools]
42
+ lightrag-viewer
43
  ```
44
 
45
  2. **εŠ θ½½ε­—δ½“**:
{extra/VisualizationTool β†’ lightrag/tools/lightrag_visualizer}/README.md RENAMED
@@ -1,6 +1,22 @@
1
- # 3D GraphML Viewer
2
 
3
- An interactive 3D graph visualization tool based on Dear ImGui and ModernGL.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  ## Features
6
 
@@ -27,44 +43,32 @@ An interactive 3D graph visualization tool based on Dear ImGui and ModernGL.
27
  - **NumPy**: Numerical computations
28
  - **community**: Community detection
29
 
30
- ## Usage
31
 
32
- 1. **Launch the Program**:
33
- ```bash
34
- python -m pip install -r requirements.txt
35
- python graph_visualizer.py
36
- ```
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- 2. **Load Font**:
39
- - Place the font file `font.ttf` in the `assets` directory
40
- - Or modify the `CUSTOM_FONT` constant to use a different font file
41
-
42
- 3. **Load Graph File**:
43
- - Click the "Load GraphML" button in the interface
44
- - Select a graph file in GraphML format
45
-
46
- 4. **Interactive Controls**:
47
- - **Camera Movement**:
48
- - W: Move forward
49
- - S: Move backward
50
- - A: Move left
51
- - D: Move right
52
- - Q: Move up
53
- - E: Move down
54
- - **View Control**:
55
- - Hold right mouse button and drag to rotate view
56
- - **Node Interaction**:
57
- - Hover mouse to highlight nodes
58
- - Click to select nodes
59
-
60
- 5. **Visualization Settings**:
61
- - Adjustable via UI control panel:
62
- - Layout type
63
- - Node size
64
- - Edge width
65
- - Label visibility
66
- - Label size
67
- - Background color
68
 
69
  ## Customization Options
70
 
@@ -75,14 +79,58 @@ An interactive 3D graph visualization tool based on Dear ImGui and ModernGL.
75
  - **Label Color**: Set label color through `label_color`
76
  - **View Distance**: Control maximum label display distance with `label_culling_distance`
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  ## Performance Optimizations
79
 
80
  - Efficient graphics rendering using ModernGL
81
  - View distance culling for label display optimization
82
  - Community detection algorithms for optimized visualization of large-scale graphs
83
 
84
- ## System Requirements
85
 
86
- - Python 3.10+
87
- - Graphics card with OpenGL 3.3+ support
88
- - Supported Operating Systems: Windows/Linux/MacOS
 
 
 
 
 
 
1
+ # LightRAG 3D Graph Viewer
2
 
3
+ An interactive 3D graph visualization tool included in the LightRAG package for visualizing and analyzing RAG (Retrieval-Augmented Generation) graphs and other graph structures.
4
+
5
+ ![image](https://github.com/user-attachments/assets/b0d86184-99fc-468c-96ed-c611f14292bf)
6
+
7
+ ## Installation
8
+
9
+ ### Quick Install
10
+ ```bash
11
+ pip install lightrag-hku[tools] # Install with visualization tool only
12
+ # or
13
+ pip install lightrag-hku[api,tools] # Install with both API and visualization tools
14
+ ```
15
+
16
+ ## Launch the Viewer
17
+ ```bash
18
+ lightrag-viewer
19
+ ```
20
 
21
  ## Features
22
 
 
43
  - **NumPy**: Numerical computations
44
  - **community**: Community detection
45
 
46
+ ## Interactive Controls
47
 
48
+ ### Camera Movement
49
+ - W: Move forward
50
+ - S: Move backward
51
+ - A: Move left
52
+ - D: Move right
53
+ - Q: Move up
54
+ - E: Move down
55
+
56
+ ### View Control
57
+ - Hold right mouse button and drag to rotate view
58
+
59
+ ### Node Interaction
60
+ - Hover mouse to highlight nodes
61
+ - Click to select nodes
62
+
63
+ ## Visualization Settings
64
 
65
+ Adjustable via UI control panel:
66
+ - Layout type
67
+ - Node size
68
+ - Edge width
69
+ - Label visibility
70
+ - Label size
71
+ - Background color
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  ## Customization Options
74
 
 
79
  - **Label Color**: Set label color through `label_color`
80
  - **View Distance**: Control maximum label display distance with `label_culling_distance`
81
 
82
+ ## System Requirements
83
+
84
+ - Python 3.9+
85
+ - Graphics card with OpenGL 3.3+ support
86
+ - Supported Operating Systems: Windows/Linux/MacOS
87
+
88
+ ## Troubleshooting
89
+
90
+ ### Common Issues
91
+
92
+ 1. **Command Not Found**
93
+ ```bash
94
+ # Make sure you installed with the 'tools' option
95
+ pip install lightrag-hku[tools]
96
+
97
+ # Verify installation
98
+ pip list | grep lightrag-hku
99
+ ```
100
+
101
+ 2. **ModernGL Initialization Failed**
102
+ ```bash
103
+ # Check OpenGL version
104
+ glxinfo | grep "OpenGL version"
105
+
106
+ # Update graphics drivers if needed
107
+ ```
108
+
109
+ 3. **Font Loading Issues**
110
+ - The required fonts are included in the package
111
+ - If issues persist, check your graphics drivers
112
+
113
+ ## Usage with LightRAG
114
+
115
+ The viewer is particularly useful for:
116
+ - Visualizing RAG knowledge graphs
117
+ - Analyzing document relationships
118
+ - Exploring semantic connections
119
+ - Debugging retrieval patterns
120
+
121
  ## Performance Optimizations
122
 
123
  - Efficient graphics rendering using ModernGL
124
  - View distance culling for label display optimization
125
  - Community detection algorithms for optimized visualization of large-scale graphs
126
 
127
+ ## Support
128
 
129
+ - GitHub Issues: [LightRAG Repository](https://github.com/HKUDS/LightRAG)
130
+ - Documentation: [LightRAG Docs](https://URL-to-docs)
131
+
132
+ ## License
133
+
134
+ This tool is part of LightRAG and is distributed under the MIT License. See `LICENSE` for more information.
135
+
136
+ Note: This visualization tool is an optional component of the LightRAG package. Install with the [tools] option to access the viewer functionality.
lightrag/tools/lightrag_visualizer/__init__.py ADDED
File without changes
lightrag/tools/lightrag_visualizer/assets/Geist-Regular.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1462ccd6f9b8ddf05af952cd66789ac74f29727f0177584163fcd8b177462e5c
3
+ size 111644
lightrag/tools/lightrag_visualizer/assets/LICENSE - Geist.txt ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2023 Vercel, in collaboration with basement.studio
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+ -----------------------------------------------------------
8
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
9
+ -----------------------------------------------------------
10
+
11
+ PREAMBLE
12
+ The goals of the Open Font License (OFL) are to stimulate worldwide
13
+ development of collaborative font projects, to support the font creation
14
+ efforts of academic and linguistic communities, and to provide a free and
15
+ open framework in which fonts may be shared and improved in partnership
16
+ with others.
17
+
18
+ The OFL allows the licensed fonts to be used, studied, modified and
19
+ redistributed freely as long as they are not sold by themselves. The
20
+ fonts, including any derivative works, can be bundled, embedded,
21
+ redistributed and/or sold with any software provided that any reserved
22
+ names are not used by derivative works. The fonts and derivatives,
23
+ however, cannot be released under any other type of license. The
24
+ requirement for fonts to remain under this license does not apply
25
+ to any document created using the fonts or their derivatives.
26
+
27
+ DEFINITIONS
28
+ "Font Software" refers to the set of files released by the Copyright
29
+ Holder(s) under this license and clearly marked as such. This may
30
+ include source files, build scripts and documentation.
31
+
32
+ "Reserved Font Name" refers to any names specified as such after the
33
+ copyright statement(s).
34
+
35
+ "Original Version" refers to the collection of Font Software components as
36
+ distributed by the Copyright Holder(s).
37
+
38
+ "Modified Version" refers to any derivative made by adding to, deleting,
39
+ or substituting -- in part or in whole -- any of the components of the
40
+ Original Version, by changing formats or by porting the Font Software to a
41
+ new environment.
42
+
43
+ "Author" refers to any designer, engineer, programmer, technical
44
+ writer or other person who contributed to the Font Software.
45
+
46
+ PERMISSION AND CONDITIONS
47
+ Permission is hereby granted, free of charge, to any person obtaining
48
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
49
+ redistribute, and sell modified and unmodified copies of the Font
50
+ Software, subject to the following conditions:
51
+
52
+ 1) Neither the Font Software nor any of its individual components,
53
+ in Original or Modified Versions, may be sold by itself.
54
+
55
+ 2) Original or Modified Versions of the Font Software may be bundled,
56
+ redistributed and/or sold with any software, provided that each copy
57
+ contains the above copyright notice and this license. These can be
58
+ included either as stand-alone text files, human-readable headers or
59
+ in the appropriate machine-readable metadata fields within text or
60
+ binary files as long as those fields can be easily viewed by the user.
61
+
62
+ 3) No Modified Version of the Font Software may use the Reserved Font
63
+ Name(s) unless explicit written permission is granted by the corresponding
64
+ Copyright Holder. This restriction only applies to the primary font name as
65
+ presented to the users.
66
+
67
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
68
+ Software shall not be used to promote, endorse or advertise any
69
+ Modified Version, except to acknowledge the contribution(s) of the
70
+ Copyright Holder(s) and the Author(s) or with their explicit written
71
+ permission.
72
+
73
+ 5) The Font Software, modified or unmodified, in part or in whole,
74
+ must be distributed entirely under this license, and must not be
75
+ distributed under any other license. The requirement for fonts to
76
+ remain under this license does not apply to any document created
77
+ using the Font Software.
78
+
79
+ TERMINATION
80
+ This license becomes null and void if any of the above conditions are
81
+ not met.
82
+
83
+ DISCLAIMER
84
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
85
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
86
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
87
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
88
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
89
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
90
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
91
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
92
+ OTHER DEALINGS IN THE FONT SOFTWARE.
lightrag/tools/lightrag_visualizer/assets/LICENSE - SmileySans.txt ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2022--2024, atelierAnchor <https://atelier-anchor.com>,
2
+ with Reserved Font Name <Smiley> and <得意黑>.
3
+
4
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
5
+ This license is copied below, and is also available with a FAQ at:
6
+ http://scripts.sil.org/OFL
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
lightrag/tools/lightrag_visualizer/assets/SmileySans-Oblique.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b447d7e781f08bc95c4c9f23ba71ed2b8ebb639aa7184485c71c4ca5afcd25c4
3
+ size 2629764
lightrag/tools/lightrag_visualizer/assets/place_font_here ADDED
File without changes
{extra/VisualizationTool β†’ lightrag/tools/lightrag_visualizer}/graph_visualizer.py RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  3D GraphML Viewer using Dear ImGui and ModernGL
3
- Author: LoLLMs, ArnoChen
4
  Description: An interactive 3D GraphML viewer using imgui_bundle and ModernGL
5
  Version: 2.0
6
  """
@@ -8,6 +8,18 @@ Version: 2.0
8
  from typing import Optional, Tuple, Dict, List
9
  import numpy as np
10
  import networkx as nx
 
 
 
 
 
 
 
 
 
 
 
 
11
  import moderngl
12
  from imgui_bundle import imgui, immapp, hello_imgui
13
  import community
@@ -20,6 +32,9 @@ import os
20
 
21
  CUSTOM_FONT = "font.ttf"
22
 
 
 
 
23
 
24
  class Node3D:
25
  """Class representing a 3D node in the graph"""
@@ -172,6 +187,10 @@ class GraphViewer:
172
  np.sin(np.radians(self.pitch)),
173
  )
174
  )
 
 
 
 
175
  if io.mouse_wheel != 0:
176
  self.move_speed += io.mouse_wheel * 0.05
177
  self.move_speed = np.max([self.move_speed, 0.01])
@@ -502,6 +521,14 @@ class GraphViewer:
502
  def load_file(self, filepath: str):
503
  """Load a GraphML file with error handling"""
504
  try:
 
 
 
 
 
 
 
 
505
  self.graph = nx.read_graphml(filepath)
506
  self.calculate_layout()
507
  self.update_buffers()
@@ -672,10 +699,6 @@ class GraphViewer:
672
  self.position, self.position + self.front, self.up
673
  )
674
 
675
- io = imgui.get_io()
676
- self.window_width = int(io.display_size.x)
677
- self.window_height = int(io.display_size.y)
678
-
679
  aspect_ratio = self.window_width / self.window_height
680
  self.proj_matrix = glm.perspective(
681
  glm.radians(60.0), # FOV
@@ -839,7 +862,7 @@ class GraphViewer:
839
  def render(self):
840
  """Render the graph"""
841
  # Clear screen
842
- self.glctx.clear(*self.background_color)
843
 
844
  if not self.graph:
845
  return
@@ -886,11 +909,15 @@ class GraphViewer:
886
  # Render id map
887
  self.render_id_map(mvp)
888
 
 
889
  # Render labels if enabled
890
- if self.show_labels:
891
  # Save current font scale
892
  original_scale = imgui.get_font_size()
893
 
 
 
 
894
  for node in self.nodes:
895
  # Project node position to screen space
896
  pos = mvp * glm.vec4(
@@ -1013,13 +1040,39 @@ def create_sphere(sectors: int = 32, rings: int = 16) -> Tuple:
1013
  return (vbo_vertices, vbo_elements)
1014
 
1015
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1016
  def main():
1017
  """Main application entry point"""
1018
  viewer = GraphViewer()
1019
 
 
 
 
1020
  def gui():
1021
  if not viewer.initialized:
1022
  viewer.setup()
 
 
 
 
 
 
 
1023
 
1024
  # Handle keyboard and mouse input
1025
  viewer.handle_keyboard_input()
@@ -1089,11 +1142,34 @@ def main():
1089
  # Render graph settings window
1090
  viewer.render_settings()
1091
 
1092
- window_bg_color.w = 0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1093
  style.set_color_(imgui.Col_.window_bg.value, window_bg_color)
1094
 
1095
- # Render the graph
1096
- viewer.render()
 
 
 
 
1097
 
1098
  runner_params = hello_imgui.RunnerParams()
1099
  runner_params.app_window_params.window_geometry.size = (
@@ -1102,47 +1178,48 @@ def main():
1102
  )
1103
  runner_params.app_window_params.window_title = "3D GraphML Viewer"
1104
  runner_params.callbacks.show_gui = gui
1105
- addons = immapp.AddOnsParams()
1106
- addons.with_markdown = True
1107
 
1108
  def load_font():
1109
- io = imgui.get_io()
1110
- io.fonts.add_font_default()
1111
-
1112
- # Load font for Chinese character support
1113
  # You will need to provide it yourself, or use another font.
1114
  font_filename = CUSTOM_FONT
1115
 
1116
- if not os.path.exists("assets/" + font_filename):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1117
  return
1118
 
1119
- # Get the full Chinese character range for ImGui
1120
- # This includes all Chinese characters supported by ImGui
1121
- cn_glyph_ranges_imgui = imgui.get_io().fonts.get_glyph_ranges_chinese_full()
1122
-
1123
- # Set up font loading parameters with Chinese character support
1124
- font_loading_params = hello_imgui.FontLoadingParams()
1125
- font_loading_params.glyph_ranges = hello_imgui.translate_common_glyph_ranges(
1126
- cn_glyph_ranges_imgui
1127
  )
1128
- custom_font = hello_imgui.load_font(font_filename, 16.0, font_loading_params)
1129
-
1130
- # # Merge with default font
1131
- # font_config = imgui.ImFontConfig()
1132
- # font_config.merge_mode = True
1133
- # custom_font = io.fonts.add_font_from_file_ttf(
1134
- # filename= "assets/" + font_filename,
1135
- # size_pixels=16.0,
1136
- # font_cfg=font_config,
1137
- # glyph_ranges_as_int_list=cn_glyph_ranges_imgui,
1138
- # )
1139
 
1140
- io.fonts.tex_desired_width = 4096 # Larger texture for better CJK font quality
1141
- io.font_default = custom_font
 
 
 
 
 
 
 
1142
 
1143
  runner_params.callbacks.load_additional_fonts = load_font
1144
 
1145
- immapp.run(runner_params, addons)
1146
 
1147
 
1148
  if __name__ == "__main__":
 
1
  """
2
  3D GraphML Viewer using Dear ImGui and ModernGL
3
+ Author: ParisNeo, ArnoChen
4
  Description: An interactive 3D GraphML viewer using imgui_bundle and ModernGL
5
  Version: 2.0
6
  """
 
8
  from typing import Optional, Tuple, Dict, List
9
  import numpy as np
10
  import networkx as nx
11
+ import pipmaster as pm
12
+
13
+ # Added automatic libraries install using pipmaster
14
+ if not pm.is_installed("moderngl"):
15
+ pm.install("moderngl")
16
+ if not pm.is_installed("imgui_bundle"):
17
+ pm.install("imgui_bundle")
18
+ if not pm.is_installed("pyglm"):
19
+ pm.install("pyglm")
20
+ if not pm.is_installed("python-louvain"):
21
+ pm.install("python-louvain")
22
+
23
  import moderngl
24
  from imgui_bundle import imgui, immapp, hello_imgui
25
  import community
 
32
 
33
  CUSTOM_FONT = "font.ttf"
34
 
35
+ DEFAULT_FONT_ENG = "Geist-Regular.ttf"
36
+ DEFAULT_FONT_CHI = "SmileySans-Oblique.ttf"
37
+
38
 
39
  class Node3D:
40
  """Class representing a 3D node in the graph"""
 
187
  np.sin(np.radians(self.pitch)),
188
  )
189
  )
190
+
191
+ if not imgui.is_window_hovered():
192
+ return
193
+
194
  if io.mouse_wheel != 0:
195
  self.move_speed += io.mouse_wheel * 0.05
196
  self.move_speed = np.max([self.move_speed, 0.01])
 
521
  def load_file(self, filepath: str):
522
  """Load a GraphML file with error handling"""
523
  try:
524
+ # Clear existing data
525
+ self.id_node_map.clear()
526
+ self.nodes.clear()
527
+ self.selected_node = None
528
+ self.highlighted_node = None
529
+ self.setup_buffers()
530
+
531
+ # Load new graph
532
  self.graph = nx.read_graphml(filepath)
533
  self.calculate_layout()
534
  self.update_buffers()
 
699
  self.position, self.position + self.front, self.up
700
  )
701
 
 
 
 
 
702
  aspect_ratio = self.window_width / self.window_height
703
  self.proj_matrix = glm.perspective(
704
  glm.radians(60.0), # FOV
 
862
  def render(self):
863
  """Render the graph"""
864
  # Clear screen
865
+ self.glctx.clear(*self.background_color, depth=1)
866
 
867
  if not self.graph:
868
  return
 
909
  # Render id map
910
  self.render_id_map(mvp)
911
 
912
+ def render_labels(self):
913
  # Render labels if enabled
914
+ if self.show_labels and self.nodes:
915
  # Save current font scale
916
  original_scale = imgui.get_font_size()
917
 
918
+ self.update_view_proj_matrix()
919
+ mvp = self.proj_matrix * self.view_matrix
920
+
921
  for node in self.nodes:
922
  # Project node position to screen space
923
  pos = mvp * glm.vec4(
 
1040
  return (vbo_vertices, vbo_elements)
1041
 
1042
 
1043
+ def draw_text_with_bg(
1044
+ text: str,
1045
+ text_pos: imgui.ImVec2Like,
1046
+ text_size: imgui.ImVec2Like,
1047
+ bg_color: int,
1048
+ ):
1049
+ imgui.get_window_draw_list().add_rect_filled(
1050
+ (text_pos[0] - 5, text_pos[1] - 5),
1051
+ (text_pos[0] + text_size[0] + 5, text_pos[1] + text_size[1] + 5),
1052
+ bg_color,
1053
+ 3.0,
1054
+ )
1055
+ imgui.set_cursor_pos(text_pos)
1056
+ imgui.text(text)
1057
+
1058
+
1059
  def main():
1060
  """Main application entry point"""
1061
  viewer = GraphViewer()
1062
 
1063
+ show_fps = True
1064
+ text_bg_color = imgui.IM_COL32(0, 0, 0, 100)
1065
+
1066
  def gui():
1067
  if not viewer.initialized:
1068
  viewer.setup()
1069
+ # # Change the theme
1070
+ # tweaked_theme = hello_imgui.get_runner_params().imgui_window_params.tweaked_theme
1071
+ # tweaked_theme.theme = hello_imgui.ImGuiTheme_.darcula_darker
1072
+ # hello_imgui.apply_tweaked_theme(tweaked_theme)
1073
+
1074
+ viewer.window_width = int(imgui.get_window_width())
1075
+ viewer.window_height = int(imgui.get_window_height())
1076
 
1077
  # Handle keyboard and mouse input
1078
  viewer.handle_keyboard_input()
 
1142
  # Render graph settings window
1143
  viewer.render_settings()
1144
 
1145
+ # Render FPS
1146
+ if show_fps:
1147
+ imgui.set_window_font_scale(1)
1148
+ fps_text = f"FPS: {hello_imgui.frame_rate():.1f}"
1149
+ text_size = imgui.calc_text_size(fps_text)
1150
+ cursor_pos = (10, viewer.window_height - text_size.y - 10)
1151
+ draw_text_with_bg(fps_text, cursor_pos, text_size, text_bg_color)
1152
+
1153
+ # Render highlighted node ID
1154
+ if viewer.highlighted_node:
1155
+ imgui.set_window_font_scale(1)
1156
+ node_text = f"Node ID: {viewer.highlighted_node.label}"
1157
+ text_size = imgui.calc_text_size(node_text)
1158
+ cursor_pos = (
1159
+ viewer.window_width - text_size.x - 10,
1160
+ viewer.window_height - text_size.y - 10,
1161
+ )
1162
+ draw_text_with_bg(node_text, cursor_pos, text_size, text_bg_color)
1163
+
1164
+ window_bg_color.w = 0
1165
  style.set_color_(imgui.Col_.window_bg.value, window_bg_color)
1166
 
1167
+ # Render labels
1168
+ viewer.render_labels()
1169
+
1170
+ def custom_background():
1171
+ if viewer.initialized:
1172
+ viewer.render()
1173
 
1174
  runner_params = hello_imgui.RunnerParams()
1175
  runner_params.app_window_params.window_geometry.size = (
 
1178
  )
1179
  runner_params.app_window_params.window_title = "3D GraphML Viewer"
1180
  runner_params.callbacks.show_gui = gui
1181
+ runner_params.callbacks.custom_background = custom_background
 
1182
 
1183
  def load_font():
 
 
 
 
1184
  # You will need to provide it yourself, or use another font.
1185
  font_filename = CUSTOM_FONT
1186
 
1187
+ io = imgui.get_io()
1188
+ io.fonts.tex_desired_width = 4096 # Larger texture for better CJK font quality
1189
+ font_size_pixels = 14
1190
+ asset_dir = os.path.join(os.path.dirname(__file__), "assets")
1191
+
1192
+ # Try to load custom font
1193
+ if not os.path.isfile(font_filename):
1194
+ font_filename = os.path.join(asset_dir, font_filename)
1195
+ if os.path.isfile(font_filename):
1196
+ custom_font = io.fonts.add_font_from_file_ttf(
1197
+ filename=font_filename,
1198
+ size_pixels=font_size_pixels,
1199
+ glyph_ranges_as_int_list=io.fonts.get_glyph_ranges_chinese_full(),
1200
+ )
1201
+ io.font_default = custom_font
1202
  return
1203
 
1204
+ # Load default fonts
1205
+ io.fonts.add_font_from_file_ttf(
1206
+ filename=os.path.join(asset_dir, DEFAULT_FONT_ENG),
1207
+ size_pixels=font_size_pixels,
 
 
 
 
1208
  )
 
 
 
 
 
 
 
 
 
 
 
1209
 
1210
+ font_config = imgui.ImFontConfig()
1211
+ font_config.merge_mode = True
1212
+
1213
+ io.font_default = io.fonts.add_font_from_file_ttf(
1214
+ filename=os.path.join(asset_dir, DEFAULT_FONT_CHI),
1215
+ size_pixels=font_size_pixels,
1216
+ font_cfg=font_config,
1217
+ glyph_ranges_as_int_list=io.fonts.get_glyph_ranges_chinese_full(),
1218
+ )
1219
 
1220
  runner_params.callbacks.load_additional_fonts = load_font
1221
 
1222
+ immapp.run(runner_params)
1223
 
1224
 
1225
  if __name__ == "__main__":
{extra/VisualizationTool β†’ lightrag/tools/lightrag_visualizer}/requirements.txt RENAMED
File without changes
setup.py CHANGED
@@ -62,6 +62,16 @@ def read_api_requirements():
62
  return api_deps
63
 
64
 
 
 
 
 
 
 
 
 
 
 
65
  metadata = retrieve_metadata()
66
  long_description = read_long_description()
67
  requirements = read_requirements()
@@ -97,10 +107,12 @@ setuptools.setup(
97
  },
98
  extras_require={
99
  "api": read_api_requirements(), # API requirements as optional
 
100
  },
101
  entry_points={
102
  "console_scripts": [
103
  "lightrag-server=lightrag.api.lightrag_server:main [api]",
 
104
  ],
105
  },
106
  )
 
62
  return api_deps
63
 
64
 
65
+ def read_extra_requirements():
66
+ api_deps = []
67
+ try:
68
+ with open("./lightrag/tools/lightrag_visualizer/requirements.txt") as f:
69
+ api_deps = [line.strip() for line in f if line.strip()]
70
+ except FileNotFoundError:
71
+ print("Warning: API requirements.txt not found.")
72
+ return api_deps
73
+
74
+
75
  metadata = retrieve_metadata()
76
  long_description = read_long_description()
77
  requirements = read_requirements()
 
107
  },
108
  extras_require={
109
  "api": read_api_requirements(), # API requirements as optional
110
+ "tools": read_extra_requirements(), # API requirements as optional
111
  },
112
  entry_points={
113
  "console_scripts": [
114
  "lightrag-server=lightrag.api.lightrag_server:main [api]",
115
+ "lightrag-viewer=lightrag.tools.lightrag_visualizer.graph_visualizer:main [tools]",
116
  ],
117
  },
118
  )