diff --git a/History/2026-07-13-sonnet-query-obfuscation-tokens.md b/History/2026-07-13-sonnet-query-obfuscation-tokens.md new file mode 100644 index 0000000..de3f2c3 --- /dev/null +++ b/History/2026-07-13-sonnet-query-obfuscation-tokens.md @@ -0,0 +1,114 @@ +# Запрос к Sonnet: анализ обфускации + +**Дата:** 2026-07-13 + +--- + +**Задача:** Найти причину расхождения между ожидаемыми токенами и реальными заменами. + +## Ожидаемое поведение + +`_next_token()` в `drhider/scanner.py` генерирует токены формата: +- `Технология_0001`, `Прогресс_0002` (для компаний) +- `+7_000_000_0001` (для телефонов) +- `email_0001` (для email) +- `ИНН_0001` (для ИНН) +- `Иванов_0001` (для ФИО) + +## Реальный результат — `TMP/mapping.csv` + +``` +тип_данных,оригинал,замена +phone,+7 (495) 789-41-35,+7 (495) 906-87-80 ← НЕ токен, реальный номер +email,info@nubes.ru,ypiorej@company.local ← НЕ токен, реальный email +company,ЗАО ****XXX****001****,АО «Прогресс» ← НЕ токен, реальное название +company,ЗАО XXX001,ООО «Альянс» ← НЕ токен, реальное название +inn_ul,ИНН 9706005293,ИНН 1846691249 ← НЕ токен, реальный ИНН +kpp,КПП 772401001,КПП 350443068 ← НЕ токен, реальный КПП +ks,Кор/сч 30101810400000000225,Кор/сч 30101201490272090211 ← НЕ токен +ogrn,ОГРН 1207700098759,ОГРН 1048672318430 ← НЕ токен +company,ООО "НУБЕС",ООО «Спектр» ← НЕ токен +text,Исполнителем Заказчику Сторонами,Кузнецов О.В. +text,"Обязанности Заказчика\nСвоевременно",Степанов А.В. +text,"Обязанности Исполнителя\nОказывать",Петров П.Е. +text,"Ответственность Заказчика\nЗаказчик",Новиков А.М. +text,"Ответственность Исполнителя\nИсполнитель",Попов О.М. +company,ПАО Сбербанк,АО «Формат» +``` + +**Ни одного токена формата `XXX_0000` в колонке «замена».** + +## Реальный результат — `TMP/договор-XXX001-03700_obfuscated.md` (первые строки) + +```markdown +**АО «Прогресс»** ... и **ООО **"**НУБЕС**" ... Новиков И.В. ... +``` + +- `Новиков И.В.` — НЕ заменён (должен быть `Иванов_0001`) +- `ООО "НУБЕС"` — НЕ заменён в тексте (есть в mapping но замена не применена?) +- `г. Москва, 1-я Стекольная 7с5` — адрес не заменён + +## Файлы для анализа + +**Обязательно прочитать:** +1. `drhider/scanner.py` — `_next_token()`, `scan_regex()`, `scan_llm_ner()`, TYPE_POOLS, промпт LLM (строки 109-151) +2. `drhider/obfuscator.py` — порядок вызова regex → LLM, как объединяется mapping (строки 63-95) +3. `drhider/config.py` — ENTITY_PATTERNS, COMPANY_PATTERN, PERSON_PATTERN +4. `drhider/llm_client.py` — `LLMClient.complete()` + +**Прочитать для контекста:** +5. `TMP/mapping.csv` — полный результат +6. `TMP/договор-XXX001-03700_obfuscated.md` — обфусцированный файл +7. `TMP/примеры_договоров_для_ИИ/договор-XXX001-03700.docx` — оригинал (для сверки адресов/имён) + +**Не лезть:** `builder.py`, `extractor.py`, `replacer.py`, `session.py`, `templates/`, docs/, History/. + +## Ключевые точки для проверки + +### 1. `scanner.py` — `_next_token()` (стр. 63-82) + +```python +def _next_token(entity_type, counters): + pool, prefix_key = TYPE_POOLS.get(entity_type, _FALLBACK_POOL) + template = random.choice(pool) + key = f"{prefix_key}_{template}" + counters[key] = counters.get(key, 0) + 1 + return f"{template}_{counters[key]:04d}" +``` + +Возвращает `Технология_0001`, `+7_000_000_0001`. **Никак не может вернуть** `АО «Прогресс»` или `+7 (495) 906-87-80`. + +### 2. `scanner.py` — `scan_regex()` (стр. 89-108) + +```python +mapping[original] = _next_token(entity_type, counters) +``` + +Всегда вызывает `_next_token`. Результат должен быть токеном. + +### 3. `scanner.py` — `scan_llm_ner()` (стр. 109-179) + +```python +mapping[val] = _next_token(ent_type, counters) +``` + +Тоже вызывает `_next_token`. Результат должен быть токеном. + +### 4. `obfuscator.py` — порядок вызова (стр. 86-92) + +```python +scanner.scan_regex(text, self._mapping, self._counters) # сначала +scanner.scan_llm_ner(all_texts, self._mapping, ...) # потом +``` + +### 5. `config.py` — regex-паттерны: + +- `phone`: `(?:\+7|8)[\s\-]?\(?\d{3}\)?...` — должно матчить `+7 (495) 789-41-35` +- `email`: `[a-zA-Z0-9._%+-]+@...` — должно матчить `info@nubes.ru` +- `inn_ul`: `ИНН\s*\d{10}` — должно матчить `ИНН 9706005293` +- `COMPANY_PATTERN`: `(?:ООО|ЗАО|...)\s+(?:«[^»]+»|"[^"]+"|...)` — должно матчить `ООО "НУБЕС"` и `ЗАО "XXX001"` +- `PERSON_PATTERN`: `[А-Я][а-я]+\s+[А-Я]\.[А-Я]\.` — должно матчить `Новиков И.В.` + +## Главный вопрос + +Каждый путь (regex и LLM) вызывает `_next_token()`. `_next_token()` физически не может выдать `АО «Прогресс»` или `+7 (495) 906-87-80`. Откуда в `mapping.csv` берутся реалистичные замены? Кто и где их генерирует В ОБХОД `_next_token()`?