Merge pull request #2218 from danielaskdd/issue-2215

Refact: Improve query result with semantic null returns
This commit is contained in:
Daniel.y 2025-10-15 12:33:52 +08:00 committed by GitHub
commit 83b10a52ad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 48 additions and 30 deletions

View file

@ -21,6 +21,7 @@ from typing import (
List, List,
Dict, Dict,
) )
from lightrag.prompt import PROMPTS
from lightrag.constants import ( from lightrag.constants import (
DEFAULT_MAX_GLEANING, DEFAULT_MAX_GLEANING,
DEFAULT_FORCE_LLM_SUMMARY_ON_MERGE, DEFAULT_FORCE_LLM_SUMMARY_ON_MERGE,
@ -2287,20 +2288,35 @@ class LightRAG:
else: else:
raise ValueError(f"Unknown mode {data_param.mode}") raise ValueError(f"Unknown mode {data_param.mode}")
# Extract raw_data from QueryResult if query_result is None:
final_data = query_result.raw_data if query_result else {} no_result_message = "Query returned no results"
if data_param.mode == "naive":
# Log final result counts - adapt to new data format from convert_to_user_format no_result_message = "No relevant document chunks found."
if final_data and "data" in final_data: final_data: dict[str, Any] = {
data_section = final_data["data"] "status": "failure",
entities_count = len(data_section.get("entities", [])) "message": no_result_message,
relationships_count = len(data_section.get("relationships", [])) "data": {},
chunks_count = len(data_section.get("chunks", [])) "metadata": {
logger.debug( "failure_reason": "no_results",
f"[aquery_data] Final result: {entities_count} entities, {relationships_count} relationships, {chunks_count} chunks" "mode": data_param.mode,
) },
}
logger.info("[aquery_data] Query returned no results.")
else: else:
logger.warning("[aquery_data] No data section found in query result") # Extract raw_data from QueryResult
final_data = query_result.raw_data or {}
# Log final result counts - adapt to new data format from convert_to_user_format
if final_data and "data" in final_data:
data_section = final_data["data"]
entities_count = len(data_section.get("entities", []))
relationships_count = len(data_section.get("relationships", []))
chunks_count = len(data_section.get("chunks", []))
logger.debug(
f"[aquery_data] Final result: {entities_count} entities, {relationships_count} relationships, {chunks_count} chunks"
)
else:
logger.warning("[aquery_data] No data section found in query result")
await self._query_done() await self._query_done()
return final_data return final_data
@ -2403,16 +2419,19 @@ class LightRAG:
"status": "failure", "status": "failure",
"message": "Query returned no results", "message": "Query returned no results",
"data": {}, "data": {},
"metadata": {}, "metadata": {
"failure_reason": "no_results",
"mode": param.mode,
},
"llm_response": { "llm_response": {
"content": None, "content": PROMPTS["fail_response"],
"response_iterator": None, "response_iterator": None,
"is_streaming": False, "is_streaming": False,
}, },
} }
# Extract structured data from query result # Extract structured data from query result
raw_data = query_result.raw_data if query_result else {} raw_data = query_result.raw_data or {}
raw_data["llm_response"] = { raw_data["llm_response"] = {
"content": query_result.content "content": query_result.content
if not query_result.is_streaming if not query_result.is_streaming

View file

@ -2247,7 +2247,7 @@ async def kg_query(
hashing_kv: BaseKVStorage | None = None, hashing_kv: BaseKVStorage | None = None,
system_prompt: str | None = None, system_prompt: str | None = None,
chunks_vdb: BaseVectorStorage = None, chunks_vdb: BaseVectorStorage = None,
) -> QueryResult: ) -> QueryResult | None:
""" """
Execute knowledge graph query and return unified QueryResult object. Execute knowledge graph query and return unified QueryResult object.
@ -2264,7 +2264,7 @@ async def kg_query(
chunks_vdb: Document chunks vector database chunks_vdb: Document chunks vector database
Returns: Returns:
QueryResult: Unified query result object containing: QueryResult | None: Unified query result object containing:
- content: Non-streaming response text content - content: Non-streaming response text content
- response_iterator: Streaming response iterator - response_iterator: Streaming response iterator
- raw_data: Complete structured data (including references and metadata) - raw_data: Complete structured data (including references and metadata)
@ -2275,6 +2275,8 @@ async def kg_query(
- only_need_prompt=True: content contains complete prompt - only_need_prompt=True: content contains complete prompt
- stream=True: response_iterator contains streaming response, raw_data contains complete data - stream=True: response_iterator contains streaming response, raw_data contains complete data
- default: content contains LLM response text, raw_data contains complete data - default: content contains LLM response text, raw_data contains complete data
Returns None when no relevant context could be constructed for the query.
""" """
if not query: if not query:
return QueryResult(content=PROMPTS["fail_response"]) return QueryResult(content=PROMPTS["fail_response"])
@ -2322,7 +2324,8 @@ async def kg_query(
) )
if context_result is None: if context_result is None:
return QueryResult(content=PROMPTS["fail_response"]) logger.info("[kg_query] No query context could be built; returning no-result.")
return None
# Return different content based on query parameters # Return different content based on query parameters
if query_param.only_need_context and not query_param.only_need_prompt: if query_param.only_need_context and not query_param.only_need_prompt:
@ -3985,7 +3988,7 @@ async def naive_query(
global_config: dict[str, str], global_config: dict[str, str],
hashing_kv: BaseKVStorage | None = None, hashing_kv: BaseKVStorage | None = None,
system_prompt: str | None = None, system_prompt: str | None = None,
) -> QueryResult: ) -> QueryResult | None:
""" """
Execute naive query and return unified QueryResult object. Execute naive query and return unified QueryResult object.
@ -3998,11 +4001,13 @@ async def naive_query(
system_prompt: System prompt system_prompt: System prompt
Returns: Returns:
QueryResult: Unified query result object containing: QueryResult | None: Unified query result object containing:
- content: Non-streaming response text content - content: Non-streaming response text content
- response_iterator: Streaming response iterator - response_iterator: Streaming response iterator
- raw_data: Complete structured data (including references and metadata) - raw_data: Complete structured data (including references and metadata)
- is_streaming: Whether this is a streaming result - is_streaming: Whether this is a streaming result
Returns None when no relevant chunks are retrieved.
""" """
if not query: if not query:
@ -4023,16 +4028,10 @@ async def naive_query(
chunks = await _get_vector_context(query, chunks_vdb, query_param, None) chunks = await _get_vector_context(query, chunks_vdb, query_param, None)
if chunks is None or len(chunks) == 0: if chunks is None or len(chunks) == 0:
# Build empty raw data structure for naive mode logger.info(
empty_raw_data = convert_to_user_format( "[naive_query] No relevant document chunks found; returning no-result."
[], # naive mode has no entities
[], # naive mode has no relationships
[], # no chunks
[], # no references
"naive",
) )
empty_raw_data["message"] = "No relevant document chunks found." return None
return QueryResult(content=PROMPTS["fail_response"], raw_data=empty_raw_data)
# Calculate dynamic token limit for chunks # Calculate dynamic token limit for chunks
max_total_tokens = getattr( max_total_tokens = getattr(