# 2026-08-20 — Вопрос-ответ по LLM-чанкингу (Q&A) Контекст: сервис обфускации, двухступенчатый детект ПДн (regex + LLM). Пользователь хочет, чтобы LLM обрабатывал ВСЕ данные, а не урезку 8000 символов. Обсуждение с Sonnet: основной вопрос + 6 уточнений. Предыдущие файлы: - History/2026-08-20-sonnet-query-llm-pattern.md — рекомендуемая схема - History/2026-08-20-sonnet-query-llm-followup.md — уточнения перед внедрением --- ## Исходная проблема `scan_llm_ner` (drhider/scanner.py) обрезал: - каждый файл до первых 3000 символов (`t[:3000]`); - всё вместе до 8000 символов (`combined[:8000]`); - один вызов LLM на весь набор. Итог: при 299 файлах LLM «видел» только ~8000 символов (~0.1–0.3% данных). Пользователь: «всё затевалось чтобы ЛЛМ ВСЁ обрабатывал». → убрать урезку. ## Рекомендуемая схема (Sonnet, основной ответ) - Отказаться от глобального батчинга → «один файл = один или несколько вызовов LLM», параллельно. - Чанкинг per-file: чанк 6000 символов, overlap 400–500 символов. - Дедупликация по файлу + верификация (найденная строка реально в тексте → отсекает галлюцинации). - Батчинг мелких файлов — опционально, второй шаг. ## Уточнения (У.1–У.6) и ответы Sonnet ### У.1 — Алгоритм разбивки на чанки Приоритет границ: `\n\n` → `\n` → `. ` → `? ` → `! ` → `; ` → `, ` → ` ` (пробел — крайний). Ищем ближайшую границу с конца в диапазоне `[size//2 .. size]`. Жёсткий разрез — только если нет ни одного пробела. Overlap: отступить назад на overlap, найти начало слова. Псевдокод: ```python BOUNDARIES = ['\n\n', '\n', '. ', '? ', '! ', '; ', ', ', ' '] def split_into_chunks(text, size=6000, overlap=500): chunks=[]; start=0 while start < len(text): end=min(start+size, len(text)) if end==len(text): chunks.append(text[start:]); break cut=None for b in BOUNDARIES: pos=text.rfind(b, start+size//2, end) if pos!=-1: cut=pos+len(b); break if cut is None: cut=end chunks.append(text[start:cut]) ov=max(start, cut-overlap) space=text.find(' ', ov) start=(space+1) if (space!=-1 and space3× от базового — снижать). --- ## Итоговое решение (для внедрения, ждёт «делай») 1. `scanner.py scan_llm_ner`: убрать `[:3000]`/`[:8000]`; по каждому файлу из `all_texts` разбить на чанки (6000/500, split_into_chunks); параллельные вызовы (ThreadPool, concurrency 4, крупные вперёд); для каждого чанка — полный промпт + «regex-найденные»; собрать сущности, normalize-дедуп, verify против полного текста файла, в mapping. 2. Добавить хелперы split_into_chunks / normalize_entity / verify в scanner.py. 3. Не дублировать regex-найденное; считать токены/время LLM корректно (llm_active/elapsed). 4. Прогнать тест на малом наборе (не прод): сколько сущностей добавит LLM, время. Статус: НЕ внедрено (ждёт «делай»). Версия при внедрении — v0.0.57.