diff --git a/rag/services/kb_service.py b/rag/services/kb_service.py index 023ec28..238dd0a 100644 --- a/rag/services/kb_service.py +++ b/rag/services/kb_service.py @@ -166,16 +166,7 @@ class KBService: update_if_exists: bool = True ) -> Tuple[int, int]: """ - Индексирует документ в базу знаний с транзакционностью и атомарным обновлением: - 1. Если документ уже существует в комнате и update_if_exists=True, - запоминаем старый doc_id, но НЕ удаляем его сразу. - 2. Создаём новую запись с indexed=False и новым doc_id. - 3. Разбиваем на чанки, получаем эмбеддинги, загружаем в Qdrant. - 4. Если успешно – обновляем indexed=True у новой записи. - 5. Удаляем старый документ (если он был) из Qdrant и PostgreSQL. - 6. При ошибке – оставляем старый документ нетронутым, новую запись удаляем (или оставляем с indexed=False для диагностики). - - Это гарантирует, что в любой момент времени либо старая версия доступна, либо новая. + Индексирует документ в базу знаний с сохранением исходного текста в БД. """ source_name = title if title else file_name doc_meta = metadata or {} @@ -184,7 +175,7 @@ class KBService: old_doc_id = None - # ---- 1. Поиск существующего документа в комнате (если нужно обновление) ---- + # ---- 1. Поиск существующего документа в комнате ---- if update_if_exists and room_jid and not is_global: existing = await self.db.find_document_by_name_and_room(source_name, room_jid) if existing: @@ -195,7 +186,7 @@ class KBService: return old_doc_id, 0 logger.info(f"Обновление документа {source_name} в комнате {room_jid}: старая версия doc_id={old_doc_id}") - # ---- 2. Создание НОВОЙ записи в PostgreSQL с indexed=False ---- + # ---- 2. Создание НОВОЙ записи в PostgreSQL с indexed=False и сохранением текста ---- new_doc_id = await self.db.add_document( source_name=source_name, owner_jid=user_jid, @@ -204,7 +195,8 @@ class KBService: metadata=doc_meta, room_jid=room_jid, file_hash=file_hash, - indexed=False # начальное состояние – не проиндексирован + indexed=False, + file_text=file_text # <-- сохраняем исходный текст ) logger.info(f"Создана новая запись документа doc_id={new_doc_id} для {source_name}") @@ -231,7 +223,7 @@ class KBService: sparse_vectors = await self.embedding.embed_sparse_batch(chunks) - # ---- 5. Сохранение чанков в Qdrant (обёрнуто в to_thread) ---- + # ---- 5. Сохранение чанков в Qdrant ---- chunk_count = 0 success = True try: @@ -269,7 +261,6 @@ class KBService: # ---- 6. Если успешно – обновляем флаг indexed у НОВОЙ записи ---- if success and chunk_count > 0: await self.db.update_document_indexed(new_doc_id, True) - # Для личных документов предоставляем доступ владельцу if not is_global and not room_jid: await self.db.add_access(new_doc_id, user_jid) logger.info(f"Новый документ {source_name} (doc_id={new_doc_id}) проиндексирован, чанков: {chunk_count}") @@ -277,15 +268,11 @@ class KBService: # ---- 7. Удаляем СТАРЫЙ документ (если был) ---- if old_doc_id is not None: logger.info(f"Удаление старой версии документа doc_id={old_doc_id}") - # Удаление из Qdrant await asyncio.to_thread(self.qdrant.delete_by_doc_id, old_doc_id) - # Удаление из PostgreSQL (включая права доступа) await self.db.delete_documents_by_ids([old_doc_id]) logger.info(f"Старая версия doc_id={old_doc_id} удалена") else: - # Не удалось загрузить все чанки – оставляем новую запись с indexed=False для диагностики logger.error(f"Документ {source_name} (doc_id={new_doc_id}) не проиндексирован (чанков: {chunk_count})") - # Старый документ (если был) остаётся нетронутым return new_doc_id, chunk_count