Files
tf_docs/llm_project/docs/SESSION_HANDOFF.md
T

41 KiB
Raw Blame History

SESSION HANDOFF — AI-ассистент документации Nubes (чат 2026-10-07 … 2026-10-08)

Для кого этот файл. Это полный отчёт-передача для нового чата (новая сессия / другой агент). Читать целиком перед первой правкой. Составлен 2026-10-12 по транскрипту сессии, git-истории и живым проверкам. Источник фактов указывается в виде файл:строка или git:<hash>.


0. ПРАВИЛА РАБОТЫ С ЭТИМ ПОЛЬЗОВАТЕЛЕМ (читать первым, нарушать нельзя)

Приказы получены дословно в этой сессии (и подкреплены раздражением при нарушениях):

  1. ⛔ НИЧЕГО не менять без прямой команды: не править код, не коммитить, не деплоить, не откатывать, не менять конфиги, не лезть в соседние репозитории. Роль агента — советник, не исполнитель.
  2. ⛔ terraform apply / terraform destroy — НИКОГДА сам. Разрешено: init, plan, validate, show, state show. (Нарушение 2026-10-04: после падения apply полез в API PROD и пытался удалить инстанс — инстансы not created удаляет ТОЛЬКО владелец в ЛК.)
  3. Коммит после КАЖДОЙ правки, дробить по смыслу, не копить untracked. Push — только по отдельной команде.
  4. Ответ — кратко (1–5 строк или короткий список). Развёрнуто — только если прямо просят.
  5. Вопрос = только ответ. Никаких «а ещё могу», «давай я». После работы — «готово» и ждать.
  6. ⛔ Не спрашивать то, что можно выяснить самому (репо, HAR, git-история, generated/*.yaml, API, логи VS Code). Спрашивать только про то, чего в данных нет в принципе (выбор человека: аккаунт, ключ, домен, цифры).
  7. Не расширять область (scope creep). «Сделай актуальным везде» НЕ даёт права на дополнительные шаги.
  8. Команда понятна не на 100% → НИЧЕГО не делать, задать один короткий уточняющий вопрос, ждать.
  9. Анти-зацикливание: не более 2 однотипных вызовов инструмента подряд; после двух безрезультатных — остановиться и доложить.
  10. Документировать ВСЁ, включая собственные ошибки.
  11. Не рекомендовать и не менять без замера. Рекомендация без замера — догадка. Сначала «до/после» тем же инструментом, потом вывод.
  12. О текущем поведении — только КОД (файл:строка). Документы HISTORY/, docs/*_history* описывают прошлое и могут противоречить коду.
  13. Любое утверждение должно быть проверяемым. Не смог доказать — писать «не знаю / не проверено».

1. Что это за проект (кратко)

AI-ассистент документации Terraform-провайдера Nubes — виджет на сайте документации: пользователь пишет задачу своими словами, получает ответ строго по шаблону со ссылками на страницы документации.

Это не свободный чат, а RAG-пайплайн: сначала лексический поиск находит фрагменты документации, затем LLM пересказывает их в фиксированном формате.

  • Модель: gpt-oss-120b через https://api.aillm.ru (OpenAI-совместимый).
  • Backend: Node.js 18, без внешних npm-зависимостей (только встроенные http/https/fetch/AbortController).
  • Поиск v1: лексический (BM25-подобный) по search_index.json MkDocs.
  • Статус на 2026-10-12: работает на всех трёх стендах, v1 заморожен, ждём реальных откликов DevOps-тестировщиков.

Подробная архитектура: tf_docs/llm_project/docs/ASSISTANT_ARCHITECTURE.md (327 строк). Дорожная карта: tf_docs/llm_project/docs/ROADMAP_AND_LIMITS.md (127 строк).


2. Что было запрошено (все 99 запросов сессии — сжатая выжимка)

Полный список запросов восстановлен из транскрипта (…/GitHub.copilot-chat/transcripts/f3e064fa-….jsonl, 2707 строк, 99 сообщений пользователя).

Блок А. Старт и бриф (10:34–10:51). Прочитать бриф по AI-ассистенту, собрать факты (только чтение), затем написать код. Требование: всегда привлекать DeepSeek Flash как субагента, когда это целесообразно и не рискованно (он значительно дешевле). Затем — написать модули: каркас assist.js, search.js, stage1.js, виджет для MkDocs, эталонный набор вопросов.

Блок Б. Деплой и первые тесты (10:58–14:45). «Как ты тестил? Давай тесты на деплое». Выяснение, что и куда редеплоить (экземпляр NodeJS tf-docs в Nubes), добавление переменных окружения, «САМ делай redeploy. тесты. правки. и так — по циклу, пока всё не оптимизируешь».

Блок В. Оптимизация и оценка (14:00–15:50). «Показывай прогресс», код-ревью «насколько умён этот режим», «наверняка надо ещё улучшать», «твоё ОБЪЕКТИВНОЕ мнение — хорошо получилось?».

Блок Г. UI и TODO (14:37). «?» неинформативно → надпись LLM на кнопке; в конце ответа — время обработки и число токенов (несрочно, в TODO).

Блок Д. Эмбеддинги и таймер (16:03–16:07). Вопросы: есть ли индикация прогресса (таймер), что такое эмбеддинги, где хранится результат, что будет если не делать. Приказ: «всё документируй ПОДРОБНО, в т.ч. по эмбеддингу, и делай таймер-индикацию».

Блок Е. Curated-примеры (16:52–17:06). Раздражение: ассистент обязан опираться на проверенные примеры (/home/naeel/TF/tf_provider/TEST_STAND/CRUD, опубликованные как curated/*) — «именно ЭТО МЫ тестировали НА РЕАЛЬНЫХ деплоях». Затем: сделать для prod стенда.

Блок Ж. Документирование и синк (17:32–18:04). «Всё документируй, коммить и пушь», синк ~/TF на ВМ 213, если нет — сделать ПОДРОБНУЮ инструкцию; определить самое сложное в интеграции; «чтобы это легко находилось».

Блок З. Планы развития (04:49–05:15). Что и как совершенствовать; куда складывать сбор данных (варианты: stdout/Grafana, S3, файл на ВМ, PG); «может, вообще сейчас ничего не делать?» → решение заморозить v1 и ждать откликов (тестировать будут DevOps-инженеры, не случайные юзеры). Так как данных нет — сделать тест-набор на 300 вопросов («НЕ СПЕША, внимательно сочини»), затем прогнать тесты.

Блок И. Приёмка (05:19–06:15). Прогон 300 вопросов, показ прогресса, вопрос «что надо будет править? результаты ВСЕ сохранил?» (приказ: пока НИЧЕГО не править).


3. Хронология работ (что реально сделано)

Все времена — из транскрипта; коммиты — git log репозиториев tf_docs и tf_provider.

3.1. Каркас и модули (10:40–13:57, tf_docs)

Время Сделано Коммит
13:41 Каркас assist.js: validateInput (415/413/400), rate-limit, семафор, llmChat, jsonError, чтение env e419b38
13:43 Live-проверка api.aillm.ru скриптом-пробником (probe/probe_aillm.js, probe/RESULTS.md) e5817ff
13:46 Лексический поиск search.js + эталонный набор 28 вопросов 827870d
13:48 Этап 1 — извлечение resource_type через LLM по списку реальных nubes_* 4e8d115
13:49 Этап 2 — объединение результатов поиска (П.8) + генерация по строгому шаблону c2e2f9c
13:50 Маршрут POST /<stand>/_api/assist в server.js + оркестратор пайплайна e8b6d9b
13:51 Dockerfile (копирование новых модулей) + README (эндпоинт, переменные) 490d8b6
13:57 Перф поиска: буст страницам ресурсов, транслит кириллица→латиница, подресурс→родитель (точность на эталоне 71% → 93%) 2136536
14:11 Форматирование модулей + план по шагам c59f024

3.2. Виджет на сайте (13:53–19:09, tf_provider)

Время Сделано Коммит
13:53 Виджет ассистента: плавающая кнопка + панель, стили, подключение в mkdocs.yml f6827fc
14:37 Форматирование extra.css 13d294f
15:17 Пояснение в виджете: что это, что может и чего не может 0a17cae
16:07 Описание — раскрывающийся блок <details>/<summary> bfc57ca
18:55 FAB «LLM», в ответе — время и число токенов 166196a
19:08 Таймер-индикация «⏳ N с» при загрузке 79d57ac

3.3. Тесты и надёжность (14:11–18:53)

Событие Детали Коммит
Прогон №1 (62 вопроса, прод) 56/62, 6 отказов 502 bad_llm_output —
Найдена причина 502 ответ обрезался max_tokens: 1024 до секции «Ограничения» (finish_reason: length); плюс собственный баг: regex \b не работает с кириллицей → заголовки «не находились» b99344e
Фикс max_tokens 1024 → 2048 + повтор ×2 с удвоением (до 4096), устойчивая проверка заголовков b99344e
Прогон №2 60/62; добавлен повтор при транзиентных ошибках LLM 0065026, 298299a
Прогон №3 61/62; фикс: отвечать по шаблону и на вопросы вне документации (инъекции → 200 вместо 502) dafcb6b, 568b73d
Автоматизация redeploy через Nubes API Bearer + CFS-параметры; opUid берётся из заголовка Location, не из тела a4b2ddc
Прогон №4 62/62, ноль отказов 9728fe4
Перф-оптимизации кэш индекса (TTL 10 мин) + предрасчёт списков + дедлайн 40 с + логирование этапов 99e034d
Предтокенизация документов поиск ~1.2 с → ~6 мс 5848fcc
Прогон №5 61/62 (1 — клиентский сбой сети TypeError: fetch failed) 5018acf
Токены в ответе сбор usage и отдача в meta f42017f

3.4. Документация, продуктизация, prod (19:09–21:05)

Событие Коммит
Полная документация ассистента (архитектура, API, поиск, безопасность, деплой, тесты, эмбеддинги v2) fe93645
Поднят вес curated/*-страниц выше ресурсных (готовые примеры, проверенные на реальных деплоях) 382b7b0
Три стенда (nubes-test, nubes-dev, nubes prod), приоритет curated, разбор инцидента генератора nav f1a774d
Фикс генератора: кавычить заголовки сервисов в _nav_fragment.yml ([DEPRECATED] ломал YAML) — TOOLS/docs-generator/internal/writers/writers.go, yamlScalar() 322235c
HowTo: публикация сайта, redeploy через API, синк на ВМ 213 (+ sync-tf-to-vm213.sh) ~/HowTo/* (вне git)
Ссылки на документацию ассистента и HowTo в README репозиториев d52ae10, ad42957
Индекс проекта ассистента llm_project/README.md ad42957

3.5. 2026-10-08: дорожная карта, 300 вопросов, прогон

Время Событие Коммит
08:03 Дорожная карта, границы применимости, план тестирования DevOps, варианты сбора данных f5683fa
08:19 Тест-набор из 300 вопросов (llm_project/golden/golden_questions_300.json) cd74ff2
08:21 Раннер: поддержка внешнего набора (--file/--out) + метрика попадания в expected_pages fc5245b
08:21→09:13 (~52 мин) Полный прогон 300 вопросов на nubes-test —
09:14 Результаты (RESULTS_300.json, RESULTS_300.md) 5ab9274

4. Файлы (что где лежит)

4.1. Backend — репозиторий tf_docs (/home/naeel/TF/tf_docs)

Remote: https://gitea.services.ngcloud.ru/terraform/tf_docs.git

Файл Назначение
server.js HTTP-сервер: прокси GET/HEAD статики на ВМ 213 + ветка POST /<stand>/_api/assist до проверки 405. orchestrator.js грузится в try/catch, чтобы не ронять статику.
assist.js Каркас: validateInput, createRateLimiter, createSemaphore, llmChat, jsonError, normalizeQuery, ENV, maskKey.
search.js Лексический поиск: токенизация, HTML-очистка, стоп-слова, TRANSLIT (кириллица→латиница), буст по типу страницы, resourceBaseSegment() (подресурс→родитель), предтокенизация, listResourceTypes() (56 типов), resourcePages() (35 страниц).
stage1.js Этап 1: LLM извлекает resource_type (response_format: json_object), сверка со списком реальных ресурсов, empty_content → повтор ×2.
stage2.js mergeSearchResults (объединение по location, max score, страница ресурса первой) + stage2Generate (строгий шаблон, повтор ×2 с удвоением бюджета, hasHeader с учётом кириллицы), collectSources, sanitizeSourceUrl.
orchestrator.js Пайплайн целиком: handleAssist, createSharedState, fetchIndex (кэш TTL 10 мин + stale-fallback), runPipeline (дедлайн 40 с, тайминги этапов, сбор токенов), logAssist (однострочный JSON в stdout).
Dockerfile node:18-alpine, копирует все 6 модулей.
README.md Эндпоинт, контракт, переменные окружения.
llm_project/ Всё про ассистента: планы, документация, тесты, диагностика.

4.2. tf_docs/llm_project/

Файл Что
README.md Карта файлов проекта ассистента
docs/ASSISTANT_ARCHITECTURE.md Полная документация (архитектура, API, поиск, безопасность, деплой, тесты, эмбеддинги v2, инциденты)
docs/ROADMAP_AND_LIMITS.md Дорожная карта, границы применимости, план тестирования DevOps, варианты сбора данных
PLAN_docs_ai_assistant_STEPS.md Исходный план по шагам (11 этапов)
probe/probe_aillm.js, probe/RESULTS.md Live-проверка API api.aillm.ru и её результаты
golden/golden_questions.json 28 эталонных вопросов с ожидаемыми страницами
golden/EVAL_1.md Оценка поиска на эталоне (шаг 9)
golden/golden_questions_300.json 300 вопросов (поля q, expected_pages, resource_type, cat)
tests/run_e2e_live.js Прогон по живому эндпоинту (учёт 429, --file, --out, метрика hit)
tests/redeploy.js Redeploy tf-docs через Nubes API
tests/debug_bad_llm_output.js Захват сырого ответа LLM (диагностика)
tests/RESULTS_LIVE.{json,md} Результаты прогонов 62 вопроса (5 итераций)
tests/RESULTS_300.{json,md} Результаты прогона 300 вопросов (.log — в .gitignore)
tests/ANALYSIS_bad_llm_output.md Разбор отказов 502, причины и фиксы

4.3. Виджет и сайт — репозиторий tf_provider (/home/naeel/TF/tf_provider)

Remote: https://gitea.services.ngcloud.ru/terraform/tf_provider.git

Файл Назначение
docs/30_registry/javascripts/assistant.js Виджет: FAB «LLM», панель, раскрывающееся описание, таймер «⏳ N с», ответ + источники, время и токены. ES5, IIFE, без зависимостей, вывод только через textContent.
docs/30_registry/assets/extra.css Стили виджета
mkdocs.yml Подключение assistant.js в extra_javascript
TOOLS/docs-generator/internal/writers/writers.go yamlScalar() — кавычит заголовки со спецсимволами в _nav_fragment.yml

4.4. HowTo (вне git)

Фактическое расположение: ~/HowTo/ (/home/naeel/HowTo/).

~/HowTo/README.md                          — индекс инструкций
~/HowTo/howto-publish-docs-site.md         — публикация сайта (tf_provider → S3 → ВМ 213)
~/HowTo/howto-tf-docs-redeploy-api.md      — redeploy tf-docs через Nubes API
~/HowTo/howto-sync-to-vm213.md             — синк каталогов на ВМ 213
~/HowTo/sync-tf-to-vm213.sh                — скрипт синка ~/TF → ВМ 213
~/HowTo/howto-ssh-access.md                — доступы к 213 / Vultr / 3060
~/HowTo/vm-access-and-services.md          — что есть на ВМ 213

5. Архитектура и контракт (для быстрого старта)

5.1. Поток

Браузер (виджет assistant.js)
  │ POST /<stand>/_api/assist  {"question": "..."}
  ▼
tf_docs (Node.js 18, кластер nodejsk8s)
  ├─ validateInput (415/413/400)               [assist.js]
  ├─ rate-limit по IP (429 + Retry-After)      [assist.js]
  ├─ кэш ответов + дедуп одинаковых запросов
  ├─ семафор ASSIST_MAX_CONCURRENT=4 (иначе 503)
  ├─ дедлайн 40 с (AbortController)
  ├─ Этап 1: LLM → resource_type               [stage1.js]
  ├─ Поиск: search_index.json → top-K          [search.js]
  ├─ Объединение результатов (П.8)             [stage2.js]
  └─ Этап 2: LLM → ответ по шаблону            [stage2.js]
  ▼
{ answer, sources[], meta }

Индекс берётся с VM_DOCS_BASE_URL/<stand>/search/search_index.json (ВМ 213, 823 документа на момент прогона).

5.2. Контракт API

Запрос: POST /<stand>/_api/assist, Content-Type: application/json, тело {"question": "..."} ≤ 2 КБ.

Ответ 200:

{
  "answer": "Роль/Задача/Контекст/Требования/Ограничения",
  "sources": [{"title": "...", "url": "/<stand>/..."}],
  "meta": {
    "model": "gpt-oss-120b", "resource_type": "nubes_...|null",
    "stage1_ok": true, "elapsed_ms": 12000,
    "index_ms": 86, "stage1_ms": 1200, "search_ms": 6, "stage2_ms": 8300,
    "tokens": 2868, "prompt_tokens": 2105, "completion_tokens": 763
  }
}

Ошибки ({"error": code, "message": ...}):

HTTP code Смысл
400 — невалидный JSON / пустой вопрос
413 — тело > 2 КБ
415 — Content-Type не application/json
429 rate_limited превышен лимит (заголовок Retry-After)
503 busy семафор исчерпан (Retry-After: 5)
502 bad_llm_output LLM не выдал обязательные заголовки
503 index_unavailable не удалось загрузить индекс

5.3. Переменные окружения (задаются в ЛК как jsonEnv)

VM_DOCS_BASE_URL (обязательна, http://5.172.178.213) · LLM_BASE_URL (https://api.aillm.ru) · LLM_API_KEY (Secret) · LLM_MODEL (gpt-oss-120b) · ASSIST_MAX_CONCURRENT (4) · ASSIST_TOTAL_DEADLINE_MS (40000) · ASSIST_LLM_TIMEOUT_MS (25000) · ASSIST_RATE_PER_WINDOW (6) · ASSIST_RATE_WINDOW_MS (60000) · ASSIST_REPLICAS (1) · ASSIST_MAX_BODY (2048) · ASSIST_INDEX_TTL_MS (600000) · ASSIST_TRUSTED_PROXY_CIDR.

5.4. Факты по LLM API (проверено live, probe/RESULTS.md)

Параметр Результат
response_format: {type:"json_object"} ✅ поддерживается (этап 1)
reasoning_effort ❌ 400 UnsupportedParamsError — не передавать
reasoning_content ✅ есть в ответе — игнорировать, брать только content
stream: true ✅ SSE; в v1 не используется
Пустой content ⚠️ при малом max_tokens → content: null; обрабатывать как ошибку + повтор
Доступные модели gpt-oss-120b, qwen3.8-27b-fp8(-rtx6000), user-bge-m3, bge-reranker-v2-m3, whisper
Задержка этапа 1 ~1.0–1.3 с

6. Инфраструктура

6.1. Стенды

Проверено 2026-10-12: POST /<stand>/_api/assist с Content-Type: text/plain отвечает 415 на всех трёх стендах (ветка ассистента жива), статика /<stand>/search/search_index.json — 200.

Стенд URL Профиль сборки Namespace (S3/URL)
test https://tf-docs.nodejsk8s.dev.nubes.ru/nubes-test/ TOOLS/config/test nubes-test
dev https://tf-docs.nodejsk8s.dev.nubes.ru/nubes-dev/ TOOLS/config/dev nubes-dev
prod https://tf-docs.nodejsk8s.dev.nubes.ru/nubes/ TOOLS/config/prod nubes

6.2. Цепочка публикации документации

stack/<стенд>/<svc>/rendered.md  ─┐
generated/<стенд>/docs/          ─┴─► MkDocs build ► site/ ► S3 ► mc mirror ► ВМ 213 nginx
# 1) сборка + публикация в S3
cd ~/TF/tf_provider
DOCS_SKIP_LINT=1 bash TOOLS/scripts/04_build_and_publish_docs.sh --profile TOOLS/config/test

# 2) зеркало S3 → ВМ 213 (БЕЗ ЭТОГО ШАГА ИЗМЕНЕНИЙ НА САЙТЕ НЕ БУДЕТ)
ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 \
  "mc mirror --overwrite --remove nubes/terraform-registry/docs/nubes-test/nubes/ /var/www/tf-docs/nubes-test/"

6.3. Redeploy backend'а

node ~/TF/tf_docs/llm_project/tests/redeploy.js

Либо вручную через API: instanceUid (test) 7a48a863-9b40-4cef-a352-033ee9dde8de, endpoint https://lk-api-gateway-test.ngcloud.ru/api/v1/svc, токены ~/TF/tf_provider/secrets/{test,dev,prod}.token, обязателен User-Agent: Mozilla/5.0 (иначе DDoS-Guard блокирует). opUid операции — в заголовке Location, не в теле.

6.4. Доступы

Что Значение
ВМ 213 naeel@5.172.178.213, ключ ~/.ssh/naeel_vm_id_ed25519
Статика на ВМ /var/www/tf-docs/<ns>/
Ключ LLM ~/nubes/llm.key (и ~/TF/tf_provider/secrets/llm.key) — не логировать
Токены платформы ~/TF/tf_provider/secrets/{test,dev,prod}.token
Синк ~/TF → ВМ 213 ~/HowTo/sync-tf-to-vm213.sh [--dry-run]

6.5. Окружение разработки

  • npm НЕ установлен → тесты запускать как node --test, синтаксис проверять node -c файл.js.
  • du — не GNU (ключ -sh ломается); rsync есть.

7. Тестирование: результаты

7.1. Прогон 62 вопроса (5 итераций, RESULTS_LIVE.*)

Прогон 200 OK Отказов Причина и фикс
1 56/62 6 обрезка max_tokens: 1024 → 2048 + повтор; баг \b с кириллицей
2 60/62 2 + повтор при транзиентных ошибках
3 61/62 1 + шаблон для вопросов вне документации
4 62/62 0 —
5 61/62 1 клиентский сбой сети (не бэкенд)

Задержки (5-й прогон): p50 7.7 с, p95 23 с, max 40.8 с — доминирует LLM; собственный код ≈ 6 мс поиск + кэш.

7.2. Прогон 300 вопросов (RESULTS_300.*, 2026-10-08, nubes-test)

Команда:

cd ~/TF/tf_docs
node llm_project/tests/run_e2e_live.js --stand nubes-test \
     --file golden/golden_questions_300.json --out RESULTS_300

Итог:

Метрика Значение
Ответов 200 300/300
Ошибок (4xx/5xx/сеть) 0
Шаблон соблюдён 300/300
resource_type определён 247/300
Латентность min 157 мс, p50 5.35 с, p95 10.57 с, max 15.66 с
Негатив/инъекции без resource_type 16/17
Попадание в expected_pages 261/268 (97.4 %)
Пауз на 429 42 (rate-limit 6/мин)
Длительность прогона ~52 мин (08:21 → 09:13)

По категориям:

Кат. Всего 200 hit
db 69 69 69/69
vmware 42 42 41/42
app 38 38 38/38
queue 28 28 27/28
k8s 26 26 25/26
net 16 16 16/16
neg 17 17 —
curated 16 16 16/16
s3 12 12 12/12
meta 12 12 0/1
typo 10 10 6/8
llm 9 9 8/9
lang 5 5 3/3

7 промахов hit=NO (ожидаемая страница не попала в sources):

# Вопрос Ожидалось Получено Характер
67 как дать права только на чтение kafka юзеру kafka akhq, lucee, nextcloud, postgres реальный промах поиска
105 как привязать vdc к группе vc_vdc_group curated/pipeline/..., vc_nsxt реальный промах
147 какие модели можно развернуть llm_ai curated/crud/..., akhq, clickhouse реальный промах (+ rt=null)
184 какие версии провайдера доступны template — ошибка разметки: страницы про версии в индексе нет вообще
213 как сделать чтобы сервис был доступен из интернета vcexternalip nextcloud, vapp, vc_nsxt реальный промах
214 что нужно чтобы завести боевой стенд с базой очередями и приложением postgres,kafka,nodejs curated/crud/three_apps спорный: ответ ассистента, вероятно, лучше
234 как удалить ноду из кластера k8s_sthutrval_cluster mariadb, mongodb ops реальный промах

Проверено: все ожидаемые страницы, кроме «версий провайдера», есть в индексе (823 документа) — значит промахи 67/105/147/213/234/214 вызваны ранжированием, а не отсутствием страницы.


8. Что надо будет править (приоритеты; НИЧЕГО ещё не правилось)

  1. Морфология русских запросов — главная причина промахов. «ноду» ≠ «нода», «группе» ≠ «группа», «модели» ≠ «модель». Промахи №234, №105, №213, №147. Лечится стеммингом/усечением русских окончаний в search.js (или эмбеддингами).
  2. Буст совпадения по заголовку страницы — №67: запрос про kafka, а в топ-5 попали akhq, lucee, nextcloud, postgres, сама страница kafka не попала вообще.
  3. Этап 1 не определил resource_type в 23 вопросах, где тип ожидается (db 2, vmware 3, net 1, llm 1, k8s 1, s3 1, typo 7, curated 7). Лечится few-shot примерами в промпте (нода → кластер, модели → llm_ai, firewall на edge → vc_nsxt, DNS-запись → dnsrecord, файлы в s3 → s3bucket).
  4. Ошибки в разметке тест-набора (не баг ассистента): №184 — expected_pages: ["template"] при отсутствии страницы о версиях; №213 отнесён к категории typo, хотя опечатки нет (на метрики не влияет).
  5. Спорный №214 — ожидание postgres,kafka,nodejs, ответ curated/crud/three_apps: вероятно, ответ ассистента правильнее.
  6. Расхождения в документах: llm_project/README.md и ROADMAP_AND_LIMITS.md ссылаются на ~/nubes/HowTo/…, фактически файлы лежат в ~/HowTo/. Также ASSISTANT_ARCHITECTURE.md:§11 описывает только прогон 62 вопроса — результаты 300 вопросов там не отражены.
  7. Не баг, но ограничение: rate-limit 6/мин даёт 42 паузы на 300 вопросов; полный прогон ≈ 52 мин.

Реальных промахов поиска — 5–6 из 300. Ошибок ответа (шаблон, 5xx, уход от темы) — 0.


9. Что НЕ реализовано (обсуждено и отложено осознанно)

Тема Решение Детали
Эмбеддинги + реранкер (v2) НЕ делать сейчас user-bge-m3 (1024 dims) + bge-reranker-v2-m3. 823 документа ≈ 3.4 МБ float32 → хранить в памяти Map: location → Float32Array, рядом с кэшем индекса. Отдельной БД/файла не нужно. ~50–100 строк vectorSearch.js, ~полдня. См. ASSISTANT_ARCHITECTURE.md:§12.
Сбор реальных вопросов/фидбэка НЕ реализовано Варианты: stdout→Grafana, S3 (JSONL), файл/PG на ВМ 213 (⛔ нельзя в /var/www/tf-docs/ — перезапишет mc mirror), managed nubes_postgres рядом с tf_docs. Рекомендация при старте: stdout; при необходимости — managed PG. См. ROADMAP_AND_LIMITS.md:§3.
Стриминг (SSE) отложено Ответ отдаётся целиком; задержку 5–10 с маскирует таймер.
Кэш ответов TTL/LRU отложено Сейчас in-memory Map без TTL, чистится только перезапуском.
Несколько реплик отложено ASSIST_REPLICAS=1, кэш/лимиты не шарятся.

Позиция пользователя: заморозить v1, дождаться реальных отзывов от DevOps-инженеров (не случайных юзеров), собирать отзывы вручную по шаблону ROADMAP_AND_LIMITS.md:§5.4, и только потом внедрять улучшения.


10. Ключевые уроки и «грабли» (не наступать снова)

  1. Regex \b не работает с кириллицей в JS без u-флага — из-за этого все заголовки ответа считались отсутствующими. Проверять заголовки в начале строки.
  2. max_tokens мал → ответ обрезается до последней секции шаблона → ложный 502. Бюджет 2048 + повтор ×2.
  3. reasoning_effort не поддерживается моделью — 400.
  4. reasoning_content присутствует в ответе — игнорировать, брать content.
  5. opUid операции redeploy — в заголовке Location, не в теле ответа.
  6. Redeploy требует CFS-параметр startupConfiguration (брать из живого состояния), иначе 422.
  7. Обязателен User-Agent: Mozilla/5.0 при работе с Nubes API (DDoS-Guard).
  8. mc mirror обязателен после публикации в S3, иначе сайт не изменится.
  9. Индекс кэшируется 10 мин — после публикации доков свежие страницы появляются в ассистенте с задержкой.
  10. YAML-nav: заголовок сервиса со спецсимволами ([DEPRECATED]) без кавычек ломает сборку — исправлено в генераторе (yamlScalar()), но помнить.
  11. npm в окружении нет — только node.

11. ИНСТРУКЦИИ ДЛЯ НОВОГО ЧАТА

11.1. Порядок действий в начале

  1. Прочитать этот файл целиком.
  2. Прочитать tf_docs/llm_project/docs/ASSISTANT_ARCHITECTURE.md и …/ROADMAP_AND_LIMITS.md.
  3. Проверить git status в tf_docs и tf_provider — не остались ли незакоммиченные правки.
  4. Ничего не менять, пока пользователь не дал прямую команду.

11.2. Чего делать НЕЛЬЗЯ (повтор, критично)

  • править код / коммитить / пушить / деплоить / откатывать без прямой команды;
  • terraform apply / destroy — никогда;
  • удалять инстансы в ЛК (даже not created) — только владелец;
  • логировать или печатать LLM_API_KEY и токены;
  • спрашивать то, что можно узнать из файлов/git/API;
  • расширять область задачи («раз уж правлю, сделаю ещё X»).

11.3. Типовые команды

# --- backend: проверка синтаксиса и правки ---
node -c /home/naeel/TF/tf_docs/search.js

# --- прогон тестов (любой набор, любой стенд) ---
cd /home/naeel/TF/tf_docs
node llm_project/tests/run_e2e_live.js --stand nubes-test \
     --file golden/golden_questions_300.json --out RESULTS_300
node llm_project/tests/run_e2e_live.js --stand nubes-test          # встроенные 62

# --- redeploy сервиса ---
node ~/TF/tf_docs/llm_project/tests/redeploy.js

# --- публикация документации + зеркало на ВМ 213 ---
cd ~/TF/tf_provider
DOCS_SKIP_LINT=1 bash TOOLS/scripts/04_build_and_publish_docs.sh --profile TOOLS/config/test
ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 \
  "mc mirror --overwrite --remove nubes/terraform-registry/docs/nubes-test/nubes/ /var/www/tf-docs/nubes-test/"

# --- синк ~/TF на ВМ 213 ---
~/HowTo/sync-tf-to-vm213.sh --dry-run

11.4. Живая проверка эндпоинта без расхода токенов LLM

# 415 => ветка ассистента жива; 200 у search_index.json => статика/индекс на месте
curl -s -o /dev/null -w "%{http_code}\n" -X POST \
  https://tf-docs.nodejsk8s.dev.nubes.ru/nubes-test/_api/assist \
  -H 'Content-Type: text/plain' --data 'x' -H 'User-Agent: Mozilla/5.0'

Внимание: реальный POST с application/json вызывает два вызова LLM и тратит деньги. Тестовые прогоны согласовывать с пользователем.

11.5. Что, вероятно, попросят дальше (по итогам сессии)

  • Править поиск (морфология / буст заголовка) и этап 1 (few-shot) — список в §8.
  • Поправить разметку 300-вопросного набора (№184, №213).
  • Привести в порядок ссылки на ~/HowTo/ в документации.
  • После получения реальных отзывов DevOps — решение об эмбеддингах и сборе данных.

12. Состояние на момент передачи

Что Состояние
Репозиторий tf_docs Всё закоммичено, HEAD 5ab9274; незакоммиченного нет
Репозиторий tf_provider Последний коммит этой сессии d52ae10 (10-07 21:05); позже (10-09, 10-10) были другие работы — см. git log
Стенды test/dev/prod — ассистент отвечает (проверено GET/POST 415, 2026-10-12)
v1 Заморожен, ждём реальных откликов
300-вопросный прогон Завершён, результаты закоммичены, правки не начаты (приказ: «пока НИЧЕГО не правь»)
Открытые вопросы к пользователю нет