lsdf commited on
Commit
1ee9ad2
·
1 Parent(s): 270367c

Expand full functional documentation with algorithmic details.

Browse files

Rewrite the documentation as an implementation-grade reference covering architecture, API contracts, module-level function logic, formulas, optimizer decision rules, frontend workflows, and reproducibility guidance.

Made-with: Cursor

Files changed (1) hide show
  1. docs/FULL_FUNCTIONAL_DOCUMENTATION.md +450 -205
docs/FULL_FUNCTIONAL_DOCUMENTATION.md CHANGED
@@ -1,317 +1,562 @@
1
- # SEO AI Editor — Полная документация функционала и логики
2
 
3
- Документ описывает текущее состояние проекта целиком: архитектуру, API, логику расчётов, фронтенд-сценарии, сохранение проектов и особенности деплоя.
4
 
5
  ---
6
 
7
- ## 1) Назначение системы
8
 
9
- Приложение объединяет два больших контура:
10
 
11
- 1. **SEO-анализ текста** (`/analyze`)
12
- - N-граммы (1-4)
13
- - BM25-рекомендации (add/remove/ok)
14
- - BERT-семантика
15
  - Word Count (total/significant)
16
- - Title analyzer
17
-
18
- 2. **Semantic Core** (`/api/v1/semantic/*`)
19
- - Семантический граф понятий
20
- - Веса узлов/связей 1..100
21
- - Гипертекстовая разметка
22
- - Реферат
23
- - Смысловой поиск (по словам и фразам)
24
- - Сравнение с конкурентами
 
 
 
 
 
 
 
 
 
 
25
 
26
  ---
27
 
28
- ## 2) Текущая структура проекта
29
 
30
- - `app.py` — FastAPI entrypoint, роутинг, orchestration.
31
- - `logic.py` — основная SEO-логика (spaCy, n-grams, BM25, BERT, Title).
32
- - `models.py` — Pydantic-модели запросов/ответов.
33
- - `nlp_processor.py` — разбор текста для Semantic Core.
34
- - `semantic_graph.py` — построение semantic graph, веса и связи.
35
- - `highlighter.py` — разметка текста по весам узлов.
36
- - `summarizer.py` — реферирование.
37
- - `search.py` — смысловой поиск.
38
- - `templates/index.html` — весь frontend (UI + JS).
39
- - `requirements.txt`, `Dockerfile`.
 
40
 
41
  ---
42
 
43
  ## 3) Поддерживаемые языки
44
 
45
- Коды языков:
46
- - `ru`, `en`, `de`, `es`, `it`, `pl`
47
 
48
- Модели spaCy задаются в `logic.py` через `MODEL_NAMES`.
49
 
50
  ---
51
 
52
- ## 4) Backend API ктуально)
53
 
54
- ## 4.1 `POST /analyze` (SEO pipeline)
55
 
56
- Вход (`AnalysisRequest`):
57
- - `target_text`
58
- - `competitors[]`
59
- - `keywords[]`
60
- - `language`
61
- - `target_title`
62
- - `competitor_titles[]`
63
 
64
- Выход (`AnalysisResponse`):
 
 
 
 
 
 
 
 
65
  - `ngram_stats`
66
  - `bm25_recommendations`
67
  - `bert_analysis`
68
  - `word_counts`
69
  - `title_analysis`
70
 
71
- ### Внутренний пайплайн
72
- 1. `count_words()` для target/competitors.
73
- 2. `calculate_ngram_stats()`.
74
- 3. `parse_keywords()` + `calculate_bm25_recommendations()`.
75
- 4. `perform_bert_analysis()`.
76
- 5. `analyze_title()`.
77
 
78
  ---
79
 
80
  ## 4.2 `POST /api/v1/semantic/analyze`
81
 
82
- Вход (`SemanticAnalyzeRequest`):
83
- - `text`
84
- - `competitors[]`
85
- - `language`
86
- - `threshold` (порог подсветки)
87
- - `compression_ratio` (доля реферата)
88
-
89
- Выход (`SemanticAnalyzeResponse`):
90
- - `target` полный semantic результат по target документу
91
- - `competitors[]` — результаты по каждому конкуренту
92
- - `comparison` — сравнительные агрегаты:
 
 
 
 
 
 
 
 
 
93
  - `target_nodes`, `target_links`
94
  - `avg_comp_nodes`, `avg_comp_links`
95
  - `num_competitors`
96
- - `term_power_table` (сравнение терминов слово+фраза)
 
 
 
 
 
 
 
 
 
97
 
98
  ---
99
 
100
  ## 4.3 `POST /api/v1/semantic/search`
101
 
102
- Вход (`SemanticSearchRequest`):
 
 
 
103
  - `query_text`
104
  - `text`
105
  - `language`
106
  - `top_n`
107
 
108
- Выход (`SemanticSearchResponse`):
109
- - `results[]` с полями:
110
- - `lemma`
111
- - `score` (1..100)
112
- - `type` (`word` / `phrase`)
113
 
114
  ---
115
 
116
- ## 5) Подробно по модулям и формулам
117
-
118
- ## 5.1 `logic.py` (SEO контур)
119
-
120
- ### Ключевые функции
121
- - `load_model_if_missing(lang)` — lazy load spaCy.
122
- - `get_doc(text, lang)` spaCy Doc.
123
- - `is_valid_token(t)` фильтр полезных токенов.
124
- - `get_lemmas_flat(text, lang)` плоские леммы.
125
- - `generate_ngrams_safe(text, lang, n)` — Smart Window:
126
- - N считается по значимым словам,
127
- - стоп-слова внутри фразы сохраняются,
128
- - стенки (punct/num/sym) режут фразу.
129
- - `count_words(text, lang)` — total/significant.
130
- - `calculate_ngram_stats(...)` — 1..4 граммы + per-competitor детали.
131
- - `calculate_bm25_recommendations(...)` — BM25 на n-grams, mirror principle.
132
- - `perform_bert_analysis(...)` — semantic similarity по chunks.
133
- - `analyze_title(...)` — title длина/ngrams/coverage/bert.
134
-
135
- ### BM25 (в текущей реализации)
136
- - ключевые фразы декомпозируются в 1/2/3-граммы через ту же функцию, что и корпус;
137
- - score target сравнивается со средним score competitors;
138
- - action:
139
- - `add`, если target заметно ниже competitors,
140
- - `remove`, если заметно выше,
141
- - `ok` иначе.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  ---
144
 
145
  ## 5.2 `nlp_processor.py`
146
 
147
- `preprocess_text(text, lang)`:
148
- - разбивает на предложения;
149
- - сохраняет токены:
150
- - `text`, `whitespace`, `lemma`, `is_significant`, `is_punct`, `is_space`;
151
- - возвращает список предложений с:
152
- - `raw_text`, `tokens`, `lemmas_clean`.
153
 
154
- Назначение: не терять исходное форматирование для UI, но иметь нормализованные данные для math-core.
155
 
156
  ---
157
 
158
- ## 5.3 `semantic_graph.py` емантическое ядро)
159
 
160
- ### Текущие принципы
161
- 1. Узлы: **слова + устойчивые фразы**.
162
- 2. Связи: направленные, локальное окно, асимметрия.
163
- 3. Вес связи:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  - `P(B|A) = cooc(A,B) / occ(A) * 100`
165
- - принудительное ограничение в диапазон `0..100`.
166
- 4. Вес узла:
167
- - PageRank + connectivity factor,
168
- - termness-буст для фраз,
169
- - IDF-подобный фактор по охвату предложений,
170
- - penalty для слишком общих доменных терминов.
171
-
172
- ### Дополнительные механики
173
- - фильтр шумных предложений (`NOISE_PATTERNS`, короткие CTA),
174
- - каноникализация терминов (`_canonicalize_term`),
175
- - извлечение фраз через `generate_ngrams_safe`.
 
 
 
 
176
 
177
  ---
178
 
179
  ## 5.4 `highlighter.py`
180
 
181
- `generate_markup_for_frontend(...)`:
182
- - подсвечивает токены/блоки, если их вес >= threshold;
183
- - соседние значимые токены склеиваются в один link-block:
184
- - `text`
185
- - `lemmas[]`
186
- - `weight`
187
 
188
  ---
189
 
190
  ## 5.5 `summarizer.py`
191
 
192
- `generate_summary(...)`:
193
- - score предложения:
194
- - `sum(weight(unique_lemmas)) / sqrt(token_count)`
195
- - отбор top по `compression_ratio`;
196
- - возврат в хронологическом порядке.
 
 
 
197
 
198
  ---
199
 
200
  ## 5.6 `search.py`
201
 
202
- Текущая логика:
203
- 1. Нормализация запроса.
204
- 2. Поиск по фразам (tri/bi) как приоритет.
205
- 3. Затем fallback по леммам-словам.
206
- 4. Расширение соседями графа.
207
- 5. Нормализация в `1..100`.
208
- 6. Маркировка типа результата: `phrase`/`word`.
 
 
 
 
 
209
 
210
  ---
211
 
212
- ## 6) Frontend: все сценарии
213
 
214
- Файл: `templates/index.html`.
 
215
 
216
- ### Основные зоны
217
- - Левый столбец: ввод данных.
218
- - Правый столбец: вкладки результатов.
219
 
220
- ### Вкладки
221
- - `BERT`
222
- - `BM25`
223
- - `N-grams`
224
- - `Title`
225
- - `Semantic Core`
226
 
227
- ### JS-функции (ключевые)
228
- - `runAnalysis()` запуск `/analyze`.
229
- - `runSemanticAnalysis()` — запуск `/api/v1/semantic/analyze`.
230
- - `runSemanticSearch()` — запуск `/api/v1/semantic/search`.
231
- - `renderResults(...)` — отрисовка SEO вкладок.
232
- - `renderSemanticResults(...)` отрисовка Semantic Core.
233
- - `showNgramTable(...)` — n-gram таблицы.
234
- - `renderTitleResults(...)` Title блоки.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
  ---
237
 
238
- ## 7) Сохранение/загрузка проекта (локально)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
 
240
- Реализовано полностью на фронтенде:
241
- - `saveProject()` — экспорт `.json`;
242
- - `loadProject()` + `applyProjectData(...)` — импорт и восстановление;
243
- - `clearProject()` — сброс до чистого состояния.
244
 
245
- Что сохраняется:
246
- - все input-поля,
247
- - semantic параметры,
248
- - последний `analysis_result`,
249
- - последний `semantic_result`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
  ---
252
 
253
- ## 8) Сравнительные таблицы в Semantic Core
254
 
255
- ## 8.1 Окно 1 (таблично)
256
- - узлы (`Node`, `Weight`, `Freq`)
257
- - связи (`From`, `To`, `P(B|A)`)
 
 
 
258
 
259
- ## 8.2 Таблица мощных терминов
260
- - термин (`word` или `phrase`)
261
- - мой вес
262
- - avg вес конкурентов
263
- - `Freq X/Y`
264
- - `K1..Kn` веса по конкурентам
265
 
266
  ---
267
 
268
- ## 9) Деплой и эксплуатация (HF)
 
 
 
269
 
270
- Текущий SDK: Docker Space.
 
271
 
272
- Практические примечания:
273
- - startup preload всех spaCy моделей отключен (для устойчивости `cpu-basic`);
274
- - были инциденты HF infra:
275
- - `Initialization step 'init' failed`
276
- - `curl: (6) Could not resolve host: huggingface.co`
277
- - это platform-side DNS/egress issue, не Python traceback приложения.
278
 
279
- Рекомендуемая диагностика:
280
- 1. сверять `repo_sha` vs `runtime_sha`,
281
- 2. смотреть `runtime_stage`,
282
- 3. повторный trigger-build (empty commit) при зависании билдера.
283
 
284
  ---
285
 
286
- ## 10) Известные ограничения и roadmap
 
 
 
 
 
 
 
 
 
287
 
288
- ### Ограничения текущей версии
289
- - semantic scoring все еще чувствителен к SEO-шаблонам и доменному шуму;
290
- - каноникализация пока rule-based;
291
- - нет отдельной debug-панели для “веса термина по компонентам”.
292
 
293
- ### Рекомендуемый roadmap
294
- 1. Debugежим для объяснимости веса термина.
295
- 2. Расширение каноникализации (brand/entity map по языкам).
296
- 3. Настраиваемые stop/penalty-листы по доменам.
297
- 4. Более строгий phrase-mining с устойчивостью по документам.
298
- 5. UI-фильтры в таблицах терминов олько phrase, только gap против competitors).
299
 
300
  ---
301
 
302
- ## 11) Быстрый чек-лист для валидации после изменений
303
 
304
- 1. `python -m py_compile app.py logic.py semantic_graph.py search.py`
305
- 2. Проверка lints измененных файлов.
306
- 3. Smoke API:
307
  - `/analyze`
308
  - `/api/v1/semantic/analyze`
309
  - `/api/v1/semantic/search`
310
- 4. UI:
311
- - вкладки рендерятся,
312
- - поиск показывает результаты рядом с формой,
313
- - сохранение/загрузка проекта работает.
314
- 5. HF:
315
- - `repo_sha == runtime_sha`,
316
- - `runtime_stage == RUNNING`.
 
 
317
 
 
1
+ # SEO AI Editor — исчерпывающая документация функционала, логики и алгоритмики
2
 
3
+ Документ описывает приложение как инженерную спецификацию: что делает каждый модуль, какие данные принимает и возвращает, какие формулы использует, какие ограничения применяет и как воспроизвести поведение системы без чтения исходного кода.
4
 
5
  ---
6
 
7
+ ## 1) Концепция приложения
8
 
9
+ `SEO AI Editor` объединяет два аналитических контура и один контур улучшения текста:
10
 
11
+ 1. **SEO-контур** (`POST /analyze`)
 
 
 
12
  - Word Count (total/significant)
13
+ - N-gram анализ (1..4)
14
+ - BM25-рекомендации (`add/remove/ok`)
15
+ - BERT-семантика по ключам
16
+ - Title-анализ (length/ngrams/coverage/BERT)
17
+
18
+ 2. **Semantic Core** (`POST /api/v1/semantic/analyze`, `POST /api/v1/semantic/search`)
19
+ - NLP-разбор и лемматизация
20
+ - семантический граф (слова + фразы)
21
+ - веса узлов и связей в шкале `1..100`
22
+ - гипертекстовая разметка
23
+ - реферат
24
+ - смысловой поиск по словам и фразам
25
+ - сравнение с конкурентами (включая таблицу мощных терминов)
26
+
27
+ 3. **LLM Optimizer** (`POST /api/v1/optimizer/run`)
28
+ - итеративная локальная оптимизация текста
29
+ - многокритериальный скоринг с защитой от деградации
30
+ - каскад уровней правок (от минимальных к более широким)
31
+ - детализированный debug-лог по кандидатам
32
 
33
  ---
34
 
35
+ ## 2) Архитектура и ответственность файлов
36
 
37
+ - `app.py` — FastAPI оркестратор, endpoint-ы, связывание модулей.
38
+ - `models.py` — Pydantic-модели входов/выходов.
39
+ - `logic.py` — SEO-ядро: токены, n-grams, BM25, BERT, Title.
40
+ - `nlp_processor.py` — NLP-предобработка для semantic-контура.
41
+ - `semantic_graph.py` — построение графа и вычисление смысловых весов.
42
+ - `highlighter.py` — разметка текста по semantic-весам.
43
+ - `summarizer.py` — генерация реферата.
44
+ - `search.py` — смысловой поиск в графе (фразы + слова).
45
+ - `url_fetcher.py` — извлечение текста/title из URL с выбором user-agent.
46
+ - `optimizer.py` — LLM-оптимизация с обратной связью от метрик.
47
+ - `templates/index.html` — frontend (UI + клиентская логика JS).
48
 
49
  ---
50
 
51
  ## 3) Поддерживаемые языки
52
 
53
+ Поддерживаемые языки анализа:
54
+ - `ru`, `en`, `de`, `es`, `it`, `pl`, `pt`
55
 
56
+ Языки задаются кодом и сопоставляются с spaCy-моделями в `logic.py` (`MODEL_NAMES`).
57
 
58
  ---
59
 
60
+ ## 4) Backend API и контракты
61
 
62
+ ## 4.1 `POST /analyze`
63
 
64
+ ### Назначение
65
+ Комплексный SEO-анализ target-текста относительно конкурентов и ключевых фраз.
 
 
 
 
 
66
 
67
+ ### Вход (`AnalysisRequest`)
68
+ - `target_text: str`
69
+ - `competitors: List[str]`
70
+ - `keywords: List[str]`
71
+ - `language: str`
72
+ - `target_title: str`
73
+ - `competitor_titles: List[str]`
74
+
75
+ ### Выход (`AnalysisResponse`)
76
  - `ngram_stats`
77
  - `bm25_recommendations`
78
  - `bert_analysis`
79
  - `word_counts`
80
  - `title_analysis`
81
 
82
+ ### Оркестрация в `app.py`
83
+ 1. Word counts (`count_words`) для target и каждого competitor.
84
+ 2. N-gram статистика (`calculate_ngram_stats`).
85
+ 3. Нормализация ключей (`parse_keywords`) и BM25 (`calculate_bm25_recommendations`).
86
+ 4. BERT-анализ (`perform_bert_analysis`).
87
+ 5. Title-анализ (`analyze_title`) если `target_title` не пустой.
88
 
89
  ---
90
 
91
  ## 4.2 `POST /api/v1/semantic/analyze`
92
 
93
+ ### Назначение
94
+ Построение semantic-среза по target и конкурентам.
95
+
96
+ ### Вход (`SemanticAnalyzeRequest`)
97
+ - `text: str`
98
+ - `competitors: List[str]`
99
+ - `language: str`
100
+ - `threshold: int` (порог подсветки)
101
+ - `compression_ratio: float` (доля предложений в реферате)
102
+
103
+ ### Выход (`SemanticAnalyzeResponse`)
104
+ - `target`:
105
+ - `graph` (`nodes`, `links`)
106
+ - `markup_text`
107
+ - `summary`
108
+ - `top_keywords`
109
+ - `word_weights`
110
+ - `stats`
111
+ - `competitors[]`: тот же формат
112
+ - `comparison`:
113
  - `target_nodes`, `target_links`
114
  - `avg_comp_nodes`, `avg_comp_links`
115
  - `num_competitors`
116
+ - `term_power_table`
117
+
118
+ ### Логика таблицы `term_power_table`
119
+ Для каждого термина из объединения target + competitors:
120
+ - `target_weight`
121
+ - `competitor_avg_weight`
122
+ - `competitor_weights` (`K1..Kn`)
123
+ - `comp_occurrence` (`X` в `X/Y`)
124
+ - `comp_total` (`Y`)
125
+ - `term_type` (`word` или `phrase`)
126
 
127
  ---
128
 
129
  ## 4.3 `POST /api/v1/semantic/search`
130
 
131
+ ### Назначение
132
+ Смысловой поиск по документу через граф.
133
+
134
+ ### Вход (`SemanticSearchRequest`)
135
  - `query_text`
136
  - `text`
137
  - `language`
138
  - `top_n`
139
 
140
+ ### Выход (`SemanticSearchResponse`)
141
+ - `results[]`: `lemma`, `score (1..100)`, `type (word|phrase)`
 
 
 
142
 
143
  ---
144
 
145
+ ## 4.4 URL Import API
146
+
147
+ ### `GET /api/v1/url/user-agents`
148
+ Возвращает список пресетов user-agent для выбора в UI.
149
+
150
+ ### `POST /api/v1/url/fetch`
151
+ Извлекает `title` и основной `text` страницы:
152
+ - вход: `url`, `user_agent`, `timeout_seconds`
153
+ - выход: `ok`, `status_code`, `title`, `text`, `error`, `final_url`, agent-метаданные.
154
+
155
+ Обработка ошибок не ломает UI: endpoint возвращает `ok=false` и `error`.
156
+
157
+ ---
158
+
159
+ ## 4.5 `POST /api/v1/optimizer/run`
160
+
161
+ ### Назначение
162
+ Итеративная локальная дооптимизация target-текста через LLM.
163
+
164
+ ### Вход (`OptimizerRequest`)
165
+ - аналитические данные: `target_text`, `competitors`, `keywords`, `language`, `target_title`, `competitor_titles`
166
+ - LLM: `api_key`, `api_base_url`, `model`, `temperature`
167
+ - стратегия: `max_iterations`, `candidates_per_iteration`, `optimization_mode`
168
+
169
+ ### Выход (`OptimizerResponse`)
170
+ - `optimized_text`
171
+ - `baseline_metrics`, `final_metrics`
172
+ - `iterations[]` (подробный лог шагов)
173
+ - `applied_changes`
174
+ - `optimization_mode`
175
+ - `error` (если есть)
176
+
177
+ ---
178
+
179
+ ## 5) Подробная алгоритмика по модулям
180
+
181
+ ## 5.1 `logic.py` — SEO-ядро
182
+
183
+ ### `load_model_if_missing(lang)`
184
+ Ленивая загрузка spaCy-модели конкретного языка. Цель: не загружать все модели на старте (критично для HF ресурсов).
185
+
186
+ ### `load_models()`
187
+ Служебная массовая загрузка моделей (используется ограниченно; основной путь в проде — lazy).
188
+
189
+ ### `get_doc(text, lang)`
190
+ Единая точка получения spaCy `Doc` с предобработкой языка/модели.
191
+
192
+ ### `is_valid_token(t)`
193
+ Фильтр значимых токенов (исключает шумовые категории: punctuation/space/часть stop и др.).
194
+
195
+ ### `get_lemmas_flat(text, lang)`
196
+ Плоский список лемм значимых токенов. Базовый строительный блок для метрик.
197
+
198
+ ### `generate_ngrams_safe(text, lang, n)` — Smart Window
199
+ Ключевой принцип:
200
+ - размер окна задается по **значимым** словам;
201
+ - stop-слова внутри валидного окна могут сохраняться для естественных фраз;
202
+ - символные границы (punct/num/sym) не дают сшивать ложные фразы.
203
+
204
+ Это гарантирует более естественные n-grams и согласованность между разными подсистемами.
205
+
206
+ ### `count_words(text, lang)`
207
+ Возвращает:
208
+ - `total` — количество словоформ
209
+ - `significant` — количество значимых токенов после фильтра
210
+
211
+ ### `calculate_ngram_stats(target_text, competitor_texts, lang)`
212
+ Строит частотные словари 1..4-грамм, агрегирует:
213
+ - частоты target
214
+ - средние частоты competitors
215
+ - сигналы дефицита/избытка
216
+ - детализацию по каждому конкуренту (для интерфейсных таблиц)
217
+
218
+ ### `parse_keywords(raw_phrases, lang)`
219
+ Нормализует сырые ключи пользователя в:
220
+ - фразовые ключи
221
+ - униграммы
222
+ с учетом текущего языка и лемматизации.
223
+
224
+ ### `calculate_bm25_recommendations(...)` — Mirror Principle
225
+ BM25 использует тот же подход токенизации/фразогенерации, что и n-gram ядро.
226
+ Смысл:
227
+ - сравнить релевантность target и среднего competitor-профиля по тем же термам;
228
+ - выдать действие:
229
+ - `add` — недобор терма,
230
+ - `remove` — вероятный переспам,
231
+ - `ok` — баланс.
232
+
233
+ ### `get_bert_model()`
234
+ Ленивая инициализация sentence-transformers модели.
235
+
236
+ ### `perform_bert_analysis(target_text, competitor_texts, key_phrases, lang)`
237
+ Для каждой ключевой фразы:
238
+ - ищет наиболее близкие чанки текста;
239
+ - считает similarity для target и competitors;
240
+ - формирует детализацию (`my_max_score`, competitor-сравнение, статусы).
241
+
242
+ ### `analyze_title(target_title, competitor_titles, raw_keywords, lang)`
243
+ Оркестратор Title-пайплайна:
244
+ - `_title_length`
245
+ - `_title_ngrams`
246
+ - `_title_keyword_coverage`
247
+ - `_title_bert`
248
+
249
+ #### `_title_length(...)`
250
+ Сравнивает длину target title с конкурентным диапазоном/средним.
251
+
252
+ #### `_title_ngrams(...)`
253
+ N-gram сопоставление title-уровня.
254
+
255
+ #### `_title_keyword_coverage(...)`
256
+ Проверяет покрытие пользовательских ключей в target и competitor title.
257
+
258
+ #### `_title_bert(...)`
259
+ Оценивает semantic-близость title к ключевому набору.
260
 
261
  ---
262
 
263
  ## 5.2 `nlp_processor.py`
264
 
265
+ ### `preprocess_text(text, lang)`
266
+ Преобразует текст в структуру предложений:
267
+ - `raw_text`
268
+ - `tokens[]` с полями `text`, `whitespace`, `lemma`, `is_significant`, `is_punct`, `is_space`
269
+ - `lemmas_clean` (очищенный список лемм)
 
270
 
271
+ Критично: сохранение `whitespace` и исходных токенов позволяет восстановить текст UI-послойно без потери форматирования.
272
 
273
  ---
274
 
275
+ ## 5.3 `semantic_graph.py` — математическое ядро
276
 
277
+ ### `_normalize_to_1_100(values)`
278
+ Нормализация произвольных весов в целочисленную шкалу `1..100`.
279
+
280
+ ### `_extract_significant_lemmas(sent)`
281
+ Достает значимые леммы из предложения.
282
+
283
+ ### `_is_noise_sentence(text)`
284
+ Отбрасывает шумовые фрагменты (короткие CTA, boilerplate-паттерны).
285
+
286
+ ### `_canonicalize_term(term)`
287
+ Rule-based каноникализация термов (снижение дублей и вариативности).
288
+
289
+ ### `_extract_phrase_candidates(sentence_text, lang)`
290
+ Извлечение кандидатных фраз через `generate_ngrams_safe` и фильтры.
291
+
292
+ ### `_normalize_lemma_sequence(lemmas)`
293
+ Нормализация последовательностей лемм для устранения артефактов.
294
+
295
+ ### `build_semantic_graph(sentences_data, lang)`
296
+ Базовые шаги:
297
+ 1. Сформировать множество терминов (слова + фразы).
298
+ 2. Подсчитать частоты терминов и совместные появления.
299
+ 3. Построить направленный граф.
300
+ 4. Рассчитать вес ребра:
301
  - `P(B|A) = cooc(A,B) / occ(A) * 100`
302
+ - затем ограничение в `0..100`.
303
+ 5. Рассчитать важность узлов:
304
+ - PageRank как глобальная связность,
305
+ - termness/coverage корректировки,
306
+ - штрафы для слишком общих доменных токенов.
307
+ 6. Вернуть граф и карту `word_weights`.
308
+
309
+ ### `get_graph_data_for_frontend(graph, top_edges_per_node=8)`
310
+ Сериализует `networkx` граф в плоский JSON:
311
+ - `nodes[]`
312
+ - `links[]`
313
+ с ограничением числа ребер на узел для управляемого рендера.
314
+
315
+ ### `get_top_keywords(node_weights, top_n=20)`
316
+ Возвращает top-N терминов по весу.
317
 
318
  ---
319
 
320
  ## 5.4 `highlighter.py`
321
 
322
+ ### `generate_markup_for_frontend(sentences_data, word_weights, threshold=50)`
323
+ Маркирует важные блоки:
324
+ - если вес леммы/фразы >= порога, блок становится `is_link=true`;
325
+ - соседние значимые токены могут объединяться в один кликабельный сегмент;
326
+ - во��вращается структура, удобная для реактивного рендера в UI.
 
327
 
328
  ---
329
 
330
  ## 5.5 `summarizer.py`
331
 
332
+ ### `generate_summary(sentences_data, word_weights, compression_ratio)`
333
+ Скоринг предложения:
334
+ - `score = sum(weight(unique_lemmas)) / sqrt(token_count)`
335
+
336
+ Далее:
337
+ 1. сортировка по score убыв.
338
+ 2. выбор top по `compression_ratio`
339
+ 3. восстановление хронологического порядка для читабельности.
340
 
341
  ---
342
 
343
  ## 5.6 `search.py`
344
 
345
+ ### `_normalize_query_text(text)`
346
+ Нормализует запрос для устойчивого поиска.
347
+
348
+ ### `semantic_search(query_text, G, word_weights, language, top_n)`
349
+ Алгоритм:
350
+ 1. Нормализовать и лемматизировать запрос.
351
+ 2. Приоритетно проверить фразы (tri/bi) из запроса.
352
+ 3. Fallback на слова.
353
+ 4. Для найденных точек входа добавить соседей по графу.
354
+ 5. Собрать score из силы связи и веса узла.
355
+ 6. Нормализовать score в `1..100`.
356
+ 7. Вернуть top-N и тип (`phrase`/`word`).
357
 
358
  ---
359
 
360
+ ## 5.7 `url_fetcher.py`
361
 
362
+ ### `get_user_agent_presets()`
363
+ Возвращает список пресетов (Googlebot, Bingbot, ChatGPT user-agent, GPTBot, Chrome Desktop и др.).
364
 
365
+ ### `_normalize_whitespace(text)`
366
+ Схлопывает лишние пробелы/переводы строк.
 
367
 
368
+ ### `_normalize_url(url)`
369
+ Приводит URL к валидному виду (схема, trimming).
 
 
 
 
370
 
371
+ ### `_resolve_user_agent(user_agent_key)`
372
+ По ключу выбирает фактическую строку user-agent.
373
+
374
+ ### `_extract_main_text_and_title(html)`
375
+ HTML extraction pipeline:
376
+ - удалить `script/style/noscript/nav/footer/header/form/svg` и прочий boilerplate;
377
+ - приоритетно извлекать `article/main`;
378
+ - fallback на абзацы/списки;
379
+ - final fallback на `body` текст;
380
+ - вернуть очищенный `title` и основной `text`.
381
+
382
+ ### `fetch_url_content(url, user_agent_key, timeout_seconds)`
383
+ Выполняет HTTP-запрос и возвращает структурированный результат для UI/API.
384
+
385
+ ---
386
+
387
+ ## 5.8 `optimizer.py` — LLM-оптимизация текста
388
+
389
+ ### Цель модуля
390
+ Итеративно улучшать конкретные проблемные зоны из аналитики, избегая полной перегенерации текста и сохраняя стиль/повествование.
391
+
392
+ ### Служебные функции подготовки
393
+ - `_tokenize` — токенизация строки.
394
+ - `_filter_stopwords` — удаление stop-слов.
395
+ - `_split_sentences` — сегментация на предложения.
396
+ - `_max_sentences_for_level` — лимиты длины кандидата по каскаду.
397
+ - `_validate_candidate_text` — pre-check качества (пустота, дубль слова/сущности, подозрительные токен-склейки, превышение лимита предложений).
398
+
399
+ ### Снимки аналитики
400
+ - `_build_analysis_snapshot` — пересчет `/analyze` локально.
401
+ - `_build_semantic_snapshot` — пересчет semantic среза локально.
402
+
403
+ ### Скоринг и выбор цели
404
+ - `_compute_metrics` — единый набор метрик состояния:
405
+ - composite score
406
+ - `bert_low_count`
407
+ - `bert_phrase_scores`
408
+ - `bm25_remove_count`
409
+ - сигналы n-gram/semantic
410
+ - `title_bert_score`
411
+ - `_choose_optimization_goal` — выбирает приоритетную проблему.
412
+ - `_choose_sentence_idx` — выбирает релевантный чанк для правки.
413
+
414
+ ### Генерация кандидатов
415
+ - `_llm_edit_chunk` — отправляет structured prompt в OpenAI-compatible API.
416
+ - учитывает `cascade_level` и тип операции (`rewrite`/`insert`)
417
+ - явно требует грамматически корректный и естественный текст
418
+ - ограничивает число предложений по уровню
419
+
420
+ ### Применение правок
421
+ - `_replace_span` — замена диапазона предложений.
422
+ - `_insert_after` — вставка после диапазона.
423
+
424
+ ### Принятие/отклонение кандидата
425
+ - `_goal_improved`:
426
+ - для BERT: улучшение score целевой фразы минимум на `0.02` **или** снижение `bert_low_count`;
427
+ - для других целей: профильные метрики улучшения.
428
+ - `_is_candidate_valid`:
429
+ - hard constraints (не ухудшать критичные метрики сверх допустимого);
430
+ - режимы `conservative/balanced/aggressive` задают пороги регрессии;
431
+ - решение учитывает и `goal_improved`, и общий `delta_score`.
432
+
433
+ ### Главная функция `optimize_text`
434
+ Итерационный цикл:
435
+ 1. baseline metrics.
436
+ 2. выбрать goal.
437
+ 3. выбрать чанк и операцию каскада.
438
+ 4. сгенерировать `N` кандидатов.
439
+ 5. pre-validation.
440
+ 6. full re-score каждого кандидата.
441
+ 7. выбрать лучший валидный.
442
+ 8. применить или отклонить шаг с причиной.
443
+ 9. при серии неудач эскалировать каскад (`L1 -> L2 -> L3 -> L4`), при успехе сбрасывать на `L1`.
444
+ 10. вести подробный лог по каждому кандидату.
445
 
446
  ---
447
 
448
+ ## 6) Frontend (`templates/index.html`) — сценарии и функции
449
+
450
+ ## 6.1 Ввод данных и URL import
451
+ - `loadUserAgentOptions` — загрузка пресетов UA.
452
+ - `fetchUrlPayload` — запрос к URL API.
453
+ - `fetchTargetFromUrl` — заполнение target text/title из URL.
454
+ - `fetchCompetitorsFromUrls` — массовое заполнение competitors.
455
+
456
+ Ручной ввод всегда остается рабочим fallback-сценарием.
457
+
458
+ ## 6.2 Локальное сохранение проекта
459
+ - `saveProject` — экспорт JSON.
460
+ - `loadProject` — загрузка JSON.
461
+ - `applyProjectData` — восстановление полей и результатов.
462
+ - `clearProject` — новый проект/сброс.
463
 
464
+ API-ключ оптимизатора в persist-состояние не сохраняется.
 
 
 
465
 
466
+ ## 6.3 Запуск аналитики и отрисовка
467
+ - `runAnalysis`
468
+ - `runSemanticAnalysis`
469
+ - `runSemanticSearch`
470
+ - `renderResults`
471
+ - `renderSemanticResults`
472
+ - `renderTitleResults`
473
+ - `showNgramTable`
474
+
475
+ ## 6.4 Сводка и оптимизатор
476
+ - `renderActionSummary` — агрегирует рекомендации BERT/BM25/N-grams/Title/Semantic в табличный формат.
477
+ - `runLlmOptimization` — запуск оптимизации.
478
+ - `renderOptimizerResults` — итог и debug-лог по шагам/кандидатам.
479
+ - `applyOptimizedText` — перенос optimized текста в `target_text`.
480
+
481
+ ## 6.5 Сортировка таблицы мощных терминов
482
+ - `setSemanticTermSortBy`
483
+ - `toggleSemanticTermSortDir`
484
+
485
+ Поддерживаются сортировки по:
486
+ - `Мой вес`
487
+ - `Avg K`
488
+ - `Freq (X/Y)` (с приоритетом большего `X` при одинаковом `Y`)
489
 
490
  ---
491
 
492
+ ## 7) Данные и модели (`models.py`)
493
 
494
+ Ключевые модели:
495
+ - `AnalysisRequest`, `AnalysisResponse`
496
+ - `SemanticAnalyzeRequest`, `SemanticAnalyzeResponse`
497
+ - `SemanticSearchRequest`, `SemanticSearchResponse`
498
+ - `UrlFetchRequest`, `UrlFetchResponse`, `UserAgentInfo`, `UserAgentsResponse`
499
+ - `OptimizerRequest`, `OptimizerResponse`
500
 
501
+ Роль моделей:
502
+ - жестко фиксируют API-контракты;
503
+ - упрощают валидацию;
504
+ - создают стабильный интерфейс между frontend/backend.
 
 
505
 
506
  ---
507
 
508
+ ## 8) Практические вычислительные принципы
509
+
510
+ 1. **Согласованная нормализация**
511
+ Одни и те же правила токенизации/лемматизации используются в нескольких модулях, чтобы избежать рассинхронизации метрик.
512
 
513
+ 2. **Локальные правки вместо полной перегенерации**
514
+ Оптимизатор меняет только локальные участки текста и проверяет эффект после каждой правки.
515
 
516
+ 3. **Многокритериальная защита**
517
+ Кандидат не принимается, если улучшение одной метрики достигается ценой неприемлемой деградации других.
 
 
 
 
518
 
519
+ 4. **Объяснимость**
520
+ Подробный лог итераций фиксирует baseline шага, кандидатов, причины отклонения и примененный вариант.
 
 
521
 
522
  ---
523
 
524
+ ## 9) Рекомендации по воспроизведению приложения по документации
525
+
526
+ Минимальный путь воспроизведения:
527
+ 1. Поднять FastAPI-приложение с endpoint-ами из раздела 4.
528
+ 2. Реализовать `logic.py` и `semantic_*` модули с описанными формулами и пайплайнами.
529
+ 3. Сделать frontend с соответствующими сценариями (`runAnalysis`, `runSemanticAnalysis`, `runLlmOptimization`).
530
+ 4. Добавить URL extractor и LLM optimizer как отдельные backend сервисы.
531
+ 5. Проверить контракты ответов, чтобы UI-таблицы и вкладки заполнялись без адаптеров.
532
+
533
+ ---
534
 
535
+ ## 10) Эксплуатация и деплой (Hugging Face)
 
 
 
536
 
537
+ - Рекомендуемый режим: lazy загрузка моделей.
538
+ - При проблемах типа `Could not resolve host: huggingface.co` рассматривать как внешнюю инфраструктурную проблему DNS/egress.
539
+ - Для диагностики сверять:
540
+ - `repo_sha` и `runtime_sha`
541
+ - `runtime_stage`
542
+ - При зависании сборки использовать повторный trigger-build.
543
 
544
  ---
545
 
546
+ ## 11) Smoke-check после любых изменений
547
 
548
+ 1. `python -m py_compile app.py logic.py semantic_graph.py search.py optimizer.py url_fetcher.py`
549
+ 2. Проверка endpoint-ов:
 
550
  - `/analyze`
551
  - `/api/v1/semantic/analyze`
552
  - `/api/v1/semantic/search`
553
+ - `/api/v1/url/user-agents`
554
+ - `/api/v1/url/fetch`
555
+ - `/api/v1/optimizer/run`
556
+ 3. Проверка UI:
557
+ - табы рендерятся;
558
+ - сортировки и таблицы работают;
559
+ - URL import заполняет text/title;
560
+ - save/load/new project работают;
561
+ - оптимизатор пишет лог и применяет текст.
562