Daniel.y commited on
Commit
a209457
·
unverified ·
2 Parent(s): f3a4077 7936422

Merge pull request #1273 from danielaskdd/merge-edge-thickness

Browse files
README.md CHANGED
@@ -655,7 +655,7 @@ The `apipeline_enqueue_documents` and `apipeline_process_enqueue_documents` func
655
 
656
  This is useful for scenarios where you want to process documents in the background while still allowing the main thread to continue executing.
657
 
658
- And using a routine to process news documents.
659
 
660
  ```python
661
  rag = LightRAG(..)
 
655
 
656
  This is useful for scenarios where you want to process documents in the background while still allowing the main thread to continue executing.
657
 
658
+ And using a routine to process new documents.
659
 
660
  ```python
661
  rag = LightRAG(..)
lightrag/api/__init__.py CHANGED
@@ -1 +1 @@
1
- __api_version__ = "0133"
 
1
+ __api_version__ = "0135"
lightrag/api/webui/assets/{index-D4h_QQ3K.js → index-CaPD9lR_.js} RENAMED
Binary files a/lightrag/api/webui/assets/index-D4h_QQ3K.js and b/lightrag/api/webui/assets/index-CaPD9lR_.js differ
 
lightrag/api/webui/index.html CHANGED
Binary files a/lightrag/api/webui/index.html and b/lightrag/api/webui/index.html differ
 
lightrag_webui/src/components/graph/GraphControl.tsx CHANGED
@@ -36,6 +36,8 @@ const GraphControl = ({ disableHoverEffect }: { disableHoverEffect?: boolean })
36
  const enableEdgeEvents = useSettingsStore.use.enableEdgeEvents()
37
  const renderEdgeLabels = useSettingsStore.use.showEdgeLabel()
38
  const renderLabels = useSettingsStore.use.showNodeLabel()
 
 
39
  const selectedNode = useGraphStore.use.selectedNode()
40
  const focusedNode = useGraphStore.use.focusedNode()
41
  const selectedEdge = useGraphStore.use.selectedEdge()
@@ -136,6 +138,51 @@ const GraphControl = ({ disableHoverEffect }: { disableHoverEffect?: boolean })
136
  registerEvents(events)
137
  }, [registerEvents, enableEdgeEvents])
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  /**
140
  * When component mount or hovered node change
141
  * => Setting the sigma reducers
 
36
  const enableEdgeEvents = useSettingsStore.use.enableEdgeEvents()
37
  const renderEdgeLabels = useSettingsStore.use.showEdgeLabel()
38
  const renderLabels = useSettingsStore.use.showNodeLabel()
39
+ const minEdgeSize = useSettingsStore.use.minEdgeSize()
40
+ const maxEdgeSize = useSettingsStore.use.maxEdgeSize()
41
  const selectedNode = useGraphStore.use.selectedNode()
42
  const focusedNode = useGraphStore.use.focusedNode()
43
  const selectedEdge = useGraphStore.use.selectedEdge()
 
138
  registerEvents(events)
139
  }, [registerEvents, enableEdgeEvents])
140
 
141
+ /**
142
+ * When edge size settings change, recalculate edge sizes and refresh the sigma instance
143
+ * to ensure changes take effect immediately
144
+ */
145
+ useEffect(() => {
146
+ if (sigma && sigmaGraph) {
147
+ // Get the graph from sigma
148
+ const graph = sigma.getGraph()
149
+
150
+ // Find min and max weight values
151
+ let minWeight = Number.MAX_SAFE_INTEGER
152
+ let maxWeight = 0
153
+
154
+ graph.forEachEdge(edge => {
155
+ // Get original weight (before scaling)
156
+ const weight = graph.getEdgeAttribute(edge, 'originalWeight') || 1
157
+ if (typeof weight === 'number') {
158
+ minWeight = Math.min(minWeight, weight)
159
+ maxWeight = Math.max(maxWeight, weight)
160
+ }
161
+ })
162
+
163
+ // Scale edge sizes based on weight range and current min/max edge size settings
164
+ const weightRange = maxWeight - minWeight
165
+ if (weightRange > 0) {
166
+ const sizeScale = maxEdgeSize - minEdgeSize
167
+ graph.forEachEdge(edge => {
168
+ const weight = graph.getEdgeAttribute(edge, 'originalWeight') || 1
169
+ if (typeof weight === 'number') {
170
+ const scaledSize = minEdgeSize + sizeScale * Math.pow((weight - minWeight) / weightRange, 0.5)
171
+ graph.setEdgeAttribute(edge, 'size', scaledSize)
172
+ }
173
+ })
174
+ } else {
175
+ // If all weights are the same, use default size
176
+ graph.forEachEdge(edge => {
177
+ graph.setEdgeAttribute(edge, 'size', minEdgeSize)
178
+ })
179
+ }
180
+
181
+ // Refresh the sigma instance to apply changes
182
+ sigma.refresh()
183
+ }
184
+ }, [sigma, sigmaGraph, minEdgeSize, maxEdgeSize])
185
+
186
  /**
187
  * When component mount or hovered node change
188
  * => Setting the sigma reducers
lightrag_webui/src/components/graph/Settings.tsx CHANGED
@@ -144,6 +144,8 @@ export default function Settings() {
144
  const enableNodeDrag = useSettingsStore.use.enableNodeDrag()
145
  const enableHideUnselectedEdges = useSettingsStore.use.enableHideUnselectedEdges()
146
  const showEdgeLabel = useSettingsStore.use.showEdgeLabel()
 
 
147
  const graphQueryMaxDepth = useSettingsStore.use.graphQueryMaxDepth()
148
  const graphMaxNodes = useSettingsStore.use.graphMaxNodes()
149
  const graphLayoutMaxIterations = useSettingsStore.use.graphLayoutMaxIterations()
@@ -292,6 +294,53 @@ export default function Settings() {
292
  label={t('graphPanel.sideBar.settings.edgeEvents')}
293
  />
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  <Separator />
296
  <LabeledNumberInput
297
  label={t('graphPanel.sideBar.settings.maxQueryDepth')}
 
144
  const enableNodeDrag = useSettingsStore.use.enableNodeDrag()
145
  const enableHideUnselectedEdges = useSettingsStore.use.enableHideUnselectedEdges()
146
  const showEdgeLabel = useSettingsStore.use.showEdgeLabel()
147
+ const minEdgeSize = useSettingsStore.use.minEdgeSize()
148
+ const maxEdgeSize = useSettingsStore.use.maxEdgeSize()
149
  const graphQueryMaxDepth = useSettingsStore.use.graphQueryMaxDepth()
150
  const graphMaxNodes = useSettingsStore.use.graphMaxNodes()
151
  const graphLayoutMaxIterations = useSettingsStore.use.graphLayoutMaxIterations()
 
294
  label={t('graphPanel.sideBar.settings.edgeEvents')}
295
  />
296
 
297
+ <div className="flex flex-col gap-2">
298
+ <label className="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
299
+ {t('graphPanel.sideBar.settings.edgeSizeRange')}
300
+ </label>
301
+ <div className="flex items-center gap-2">
302
+ <Input
303
+ type="number"
304
+ value={minEdgeSize}
305
+ onChange={(e) => {
306
+ const newValue = Number(e.target.value);
307
+ if (!isNaN(newValue) && newValue >= 1 && newValue <= maxEdgeSize) {
308
+ useSettingsStore.setState({ minEdgeSize: newValue });
309
+ }
310
+ }}
311
+ className="h-6 w-16 min-w-0 pr-1"
312
+ min={1}
313
+ max={Math.min(maxEdgeSize, 10)}
314
+ />
315
+ <span>-</span>
316
+ <div className="flex items-center gap-1">
317
+ <Input
318
+ type="number"
319
+ value={maxEdgeSize}
320
+ onChange={(e) => {
321
+ const newValue = Number(e.target.value);
322
+ if (!isNaN(newValue) && newValue >= minEdgeSize && newValue >= 1 && newValue <= 10) {
323
+ useSettingsStore.setState({ maxEdgeSize: newValue });
324
+ }
325
+ }}
326
+ className="h-6 w-16 min-w-0 pr-1"
327
+ min={minEdgeSize}
328
+ max={10}
329
+ />
330
+ <Button
331
+ variant="ghost"
332
+ size="icon"
333
+ className="h-6 w-6 flex-shrink-0 hover:bg-muted text-muted-foreground hover:text-foreground"
334
+ onClick={() => useSettingsStore.setState({ minEdgeSize: 1, maxEdgeSize: 5 })}
335
+ type="button"
336
+ title={t('graphPanel.sideBar.settings.resetToDefault')}
337
+ >
338
+ <Undo2 className="h-3.5 w-3.5" />
339
+ </Button>
340
+ </div>
341
+ </div>
342
+ </div>
343
+
344
  <Separator />
345
  <LabeledNumberInput
346
  label={t('graphPanel.sideBar.settings.maxQueryDepth')}
lightrag_webui/src/hooks/useLightragGraph.tsx CHANGED
@@ -68,7 +68,13 @@ export type NodeType = {
68
  color: string
69
  highlighted?: boolean
70
  }
71
- export type EdgeType = { label: string }
 
 
 
 
 
 
72
 
73
  const fetchGraph = async (label: string, maxDepth: number, maxNodes: number) => {
74
  let rawData: any = null;
@@ -174,6 +180,9 @@ const fetchGraph = async (label: string, maxDepth: number, maxNodes: number) =>
174
 
175
  // Create a new graph instance with the raw graph data
176
  const createSigmaGraph = (rawGraph: RawGraph | null) => {
 
 
 
177
  // Skip graph creation if no data or empty nodes
178
  if (!rawGraph || !rawGraph.nodes.length) {
179
  console.log('No graph data available, skipping sigma graph creation');
@@ -204,8 +213,40 @@ const createSigmaGraph = (rawGraph: RawGraph | null) => {
204
 
205
  // Add edges from raw graph data
206
  for (const rawEdge of rawGraph?.edges ?? []) {
 
 
 
207
  rawEdge.dynamicId = graph.addDirectedEdge(rawEdge.source, rawEdge.target, {
208
- label: rawEdge.properties?.keywords || undefined
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  })
210
  }
211
 
 
68
  color: string
69
  highlighted?: boolean
70
  }
71
+ export type EdgeType = {
72
+ label: string
73
+ originalWeight?: number
74
+ size?: number
75
+ color?: string
76
+ hidden?: boolean
77
+ }
78
 
79
  const fetchGraph = async (label: string, maxDepth: number, maxNodes: number) => {
80
  let rawData: any = null;
 
180
 
181
  // Create a new graph instance with the raw graph data
182
  const createSigmaGraph = (rawGraph: RawGraph | null) => {
183
+ // Get edge size settings from store
184
+ const minEdgeSize = useSettingsStore.getState().minEdgeSize
185
+ const maxEdgeSize = useSettingsStore.getState().maxEdgeSize
186
  // Skip graph creation if no data or empty nodes
187
  if (!rawGraph || !rawGraph.nodes.length) {
188
  console.log('No graph data available, skipping sigma graph creation');
 
213
 
214
  // Add edges from raw graph data
215
  for (const rawEdge of rawGraph?.edges ?? []) {
216
+ // Get weight from edge properties or default to 1
217
+ const weight = rawEdge.properties?.weight !== undefined ? Number(rawEdge.properties.weight) : 1
218
+
219
  rawEdge.dynamicId = graph.addDirectedEdge(rawEdge.source, rawEdge.target, {
220
+ label: rawEdge.properties?.keywords || undefined,
221
+ size: weight, // Set initial size based on weight
222
+ originalWeight: weight, // Store original weight for recalculation
223
+ })
224
+ }
225
+
226
+ // Calculate edge size based on weight range, similar to node size calculation
227
+ let minWeight = Number.MAX_SAFE_INTEGER
228
+ let maxWeight = 0
229
+
230
+ // Find min and max weight values
231
+ graph.forEachEdge(edge => {
232
+ const weight = graph.getEdgeAttribute(edge, 'originalWeight') || 1
233
+ minWeight = Math.min(minWeight, weight)
234
+ maxWeight = Math.max(maxWeight, weight)
235
+ })
236
+
237
+ // Scale edge sizes based on weight range
238
+ const weightRange = maxWeight - minWeight
239
+ if (weightRange > 0) {
240
+ const sizeScale = maxEdgeSize - minEdgeSize
241
+ graph.forEachEdge(edge => {
242
+ const weight = graph.getEdgeAttribute(edge, 'originalWeight') || 1
243
+ const scaledSize = minEdgeSize + sizeScale * Math.pow((weight - minWeight) / weightRange, 0.5)
244
+ graph.setEdgeAttribute(edge, 'size', scaledSize)
245
+ })
246
+ } else {
247
+ // If all weights are the same, use default size
248
+ graph.forEachEdge(edge => {
249
+ graph.setEdgeAttribute(edge, 'size', minEdgeSize)
250
  })
251
  }
252
 
lightrag_webui/src/locales/ar.json CHANGED
@@ -157,6 +157,7 @@
157
  "maxNodes": "الحد الأقصى للعقد",
158
  "maxLayoutIterations": "أقصى تكرارات التخطيط",
159
  "resetToDefault": "إعادة التعيين إلى الافتراضي",
 
160
  "depth": "D",
161
  "max": "Max",
162
  "degree": "الدرجة",
 
157
  "maxNodes": "الحد الأقصى للعقد",
158
  "maxLayoutIterations": "أقصى تكرارات التخطيط",
159
  "resetToDefault": "إعادة التعيين إلى الافتراضي",
160
+ "edgeSizeRange": "نطاق حجم الحافة",
161
  "depth": "D",
162
  "max": "Max",
163
  "degree": "الدرجة",
lightrag_webui/src/locales/en.json CHANGED
@@ -157,6 +157,7 @@
157
  "maxNodes": "Max Nodes",
158
  "maxLayoutIterations": "Max Layout Iterations",
159
  "resetToDefault": "Reset to default",
 
160
  "depth": "D",
161
  "max": "Max",
162
  "degree": "Degree",
 
157
  "maxNodes": "Max Nodes",
158
  "maxLayoutIterations": "Max Layout Iterations",
159
  "resetToDefault": "Reset to default",
160
+ "edgeSizeRange": "Edge Size Range",
161
  "depth": "D",
162
  "max": "Max",
163
  "degree": "Degree",
lightrag_webui/src/locales/fr.json CHANGED
@@ -157,6 +157,7 @@
157
  "maxNodes": "Nombre maximum de nœuds",
158
  "maxLayoutIterations": "Itérations maximales de mise en page",
159
  "resetToDefault": "Réinitialiser par défaut",
 
160
  "depth": "D",
161
  "max": "Max",
162
  "degree": "Degré",
 
157
  "maxNodes": "Nombre maximum de nœuds",
158
  "maxLayoutIterations": "Itérations maximales de mise en page",
159
  "resetToDefault": "Réinitialiser par défaut",
160
+ "edgeSizeRange": "Plage de taille des arêtes",
161
  "depth": "D",
162
  "max": "Max",
163
  "degree": "Degré",
lightrag_webui/src/locales/zh.json CHANGED
@@ -157,6 +157,7 @@
157
  "maxNodes": "最大返回节点数",
158
  "maxLayoutIterations": "最大布局迭代次数",
159
  "resetToDefault": "重置为默认值",
 
160
  "depth": "深",
161
  "max": "Max",
162
  "degree": "邻边",
 
157
  "maxNodes": "最大返回节点数",
158
  "maxLayoutIterations": "最大布局迭代次数",
159
  "resetToDefault": "重置为默认值",
160
+ "edgeSizeRange": "边粗细范围",
161
  "depth": "深",
162
  "max": "Max",
163
  "degree": "邻边",
lightrag_webui/src/stores/settings.ts CHANGED
@@ -24,6 +24,12 @@ interface SettingsState {
24
  enableHideUnselectedEdges: boolean
25
  enableEdgeEvents: boolean
26
 
 
 
 
 
 
 
27
  graphQueryMaxDepth: number
28
  setGraphQueryMaxDepth: (depth: number) => void
29
 
@@ -76,6 +82,9 @@ const useSettingsStoreBase = create<SettingsState>()(
76
  enableHideUnselectedEdges: true,
77
  enableEdgeEvents: false,
78
 
 
 
 
79
  graphQueryMaxDepth: 3,
80
  graphMaxNodes: 1000,
81
  graphLayoutMaxIterations: 15,
@@ -132,6 +141,10 @@ const useSettingsStoreBase = create<SettingsState>()(
132
 
133
  setGraphMaxNodes: (nodes: number) => set({ graphMaxNodes: nodes }),
134
 
 
 
 
 
135
  setEnableHealthCheck: (enable: boolean) => set({ enableHealthCheck: enable }),
136
 
137
  setApiKey: (apiKey: string | null) => set({ apiKey }),
@@ -150,7 +163,7 @@ const useSettingsStoreBase = create<SettingsState>()(
150
  {
151
  name: 'settings-storage',
152
  storage: createJSONStorage(() => localStorage),
153
- version: 10,
154
  migrate: (state: any, version: number) => {
155
  if (version < 2) {
156
  state.showEdgeLabel = false
@@ -200,6 +213,10 @@ const useSettingsStoreBase = create<SettingsState>()(
200
  delete state.graphMinDegree // 删除废弃参数
201
  state.graphMaxNodes = 1000 // 添加新参数
202
  }
 
 
 
 
203
  return state
204
  }
205
  }
 
24
  enableHideUnselectedEdges: boolean
25
  enableEdgeEvents: boolean
26
 
27
+ minEdgeSize: number
28
+ setMinEdgeSize: (size: number) => void
29
+
30
+ maxEdgeSize: number
31
+ setMaxEdgeSize: (size: number) => void
32
+
33
  graphQueryMaxDepth: number
34
  setGraphQueryMaxDepth: (depth: number) => void
35
 
 
82
  enableHideUnselectedEdges: true,
83
  enableEdgeEvents: false,
84
 
85
+ minEdgeSize: 1,
86
+ maxEdgeSize: 1,
87
+
88
  graphQueryMaxDepth: 3,
89
  graphMaxNodes: 1000,
90
  graphLayoutMaxIterations: 15,
 
141
 
142
  setGraphMaxNodes: (nodes: number) => set({ graphMaxNodes: nodes }),
143
 
144
+ setMinEdgeSize: (size: number) => set({ minEdgeSize: size }),
145
+
146
+ setMaxEdgeSize: (size: number) => set({ maxEdgeSize: size }),
147
+
148
  setEnableHealthCheck: (enable: boolean) => set({ enableHealthCheck: enable }),
149
 
150
  setApiKey: (apiKey: string | null) => set({ apiKey }),
 
163
  {
164
  name: 'settings-storage',
165
  storage: createJSONStorage(() => localStorage),
166
+ version: 11,
167
  migrate: (state: any, version: number) => {
168
  if (version < 2) {
169
  state.showEdgeLabel = false
 
213
  delete state.graphMinDegree // 删除废弃参数
214
  state.graphMaxNodes = 1000 // 添加新参数
215
  }
216
+ if (version < 11) {
217
+ state.minEdgeSize = 1
218
+ state.maxEdgeSize = 1
219
+ }
220
  return state
221
  }
222
  }