Daniel.y commited on
Commit
523308c
·
unverified ·
2 Parent(s): ff39dc4 4b8c31d

Merge pull request #1156 from danielaskdd/main

Browse files

Improve node size calculation logic for node expansion to prevent oversize

lightrag/api/webui/assets/index-BcBS1RaQ.css DELETED
Binary file (53 kB)
 
lightrag/api/webui/assets/index-Cq65VeVX.css ADDED
Binary file (53.1 kB). View file
 
lightrag/api/webui/assets/{index-DpQ0dh7t.js → index-DPOdOU_f.js} RENAMED
Binary files a/lightrag/api/webui/assets/index-DpQ0dh7t.js and b/lightrag/api/webui/assets/index-DPOdOU_f.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/LayoutsControl.tsx CHANGED
@@ -218,8 +218,8 @@ const LayoutsControl = () => {
218
  maxIterations: maxIterations,
219
  settings: {
220
  attraction: 0.0003, // Lower attraction force to reduce oscillation
221
- repulsion: 0.05, // Lower repulsion force to reduce oscillation
222
- gravity: 0.01, // Increase gravity to make nodes converge to center faster
223
  inertia: 0.4, // Lower inertia to add damping effect
224
  maxMove: 100 // Limit maximum movement per step to prevent large jumps
225
  }
 
218
  maxIterations: maxIterations,
219
  settings: {
220
  attraction: 0.0003, // Lower attraction force to reduce oscillation
221
+ repulsion: 0.02, // Lower repulsion force to reduce oscillation
222
+ gravity: 0.02, // Increase gravity to make nodes converge to center faster
223
  inertia: 0.4, // Lower inertia to add damping effect
224
  maxMove: 100 // Limit maximum movement per step to prevent large jumps
225
  }
lightrag_webui/src/hooks/useLightragGraph.tsx CHANGED
@@ -76,7 +76,7 @@ const fetchGraph = async (label: string, maxDepth: number, minDegree: number) =>
76
  // Check if we need to fetch all database labels first
77
  const lastSuccessfulQueryLabel = useGraphStore.getState().lastSuccessfulQueryLabel;
78
  if (!lastSuccessfulQueryLabel) {
79
- console.log('Last successful query label is empty, fetching all database labels first...');
80
  try {
81
  await useGraphStore.getState().fetchAllDatabaseLabels();
82
  } catch (e) {
@@ -89,7 +89,7 @@ const fetchGraph = async (label: string, maxDepth: number, minDegree: number) =>
89
  const queryLabel = label || '*';
90
 
91
  try {
92
- console.log(`Fetching graph data with label: ${queryLabel}, maxDepth: ${maxDepth}, minDegree: ${minDegree}`);
93
  rawData = await queryGraphs(queryLabel, maxDepth, minDegree);
94
  } catch (e) {
95
  useBackendState.getState().setErrorMessage(errorMessage(e), 'Query Graphs Error!');
@@ -163,7 +163,7 @@ const fetchGraph = async (label: string, maxDepth: number, minDegree: number) =>
163
 
164
  if (!validateGraph(rawGraph)) {
165
  rawGraph = null
166
- console.error('Invalid graph data')
167
  }
168
  console.log('Graph data loaded')
169
  }
@@ -360,8 +360,6 @@ const useLightrangeGraph = () => {
360
 
361
  // Reset camera view
362
  state.setMoveToSelectedNode(true);
363
-
364
- console.log('Graph data loaded successfully');
365
  }
366
 
367
  // Update flags
@@ -466,7 +464,7 @@ const useLightrangeGraph = () => {
466
  const nodesToAdd = new Set<string>();
467
  const edgesToAdd = new Set<string>();
468
 
469
- // Get degree range from existing graph for size calculations
470
  const minDegree = 1;
471
  let maxDegree = 0;
472
  sigmaGraph.forEachNode(node => {
@@ -474,10 +472,6 @@ const useLightrangeGraph = () => {
474
  maxDegree = Math.max(maxDegree, degree);
475
  });
476
 
477
- // Calculate size formula parameters
478
- const range = maxDegree - minDegree || 1; // Avoid division by zero
479
- const scale = Constants.maxNodeSize - Constants.minNodeSize;
480
-
481
  // First identify connectable nodes (nodes connected to the expanded node)
482
  for (const node of processedNodes) {
483
  // Skip if node already exists
@@ -498,6 +492,7 @@ const useLightrangeGraph = () => {
498
 
499
  // Calculate node degrees and track discarded edges in one pass
500
  const nodeDegrees = new Map<string, number>();
 
501
  const nodesWithDiscardedEdges = new Set<string>();
502
 
503
  for (const edge of processedEdges) {
@@ -506,12 +501,19 @@ const useLightrangeGraph = () => {
506
 
507
  if (sourceExists && targetExists) {
508
  edgesToAdd.add(edge.id);
509
- // Add degrees for valid edges
510
  if (nodesToAdd.has(edge.source)) {
511
  nodeDegrees.set(edge.source, (nodeDegrees.get(edge.source) || 0) + 1);
 
 
 
512
  }
 
513
  if (nodesToAdd.has(edge.target)) {
514
  nodeDegrees.set(edge.target, (nodeDegrees.get(edge.target) || 0) + 1);
 
 
 
515
  }
516
  } else {
517
  // Track discarded edges for both new and existing nodes
@@ -535,16 +537,21 @@ const useLightrangeGraph = () => {
535
  sigmaGraph: DirectedGraph,
536
  nodesWithDiscardedEdges: Set<string>,
537
  minDegree: number,
538
- range: number,
539
- scale: number
540
  ) => {
 
 
 
 
541
  for (const nodeId of nodesWithDiscardedEdges) {
542
  if (sigmaGraph.hasNode(nodeId)) {
543
  let newDegree = sigmaGraph.degree(nodeId);
544
  newDegree += 1; // Add +1 for discarded edges
 
 
545
 
546
  const newSize = Math.round(
547
- Constants.minNodeSize + scale * Math.pow((newDegree - minDegree) / range, 0.5)
548
  );
549
 
550
  const currentSize = sigmaGraph.getNodeAttribute(nodeId, 'size');
@@ -558,16 +565,27 @@ const useLightrangeGraph = () => {
558
 
559
  // If no new connectable nodes found, show toast and return
560
  if (nodesToAdd.size === 0) {
561
- updateNodeSizes(sigmaGraph, nodesWithDiscardedEdges, minDegree, range, scale);
562
  toast.info(t('graphPanel.propertiesView.node.noNewNodes'));
563
  return;
564
  }
565
 
566
- // Update maxDegree with new node degrees
 
567
  for (const [, degree] of nodeDegrees.entries()) {
568
  maxDegree = Math.max(maxDegree, degree);
569
  }
570
 
 
 
 
 
 
 
 
 
 
 
571
  // SAdd nodes and edges to the graph
572
  // Calculate camera ratio and spread factor once before the loop
573
  const cameraRatio = useGraphStore.getState().sigmaInstance?.getCamera().ratio || 1;
@@ -587,8 +605,10 @@ const useLightrangeGraph = () => {
587
  const nodeDegree = nodeDegrees.get(nodeId) || 0;
588
 
589
  // Calculate node size
 
 
590
  const nodeSize = Math.round(
591
- Constants.minNodeSize + scale * Math.pow((nodeDegree - minDegree) / range, 0.5)
592
  );
593
 
594
  // Calculate angle for polar coordinates
@@ -663,7 +683,18 @@ const useLightrangeGraph = () => {
663
  useGraphStore.getState().resetSearchEngine();
664
 
665
  // Update sizes for all nodes with discarded edges
666
- updateNodeSizes(sigmaGraph, nodesWithDiscardedEdges, minDegree, range, scale);
 
 
 
 
 
 
 
 
 
 
 
667
 
668
  } catch (error) {
669
  console.error('Error expanding node:', error);
 
76
  // Check if we need to fetch all database labels first
77
  const lastSuccessfulQueryLabel = useGraphStore.getState().lastSuccessfulQueryLabel;
78
  if (!lastSuccessfulQueryLabel) {
79
+ console.log('Last successful queryLabel is empty');
80
  try {
81
  await useGraphStore.getState().fetchAllDatabaseLabels();
82
  } catch (e) {
 
89
  const queryLabel = label || '*';
90
 
91
  try {
92
+ console.log(`Fetching graph label: ${queryLabel}, depth: ${maxDepth}, deg: ${minDegree}`);
93
  rawData = await queryGraphs(queryLabel, maxDepth, minDegree);
94
  } catch (e) {
95
  useBackendState.getState().setErrorMessage(errorMessage(e), 'Query Graphs Error!');
 
163
 
164
  if (!validateGraph(rawGraph)) {
165
  rawGraph = null
166
+ console.warn('Invalid graph data')
167
  }
168
  console.log('Graph data loaded')
169
  }
 
360
 
361
  // Reset camera view
362
  state.setMoveToSelectedNode(true);
 
 
363
  }
364
 
365
  // Update flags
 
464
  const nodesToAdd = new Set<string>();
465
  const edgesToAdd = new Set<string>();
466
 
467
+ // Get degree maxDegree from existing graph for size calculations
468
  const minDegree = 1;
469
  let maxDegree = 0;
470
  sigmaGraph.forEachNode(node => {
 
472
  maxDegree = Math.max(maxDegree, degree);
473
  });
474
 
 
 
 
 
475
  // First identify connectable nodes (nodes connected to the expanded node)
476
  for (const node of processedNodes) {
477
  // Skip if node already exists
 
492
 
493
  // Calculate node degrees and track discarded edges in one pass
494
  const nodeDegrees = new Map<string, number>();
495
+ const existingNodeDegreeIncrements = new Map<string, number>(); // Track degree increments for existing nodes
496
  const nodesWithDiscardedEdges = new Set<string>();
497
 
498
  for (const edge of processedEdges) {
 
501
 
502
  if (sourceExists && targetExists) {
503
  edgesToAdd.add(edge.id);
504
+ // Add degrees for both new and existing nodes
505
  if (nodesToAdd.has(edge.source)) {
506
  nodeDegrees.set(edge.source, (nodeDegrees.get(edge.source) || 0) + 1);
507
+ } else if (existingNodeIds.has(edge.source)) {
508
+ // Track degree increments for existing nodes
509
+ existingNodeDegreeIncrements.set(edge.source, (existingNodeDegreeIncrements.get(edge.source) || 0) + 1);
510
  }
511
+
512
  if (nodesToAdd.has(edge.target)) {
513
  nodeDegrees.set(edge.target, (nodeDegrees.get(edge.target) || 0) + 1);
514
+ } else if (existingNodeIds.has(edge.target)) {
515
+ // Track degree increments for existing nodes
516
+ existingNodeDegreeIncrements.set(edge.target, (existingNodeDegreeIncrements.get(edge.target) || 0) + 1);
517
  }
518
  } else {
519
  // Track discarded edges for both new and existing nodes
 
537
  sigmaGraph: DirectedGraph,
538
  nodesWithDiscardedEdges: Set<string>,
539
  minDegree: number,
540
+ maxDegree: number
 
541
  ) => {
542
+ // Calculate derived values inside the function
543
+ const range = maxDegree - minDegree || 1; // Avoid division by zero
544
+ const scale = Constants.maxNodeSize - Constants.minNodeSize;
545
+
546
  for (const nodeId of nodesWithDiscardedEdges) {
547
  if (sigmaGraph.hasNode(nodeId)) {
548
  let newDegree = sigmaGraph.degree(nodeId);
549
  newDegree += 1; // Add +1 for discarded edges
550
+ // Limit newDegree to maxDegree + 1 to prevent nodes from being too large
551
+ const limitedDegree = Math.min(newDegree, maxDegree + 1);
552
 
553
  const newSize = Math.round(
554
+ Constants.minNodeSize + scale * Math.pow((limitedDegree - minDegree) / range, 0.5)
555
  );
556
 
557
  const currentSize = sigmaGraph.getNodeAttribute(nodeId, 'size');
 
565
 
566
  // If no new connectable nodes found, show toast and return
567
  if (nodesToAdd.size === 0) {
568
+ updateNodeSizes(sigmaGraph, nodesWithDiscardedEdges, minDegree, maxDegree);
569
  toast.info(t('graphPanel.propertiesView.node.noNewNodes'));
570
  return;
571
  }
572
 
573
+ // Update maxDegree considering all nodes (both new and existing)
574
+ // 1. Consider degrees of new nodes
575
  for (const [, degree] of nodeDegrees.entries()) {
576
  maxDegree = Math.max(maxDegree, degree);
577
  }
578
 
579
+ // 2. Consider degree increments for existing nodes
580
+ for (const [nodeId, increment] of existingNodeDegreeIncrements.entries()) {
581
+ const currentDegree = sigmaGraph.degree(nodeId);
582
+ const projectedDegree = currentDegree + increment;
583
+ maxDegree = Math.max(maxDegree, projectedDegree);
584
+ }
585
+
586
+ const range = maxDegree - minDegree || 1; // Avoid division by zero
587
+ const scale = Constants.maxNodeSize - Constants.minNodeSize;
588
+
589
  // SAdd nodes and edges to the graph
590
  // Calculate camera ratio and spread factor once before the loop
591
  const cameraRatio = useGraphStore.getState().sigmaInstance?.getCamera().ratio || 1;
 
605
  const nodeDegree = nodeDegrees.get(nodeId) || 0;
606
 
607
  // Calculate node size
608
+ // Limit nodeDegree to maxDegree + 1 to prevent new nodes from being too large
609
+ const limitedDegree = Math.min(nodeDegree, maxDegree + 1);
610
  const nodeSize = Math.round(
611
+ Constants.minNodeSize + scale * Math.pow((limitedDegree - minDegree) / range, 0.5)
612
  );
613
 
614
  // Calculate angle for polar coordinates
 
683
  useGraphStore.getState().resetSearchEngine();
684
 
685
  // Update sizes for all nodes with discarded edges
686
+ updateNodeSizes(sigmaGraph, nodesWithDiscardedEdges, minDegree, maxDegree);
687
+
688
+ if (sigmaGraph.hasNode(nodeId)) {
689
+ const finalDegree = sigmaGraph.degree(nodeId);
690
+ const limitedDegree = Math.min(finalDegree, maxDegree + 1);
691
+ const newSize = Math.round(
692
+ Constants.minNodeSize + scale * Math.pow((limitedDegree - minDegree) / range, 0.5)
693
+ );
694
+ sigmaGraph.setNodeAttribute(nodeId, 'size', newSize);
695
+ nodeToExpand.size = newSize;
696
+ nodeToExpand.degree = finalDegree;
697
+ }
698
 
699
  } catch (error) {
700
  console.error('Error expanding node:', error);
lightrag_webui/src/locales/ar.json CHANGED
@@ -164,7 +164,7 @@
164
  "labels": "التسميات",
165
  "degree": "الدرجة",
166
  "properties": "الخصائص",
167
- "relationships": "العلاقات",
168
  "expandNode": "توسيع العقدة",
169
  "pruneNode": "تقليم العقدة",
170
  "deleteAllNodesError": "رفض حذف جميع العقد في الرسم البياني",
 
164
  "labels": "التسميات",
165
  "degree": "الدرجة",
166
  "properties": "الخصائص",
167
+ "relationships": "العلاقات (داخل الرسم الفرعي)",
168
  "expandNode": "توسيع العقدة",
169
  "pruneNode": "تقليم العقدة",
170
  "deleteAllNodesError": "رفض حذف جميع العقد في الرسم البياني",
lightrag_webui/src/locales/en.json CHANGED
@@ -167,7 +167,7 @@
167
  "labels": "Labels",
168
  "degree": "Degree",
169
  "properties": "Properties",
170
- "relationships": "Relationships",
171
  "expandNode": "Expand Node",
172
  "pruneNode": "Prune Node",
173
  "deleteAllNodesError": "Refuse to delete all nodes in the graph",
 
167
  "labels": "Labels",
168
  "degree": "Degree",
169
  "properties": "Properties",
170
+ "relationships": "Relations(within subgraph)",
171
  "expandNode": "Expand Node",
172
  "pruneNode": "Prune Node",
173
  "deleteAllNodesError": "Refuse to delete all nodes in the graph",
lightrag_webui/src/locales/fr.json CHANGED
@@ -164,7 +164,7 @@
164
  "labels": "Étiquettes",
165
  "degree": "Degré",
166
  "properties": "Propriétés",
167
- "relationships": "Relations",
168
  "expandNode": "Développer le nœud",
169
  "pruneNode": "Élaguer le nœud",
170
  "deleteAllNodesError": "Refus de supprimer tous les nœuds du graphe",
 
164
  "labels": "Étiquettes",
165
  "degree": "Degré",
166
  "properties": "Propriétés",
167
+ "relationships": "Relations(dans le sous-graphe)",
168
  "expandNode": "Développer le nœud",
169
  "pruneNode": "Élaguer le nœud",
170
  "deleteAllNodesError": "Refus de supprimer tous les nœuds du graphe",
lightrag_webui/src/locales/zh.json CHANGED
@@ -164,7 +164,7 @@
164
  "labels": "标签",
165
  "degree": "度数",
166
  "properties": "属性",
167
- "relationships": "关系",
168
  "expandNode": "扩展节点",
169
  "pruneNode": "修剪节点",
170
  "deleteAllNodesError": "拒绝删除图中的所有节点",
 
164
  "labels": "标签",
165
  "degree": "度数",
166
  "properties": "属性",
167
+ "relationships": "关系(子图内)",
168
  "expandNode": "扩展节点",
169
  "pruneNode": "修剪节点",
170
  "deleteAllNodesError": "拒绝删除图中的所有节点",