1- import traceback
21from pathlib import Path
32
43from astrbot .core import logger
@@ -56,8 +55,7 @@ async def initialize(self) -> None:
5655 logger .error (f"知识库模块导入失败: { e } " )
5756 logger .warning ("请确保已安装所需依赖: pypdf, aiofiles, Pillow, rank-bm25" )
5857 except Exception as e :
59- logger .error (f"知识库模块初始化失败: { e } " )
60- logger .error (traceback .format_exc ())
58+ logger .error (f"知识库模块初始化失败: { e } " , exc_info = True )
6159
6260 async def _init_kb_database (self ) -> None :
6361 self .kb_db = KBSQLiteDatabase (DB_PATH .as_posix ())
@@ -76,7 +74,14 @@ async def load_kbs(self) -> None:
7674 kb_root_dir = FILES_PATH ,
7775 chunker = CHUNKER ,
7876 )
79- await kb_helper .initialize ()
77+ try :
78+ await kb_helper .initialize ()
79+ except Exception as e :
80+ kb_helper .init_error = str (e )
81+ logger .error (
82+ f"知识库 { record .kb_name } ({ record .kb_id } ) 初始化失败: { e } " ,
83+ exc_info = True ,
84+ )
8085 self .kb_insts [record .kb_id ] = kb_helper
8186
8287 async def create_kb (
@@ -179,6 +184,20 @@ async def update_kb(
179184 return None
180185
181186 kb = kb_helper .kb
187+ previous_state = {
188+ "kb_name" : kb .kb_name ,
189+ "description" : kb .description ,
190+ "emoji" : kb .emoji ,
191+ "embedding_provider_id" : kb .embedding_provider_id ,
192+ "rerank_provider_id" : kb .rerank_provider_id ,
193+ "chunk_size" : kb .chunk_size ,
194+ "chunk_overlap" : kb .chunk_overlap ,
195+ "top_k_dense" : kb .top_k_dense ,
196+ "top_k_sparse" : kb .top_k_sparse ,
197+ "top_m_final" : kb .top_m_final ,
198+ }
199+ previous_init_error = kb_helper .init_error
200+
182201 if kb_name is not None :
183202 kb .kb_name = kb_name
184203 if description is not None :
@@ -198,12 +217,47 @@ async def update_kb(
198217 kb .top_k_sparse = top_k_sparse
199218 if top_m_final is not None :
200219 kb .top_m_final = top_m_final
220+
221+ # Build a new helper first. Keep current vec_db alive until new init succeeds.
222+ new_helper = KBHelper (
223+ kb_db = self .kb_db ,
224+ kb = kb ,
225+ provider_manager = self .provider_manager ,
226+ kb_root_dir = FILES_PATH ,
227+ chunker = CHUNKER ,
228+ )
229+
230+ try :
231+ await new_helper .initialize ()
232+ except Exception as e :
233+ # Roll back in-memory settings and keep current helper available.
234+ kb .kb_name = previous_state ["kb_name" ]
235+ kb .description = previous_state ["description" ]
236+ kb .emoji = previous_state ["emoji" ]
237+ kb .embedding_provider_id = previous_state ["embedding_provider_id" ]
238+ kb .rerank_provider_id = previous_state ["rerank_provider_id" ]
239+ kb .chunk_size = previous_state ["chunk_size" ]
240+ kb .chunk_overlap = previous_state ["chunk_overlap" ]
241+ kb .top_k_dense = previous_state ["top_k_dense" ]
242+ kb .top_k_sparse = previous_state ["top_k_sparse" ]
243+ kb .top_m_final = previous_state ["top_m_final" ]
244+ kb_helper .init_error = previous_init_error
245+ logger .error (
246+ f"知识库 { kb .kb_name } ({ kb .kb_id } ) 重新初始化失败,继续使用旧实例: { e } " ,
247+ exc_info = True ,
248+ )
249+ return kb_helper
250+
201251 async with self .kb_db .get_db () as session :
202252 session .add (kb )
203253 await session .commit ()
204254 await session .refresh (kb )
205255
206- return kb_helper
256+ old_helper = kb_helper
257+ self .kb_insts [kb_id ] = new_helper
258+ await old_helper .terminate ()
259+ new_helper .init_error = None
260+ return new_helper
207261
208262 async def retrieve (
209263 self ,
@@ -215,11 +269,21 @@ async def retrieve(
215269 """从指定知识库中检索相关内容"""
216270 kb_ids = []
217271 kb_id_helper_map = {}
272+ unavailable_kbs = []
218273 for kb_name in kb_names :
219274 if kb_helper := await self .get_kb_by_name (kb_name ):
275+ if kb_helper .init_error :
276+ unavailable_kbs .append ((kb_name , kb_helper .init_error ))
277+ logger .warning (f"知识库 { kb_name } 不可用: { kb_helper .init_error } " )
278+ continue
220279 kb_ids .append (kb_helper .kb .kb_id )
221280 kb_id_helper_map [kb_helper .kb .kb_id ] = kb_helper
222281
282+ # all requested KBs are unavailable
283+ if not kb_ids and unavailable_kbs :
284+ errors = "; " .join (f"{ n } : { e } " for n , e in unavailable_kbs )
285+ raise ValueError (f"所有请求的知识库均不可用: { errors } " )
286+
223287 if not kb_ids :
224288 return {}
225289
0 commit comments