From ad2102c1a81e1c5296530613b6c456aae98525cd Mon Sep 17 00:00:00 2001 From: qinling0210 <88864212+qinling0210@users.noreply.github.com> Date: Tue, 28 Jul 2026 15:26:40 +0800 Subject: [PATCH] fix(infinity): parent_kwd incorrectly split as keyword list causing orphaned clusters (#17475) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …rphaned clusters ### Summary **Problem** When deleting a document from the knowledge base, the parent cluster could never be located and was therefore never cleaned up, leaving orphaned clusters in Infinity indefinitely. **Root Cause** InfinityConnection.field_keyword() treats all _kwd-suffixed columns as keyword lists and applies .split("###") to them in get_fields(). parent_kwd was missing from the exclusion list. This caused a parent cluster name like "Toronto Transit & Authority Control 5e8d5eb6" to become ['Toronto Transit & Authority Control 5e8d5eb6'] (a single-element list). When that list was fed into _nav_cluster_id(), it produced a different hash than the actual cluster's hash (computed from the plain string), so every deletion-time cluster lookup silently failed. **Fix** Added "parent_kwd" to the exclusion list in field_keyword(), alongside docnm_kwd, important_kwd, question_kwd, etc. --- rag/utils/infinity_conn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rag/utils/infinity_conn.py b/rag/utils/infinity_conn.py index f69324e07f..e2980f19e2 100644 --- a/rag/utils/infinity_conn.py +++ b/rag/utils/infinity_conn.py @@ -72,11 +72,11 @@ class InfinityConnection(InfinityConnectionBase): @staticmethod def field_keyword(field_name: str): - # Treat "*_kwd" tag-like columns as keyword lists except knowledge_graph_kwd; source_id is also keyword-like. + # Treat "*_kwd" tag-like columns as keyword lists except for the fields in the exclusion list; source_id is also keyword-like. # source_doc_ids / source_chunk_ids are multi-valued provenance lists (artifact/wiki rows) and must be # stored/read/updated as keyword lists so the delete-time ref-count (remove one id, drop row when empty) works. if field_name in ("source_id", "source_doc_ids", "source_chunk_ids") or ( - field_name.endswith("_kwd") and field_name not in ["knowledge_graph_kwd", "docnm_kwd", "important_kwd", "question_kwd"] + field_name.endswith("_kwd") and field_name not in ["knowledge_graph_kwd", "docnm_kwd", "important_kwd", "question_kwd", "parent_kwd"] ): return True return False