yangdx commited on
Commit
e7aca43
·
1 Parent(s): 8d92e7b

Add env FORCE_LLM_SUMMARY_ON_MERGE

Browse files
env.example CHANGED
@@ -43,11 +43,15 @@ WEBUI_DESCRIPTION="Simple and Fast Graph Based RAG System"
43
  SUMMARY_LANGUAGE=English
44
  # CHUNK_SIZE=1200
45
  # CHUNK_OVERLAP_SIZE=100
46
- ### Max tokens for entity or relations summary
47
- # MAX_TOKEN_SUMMARY=500
48
  ### Number of parallel processing documents in one patch
49
  # MAX_PARALLEL_INSERT=2
50
 
 
 
 
 
 
51
  ### Num of chunks send to Embedding in single request
52
  # EMBEDDING_BATCH_NUM=32
53
  ### Max concurrency requests for Embedding
 
43
  SUMMARY_LANGUAGE=English
44
  # CHUNK_SIZE=1200
45
  # CHUNK_OVERLAP_SIZE=100
46
+
 
47
  ### Number of parallel processing documents in one patch
48
  # MAX_PARALLEL_INSERT=2
49
 
50
+ ### Max tokens for entity/relations description after merge
51
+ # MAX_TOKEN_SUMMARY=500
52
+ ### Number of entities/edges to trigger LLM re-summary on merge ( at least 3 is recommented)
53
+ # FORCE_LLM_SUMMARY_ON_MERGE=6
54
+
55
  ### Num of chunks send to Embedding in single request
56
  # EMBEDDING_BATCH_NUM=32
57
  ### Max concurrency requests for Embedding
lightrag/api/utils_api.py CHANGED
@@ -261,8 +261,12 @@ def display_splash_screen(args: argparse.Namespace) -> None:
261
  ASCIIColors.yellow(f"{args.chunk_overlap_size}")
262
  ASCIIColors.white(" ├─ Cosine Threshold: ", end="")
263
  ASCIIColors.yellow(f"{args.cosine_threshold}")
264
- ASCIIColors.white(" └─ Top-K: ", end="")
265
  ASCIIColors.yellow(f"{args.top_k}")
 
 
 
 
266
 
267
  # System Configuration
268
  ASCIIColors.magenta("\n💾 Storage Configuration:")
 
261
  ASCIIColors.yellow(f"{args.chunk_overlap_size}")
262
  ASCIIColors.white(" ├─ Cosine Threshold: ", end="")
263
  ASCIIColors.yellow(f"{args.cosine_threshold}")
264
+ ASCIIColors.white(" ├─ Top-K: ", end="")
265
  ASCIIColors.yellow(f"{args.top_k}")
266
+ ASCIIColors.white(" ├─ Max Token Summary: ", end="")
267
+ ASCIIColors.yellow(f"{int(os.getenv('MAX_TOKEN_SUMMARY', 500))}")
268
+ ASCIIColors.white(" └─ Force LLM Summary on Merge: ", end="")
269
+ ASCIIColors.yellow(f"{int(os.getenv('FORCE_LLM_SUMMARY_ON_MERGE', 6))}")
270
 
271
  # System Configuration
272
  ASCIIColors.magenta("\n💾 Storage Configuration:")
lightrag/lightrag.py CHANGED
@@ -103,8 +103,10 @@ class LightRAG:
103
  entity_extract_max_gleaning: int = field(default=1)
104
  """Maximum number of entity extraction attempts for ambiguous content."""
105
 
106
- entity_summary_to_max_tokens: int = field(
107
- default=int(os.getenv("MAX_TOKEN_SUMMARY", 500))
 
 
108
  )
109
 
110
  # Text chunking
 
103
  entity_extract_max_gleaning: int = field(default=1)
104
  """Maximum number of entity extraction attempts for ambiguous content."""
105
 
106
+ summary_to_max_tokens: int = field(default=int(os.getenv("MAX_TOKEN_SUMMARY", 500)))
107
+
108
+ force_llm_summary_on_merge: int = field(
109
+ default=int(os.getenv("FORCE_LLM_SUMMARY_ON_MERGE", 6))
110
  )
111
 
112
  # Text chunking
lightrag/operate.py CHANGED
@@ -117,15 +117,13 @@ async def _handle_entity_relation_summary(
117
  use_llm_func: callable = global_config["llm_model_func"]
118
  llm_max_tokens = global_config["llm_model_max_token_size"]
119
  tiktoken_model_name = global_config["tiktoken_model_name"]
120
- summary_max_tokens = global_config["entity_summary_to_max_tokens"]
 
121
  language = global_config["addon_params"].get(
122
  "language", PROMPTS["DEFAULT_LANGUAGE"]
123
  )
124
 
125
  tokens = encode_string_by_tiktoken(description, model_name=tiktoken_model_name)
126
- if len(tokens) < summary_max_tokens: # No need for summary
127
- return description
128
-
129
  prompt_template = PROMPTS["summarize_entity_descriptions"]
130
  use_description = decode_tokens_by_tiktoken(
131
  tokens[:llm_max_tokens], model_name=tiktoken_model_name
@@ -138,14 +136,6 @@ async def _handle_entity_relation_summary(
138
  use_prompt = prompt_template.format(**context_base)
139
  logger.debug(f"Trigger summary: {entity_or_relation_name}")
140
 
141
- # Update pipeline status when LLM summary is needed
142
- status_message = " == Use LLM == to re-summary description..."
143
- logger.info(status_message)
144
- if pipeline_status is not None and pipeline_status_lock is not None:
145
- async with pipeline_status_lock:
146
- pipeline_status["latest_message"] = status_message
147
- pipeline_status["history_messages"].append(status_message)
148
-
149
  # Use LLM function with cache
150
  summary = await use_llm_func_with_cache(
151
  use_prompt,
@@ -270,23 +260,34 @@ async def _merge_nodes_then_upsert(
270
  set([dp["file_path"] for dp in nodes_data] + already_file_paths)
271
  )
272
 
273
- if len(nodes_data) > 1 or len(already_entity_types) > 0:
274
- # Update pipeline status when a node that needs merging
275
- status_message = f"Merging entity: {entity_name} | {len(nodes_data)}+{len(already_entity_types)}"
276
- logger.info(status_message)
277
- if pipeline_status is not None and pipeline_status_lock is not None:
278
- async with pipeline_status_lock:
279
- pipeline_status["latest_message"] = status_message
280
- pipeline_status["history_messages"].append(status_message)
281
 
282
- description = await _handle_entity_relation_summary(
283
- entity_name,
284
- description,
285
- global_config,
286
- pipeline_status,
287
- pipeline_status_lock,
288
- llm_response_cache,
289
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
 
291
  node_data = dict(
292
  entity_id=entity_name,
@@ -398,23 +399,36 @@ async def _merge_edges_then_upsert(
398
  },
399
  )
400
 
401
- if len(edges_data) > 1 or len(already_weights) > 0:
402
- # Update pipeline status when a edge that needs merging
403
- status_message = f"Merging edge::: {src_id} - {tgt_id} | {len(edges_data)}+{len(already_weights)}"
404
- logger.info(status_message)
405
- if pipeline_status is not None and pipeline_status_lock is not None:
406
- async with pipeline_status_lock:
407
- pipeline_status["latest_message"] = status_message
408
- pipeline_status["history_messages"].append(status_message)
409
 
410
- description = await _handle_entity_relation_summary(
411
- f"({src_id}, {tgt_id})",
412
- description,
413
- global_config,
414
- pipeline_status,
415
- pipeline_status_lock,
416
- llm_response_cache,
417
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
 
419
  await knowledge_graph_inst.upsert_edge(
420
  src_id,
 
117
  use_llm_func: callable = global_config["llm_model_func"]
118
  llm_max_tokens = global_config["llm_model_max_token_size"]
119
  tiktoken_model_name = global_config["tiktoken_model_name"]
120
+ summary_max_tokens = global_config["summary_to_max_tokens"]
121
+
122
  language = global_config["addon_params"].get(
123
  "language", PROMPTS["DEFAULT_LANGUAGE"]
124
  )
125
 
126
  tokens = encode_string_by_tiktoken(description, model_name=tiktoken_model_name)
 
 
 
127
  prompt_template = PROMPTS["summarize_entity_descriptions"]
128
  use_description = decode_tokens_by_tiktoken(
129
  tokens[:llm_max_tokens], model_name=tiktoken_model_name
 
136
  use_prompt = prompt_template.format(**context_base)
137
  logger.debug(f"Trigger summary: {entity_or_relation_name}")
138
 
 
 
 
 
 
 
 
 
139
  # Use LLM function with cache
140
  summary = await use_llm_func_with_cache(
141
  use_prompt,
 
260
  set([dp["file_path"] for dp in nodes_data] + already_file_paths)
261
  )
262
 
263
+ force_llm_summary_on_merge = global_config["force_llm_summary_on_merge"]
 
 
 
 
 
 
 
264
 
265
+ num_fragment = description.count(GRAPH_FIELD_SEP) + 1
266
+ num_new_fragment = len(set([dp["description"] for dp in nodes_data]))
267
+
268
+ if num_fragment > 1:
269
+ if num_fragment >= force_llm_summary_on_merge:
270
+ status_message = f"LLM merge N: {entity_name} | {num_new_fragment}+{num_fragment-num_new_fragment}"
271
+ logger.info(status_message)
272
+ if pipeline_status is not None and pipeline_status_lock is not None:
273
+ async with pipeline_status_lock:
274
+ pipeline_status["latest_message"] = status_message
275
+ pipeline_status["history_messages"].append(status_message)
276
+ description = await _handle_entity_relation_summary(
277
+ entity_name,
278
+ description,
279
+ global_config,
280
+ pipeline_status,
281
+ pipeline_status_lock,
282
+ llm_response_cache,
283
+ )
284
+ else:
285
+ status_message = f"Merge N: {entity_name} | {num_new_fragment}+{num_fragment-num_new_fragment}"
286
+ logger.info(status_message)
287
+ if pipeline_status is not None and pipeline_status_lock is not None:
288
+ async with pipeline_status_lock:
289
+ pipeline_status["latest_message"] = status_message
290
+ pipeline_status["history_messages"].append(status_message)
291
 
292
  node_data = dict(
293
  entity_id=entity_name,
 
399
  },
400
  )
401
 
402
+ force_llm_summary_on_merge = global_config["force_llm_summary_on_merge"]
 
 
 
 
 
 
 
403
 
404
+ num_fragment = description.count(GRAPH_FIELD_SEP) + 1
405
+ num_new_fragment = len(
406
+ set([dp["description"] for dp in edges_data if dp.get("description")])
407
+ )
408
+
409
+ if num_fragment > 1:
410
+ if num_fragment >= force_llm_summary_on_merge:
411
+ status_message = f"LLM merge E: {src_id} - {tgt_id} | {num_new_fragment}+{num_fragment-num_new_fragment}"
412
+ logger.info(status_message)
413
+ if pipeline_status is not None and pipeline_status_lock is not None:
414
+ async with pipeline_status_lock:
415
+ pipeline_status["latest_message"] = status_message
416
+ pipeline_status["history_messages"].append(status_message)
417
+ description = await _handle_entity_relation_summary(
418
+ f"({src_id}, {tgt_id})",
419
+ description,
420
+ global_config,
421
+ pipeline_status,
422
+ pipeline_status_lock,
423
+ llm_response_cache,
424
+ )
425
+ else:
426
+ status_message = f"Merge E: {src_id} - {tgt_id} | {num_new_fragment}+{num_fragment-num_new_fragment}"
427
+ logger.info(status_message)
428
+ if pipeline_status is not None and pipeline_status_lock is not None:
429
+ async with pipeline_status_lock:
430
+ pipeline_status["latest_message"] = status_message
431
+ pipeline_status["history_messages"].append(status_message)
432
 
433
  await knowledge_graph_inst.upsert_edge(
434
  src_id,
lightrag/utils.py CHANGED
@@ -967,7 +967,7 @@ async def use_llm_func_with_cache(
967
  res: str = await use_llm_func(input_text, **kwargs)
968
 
969
  # Save to cache
970
- logger.info(f"Saving LLM cache for {arg_hash}")
971
  await save_to_cache(
972
  llm_response_cache,
973
  CacheData(
 
967
  res: str = await use_llm_func(input_text, **kwargs)
968
 
969
  # Save to cache
970
+ logger.info(f" == LLM cache == saving {arg_hash}")
971
  await save_to_cache(
972
  llm_response_cache,
973
  CacheData(