@@ -741,6 +741,7 @@ async def summary_index_name(self,
741741 index_name: Name of the index to summarize
742742 batch_size: Number of documents to sample (default: 1000)
743743 vdb_core: VectorDatabaseCore instance
744+ user_id: ID of the user delete the knowledge base
744745 tenant_id: ID of the tenant
745746 language: Language of the summary (default: 'zh')
746747 model_id: Model ID for LLM summarization
@@ -762,32 +763,45 @@ async def summary_index_name(self,
762763 # Use new Map-Reduce approach
763764 sample_count = min (batch_size // 5 , 200 ) # Sample reasonable number of documents
764765
765- # Step 1: Get documents and calculate embeddings
766- document_samples , doc_embeddings = process_documents_for_clustering (
767- index_name = index_name ,
768- vdb_core = vdb_core ,
769- sample_doc_count = sample_count
770- )
771-
772- if not document_samples :
773- raise Exception ("No documents found in index." )
774-
775- # Step 2: Cluster documents
776- clusters = kmeans_cluster_documents (doc_embeddings , k = None )
777-
778- # Step 3: Map-Reduce summarization
779- cluster_summaries = summarize_clusters_map_reduce (
780- document_samples = document_samples ,
781- clusters = clusters ,
782- language = language ,
783- doc_max_words = 100 ,
784- cluster_max_words = 150 ,
785- model_id = model_id ,
786- tenant_id = tenant_id
787- )
766+ # Define a helper function to run all blocking operations in a thread pool
767+ def _generate_summary_sync ():
768+ """Synchronous function that performs all blocking operations"""
769+ # Step 1: Get documents and calculate embeddings
770+ document_samples , doc_embeddings = process_documents_for_clustering (
771+ index_name = index_name ,
772+ vdb_core = vdb_core ,
773+ sample_doc_count = sample_count
774+ )
775+
776+ if not document_samples :
777+ raise Exception ("No documents found in index." )
778+
779+ # Step 2: Cluster documents (CPU-intensive operation)
780+ clusters = kmeans_cluster_documents (doc_embeddings , k = None )
781+
782+ # Step 3: Map-Reduce summarization (contains blocking LLM calls)
783+ cluster_summaries = summarize_clusters_map_reduce (
784+ document_samples = document_samples ,
785+ clusters = clusters ,
786+ language = language ,
787+ doc_max_words = 100 ,
788+ cluster_max_words = 150 ,
789+ model_id = model_id ,
790+ tenant_id = tenant_id
791+ )
792+
793+ # Step 4: Merge into final summary
794+ final_summary = merge_cluster_summaries (cluster_summaries )
795+ return final_summary
788796
789- # Step 4: Merge into final summary
790- final_summary = merge_cluster_summaries (cluster_summaries )
797+ # Run blocking operations in a thread pool to avoid blocking the event loop
798+ # Use get_running_loop() for better compatibility with modern asyncio
799+ try :
800+ loop = asyncio .get_running_loop ()
801+ except RuntimeError :
802+ # Fallback for edge cases
803+ loop = asyncio .get_event_loop ()
804+ final_summary = await loop .run_in_executor (None , _generate_summary_sync )
791805
792806 # Stream the result
793807 async def generate_summary ():
0 commit comments