Spaces:
Sleeping
Sleeping
""" | |
Базовый класс для всех стратегий чанкинга. | |
""" | |
from abc import ABC, abstractmethod | |
from ntr_fileparser import ParsedDocument | |
from ..models import Chunk, DocumentAsEntity, LinkerEntity | |
class ChunkingStrategy(ABC): | |
""" | |
Базовый абстрактный класс для всех стратегий чанкинга. | |
""" | |
def chunk(self, document: ParsedDocument, doc_entity: DocumentAsEntity | None = None) -> list[LinkerEntity]: | |
""" | |
Разбивает документ на чанки в соответствии со стратегией. | |
Args: | |
document: ParsedDocument для извлечения текста | |
doc_entity: Опциональная сущность документа для привязки чанков. | |
Если не указана, будет создана новая. | |
Returns: | |
list[LinkerEntity]: Список сущностей (документ, чанки, связи) | |
""" | |
raise NotImplementedError("Стратегия чанкинга должна реализовать метод chunk") | |
def dechunk(self, chunks: list[LinkerEntity], repository: 'EntityRepository' = None) -> str: | |
""" | |
Собирает документ из чанков и связей. | |
Базовая реализация сортирует чанки по chunk_index и объединяет их тексты, | |
сохраняя структуру параграфов и избегая дублирования текста. | |
Args: | |
chunks: Список отфильтрованных чанков в случайном порядке | |
repository: Репозиторий сущностей для получения дополнительной информации (может быть None) | |
Returns: | |
Восстановленный текст документа | |
""" | |
import re | |
# Проверяем, есть ли чанки для сборки | |
if not chunks: | |
return "" | |
# Отбираем только чанки | |
valid_chunks = [c for c in chunks if isinstance(c, Chunk)] | |
# Сортируем чанки по chunk_index | |
sorted_chunks = sorted(valid_chunks, key=lambda c: c.chunk_index or 0) | |
# Собираем текст документа с учетом структуры параграфов | |
result_text = "" | |
for chunk in sorted_chunks: | |
# Получаем текст чанка (предпочитаем text, а не in_search_text для избежания дублирования) | |
chunk_text = chunk.text if hasattr(chunk, 'text') and chunk.text else "" | |
# Добавляем текст чанка с сохранением структуры параграфов | |
if result_text and result_text[-1] != "\n" and chunk_text and chunk_text[0] != "\n": | |
result_text += " " | |
result_text += chunk_text | |
# Пост-обработка результата | |
# Заменяем множественные переносы строк на одиночные | |
result_text = re.sub(r'\n+', '\n', result_text) | |
# Заменяем множественные пробелы на одиночные | |
result_text = re.sub(r' +', ' ', result_text) | |
# Убираем пробелы перед переносами строк | |
result_text = re.sub(r' +\n', '\n', result_text) | |
# Убираем пробелы после переносов строк | |
result_text = re.sub(r'\n +', '\n', result_text) | |
# Убираем лишние переносы строк в начале и конце текста | |
result_text = result_text.strip() | |
return result_text |