feat(sprint2.5): чистка чанков и переиндексация
Чанкер тащил в базу markdown-мусор: навигационные блоки «Вернуться на:»
со списками ссылок, инлайн-ссылки [текст](url) в теле, служебные
пометки _Источник: .../file.md_, лишние пустые строки. Всё это ело
контекст LLM и засоряло правую панель отладки.
- services/text_cleanup: clean_markdown_text — удаляет навигационные
строки, строки-только-ссылки (обычно это меню), служебные _Источник:_,
раскрывает инлайн-ссылки [x](url) → x, сжимает 3+ переносов до 2.
- services/document_processor: process_document теперь возвращает
(id, raw_text, sections, chunks); чистку применяем к заголовкам и
телам секций; чанки короче 20 символов выбрасываем с пересчётом
индексов. Вспомогательная rechunk_raw_text — для переиндексации.
Чтобы переиндексировать без повторной загрузки файла, нужен исходный
текст. Вводим отдельный слой:
- новая таблица SQLite documents (id, name, file_type, raw_text,
created_at, updated_at) + миграция Alembic 7ee7296ccd6d.
- db/models/Document + регистрация в db.models.__init__.
- services/document_service: save/get/list/delete для raw_text.
- routers/documents.upload: сохраняет raw_text в SQLite перед
индексацией в Chroma; delete убирает и из SQLite, и из Chroma.
- Новые эндпоинты POST /documents/{id}/reindex и
POST /documents/reindex-all — берут raw_text из SQLite, пропускают
через rechunk_raw_text, заменяют чанки в Chroma.
Существующие 4 документа были перезалиты вручную (решение: не делать
одноразовый backfill, проще залить заново). Старая Chroma очищена,
новые чанки прошли через чистку — мусор ушёл.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
"""Чистка wiki-текстов от навигационного и служебного markdown-мусора."""
|
||||
import re
|
||||
|
||||
RETURN_TO_RE = re.compile(r"^\*\*\s*Вернуться на\s*:?\s*\*\*\s*:?$")
|
||||
LINK_ONLY_RE = re.compile(r"^\[[^\]\n]+\]\([^\)\n]+\)$")
|
||||
SOURCE_NOTE_RE = re.compile(r"^_Источник\s*:.*_$")
|
||||
INLINE_LINK_RE = re.compile(r"\[([^\]\n]+)\]\([^\)\n]+\)")
|
||||
MULTI_BLANK_RE = re.compile(r"\n{3,}")
|
||||
|
||||
|
||||
def clean_markdown_text(text: str) -> str:
|
||||
"""Удаляет навигационный мусор и раскрывает инлайн-ссылки.
|
||||
|
||||
Правила:
|
||||
- Строка `**Вернуться на:**` — выбрасывается.
|
||||
- Строка, целиком состоящая из markdown-ссылки `[x](url)` — выбрасывается (это навигация).
|
||||
- Строка `_Источник: .../file.md_` — выбрасывается.
|
||||
- Инлайн-ссылки в теле `[текст](url)` заменяются на `текст`.
|
||||
- 3+ подряд переносов строк сжимаются до 2.
|
||||
"""
|
||||
if not text:
|
||||
return ""
|
||||
|
||||
lines = text.split("\n")
|
||||
cleaned_lines = []
|
||||
for line in lines:
|
||||
stripped = line.strip()
|
||||
if RETURN_TO_RE.match(stripped):
|
||||
continue
|
||||
if LINK_ONLY_RE.match(stripped):
|
||||
continue
|
||||
if SOURCE_NOTE_RE.match(stripped):
|
||||
continue
|
||||
cleaned_lines.append(line)
|
||||
|
||||
text = "\n".join(cleaned_lines)
|
||||
text = INLINE_LINK_RE.sub(r"\1", text)
|
||||
text = MULTI_BLANK_RE.sub("\n\n", text)
|
||||
return text.strip()
|
||||
Reference in New Issue
Block a user