yangdx
commited on
Commit
·
e7aca43
1
Parent(s):
8d92e7b
Add env FORCE_LLM_SUMMARY_ON_MERGE
Browse files- env.example +6 -2
- lightrag/api/utils_api.py +5 -1
- lightrag/lightrag.py +4 -2
- lightrag/operate.py +58 -44
- lightrag/utils.py +1 -1
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 |
-
|
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("
|
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 |
-
|
107 |
-
|
|
|
|
|
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["
|
|
|
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 |
-
|
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 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
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 |
-
|
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 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
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"
|
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(
|