Files
llm/docs/runbooks/1c-code-embeddings.md
T
2026-08-14 09:40:51 +03:00

7.6 KiB
Raw Blame History

Актуальный векторный поиск по коду 1С

Цель: семантический поиск по локальному SQL-индексу адаптера без потери актуальности кода. Вектор является только производным кешем: перед выдачей адаптер сверяет найденные фрагменты с текущим состоянием конфигурации и отбрасывает либо переиндексирует устаревшие записи.

Выбранная модель

  • Qwen/Qwen3-Embedding-0.6B-GGUF, квантование Q8_0;
  • OpenAI-compatible endpoint на http://docker-gpu.cin.su:8082;
  • llama.cpp, --embedding --pooling last;
  • CPU-only (--n-gpu-layers 0), чтобы не менять работающие GPU-сервисы;
  • endpoint возвращает 1024 измерения, клиент использует Matryoshka-срез до запрошенных 384 измерений и повторно нормализует его.

Образ llama.cpp зафиксирован digest, а модель — официальным repository/quant селектором. Это исключает незаметную смену runtime при повторном deploy.

Модель и образ публичные, endpoint работает в изолированном тестовом контуре без токена. Постоянный кеш модели хранится вне git в Z:\LLM\models\cache\llama.cpp.

Развёртывание

Проверить итоговую конфигурацию:

powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_embeddings.ps1 -ConfigOnly

Запустить сервис с загрузкой образа:

powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_embeddings.ps1 -Pull

Первый запуск скачивает модель в постоянный кеш и поэтому может занять несколько минут. Скрипт ждёт /health, проверяет имя модели и делает реальный запрос к /v1/embeddings.

Обновление векторов

Сначала адаптер должен содержать актуальные текстовые chunks. Затем worker забирает только отсутствующие либо изменившиеся фрагменты:

python scripts/embed_1c_code_vectors.py `
  --adapter-url http://docker.cin.su:8011/rpc `
  --base-id upo_test `
  --embedding-provider openai-compatible `
  --embedding-model qwen3-embedding-0.6b `
  --dimensions 384 `
  --embedding-base-url http://docker-gpu.cin.su:8082 `
  --limit 500 `
  --batch-size 8 `
  --chunk-kind routine `
  --max-text-chars 4000 `
  --json

Worker по умолчанию индексирует routine: процедуры и функции дают наиболее точный контекст для программирования и заметно быстрее пересчитываются при частых изменениях. Для диагностического покрытия модульных фрагментов можно добавить второй --chunk-kind module; это более дорогой отдельный проход. --max-text-chars не обрезает код молча: длинные chunks пропускаются в этом проходе и остаются pending. Их нужно разбивать на окна отдельной задачей либо индексировать в период низкой нагрузки с большим лимитом.

Размерность входит в имя кеша (openai-compatible:qwen3-embedding-0.6b@d384), поэтому векторы разных размеров никогда не смешиваются.

Поиск

python scripts/search_1c_code_vectors.py `
  "где рассчитывается сумма документа перед проведением" `
  --adapter-url http://docker.cin.su:8011/rpc `
  --base-id upo_test `
  --embedding-provider openai-compatible `
  --embedding-model qwen3-embedding-0.6b `
  --dimensions 384 `
  --embedding-base-url http://docker-gpu.cin.su:8082 `
  --limit 10 `
  --json

Поиск вызывается с strict=true и verify=true. Сохранённые изменения Конфигуратора перекрывают активную конфигурацию, а удалённые/изменённые chunks не возвращаются по старому вектору.

Для активного кода расширений хеш ConfigCAS разрешается через текущий manifest расширения в descriptor объекта. Результат содержит обычные kind/name, а также extension и extension_guid; вызывающему коду не нужно работать с CAS-хешами как с именами объектов.

Перед первым глобальным поиском после обновления адаптера нужно постранично заполнить локальную карту владельцев:

{
  "method": "metadata.module_owner_cache.backfill",
  "payload": {
    "base_id": "upo_test",
    "limit": 50,
    "kind_index": 0,
    "offset": 0
  }
}

Следующий вызов получает kind_index и offset из next_cursor. Повторять до complete=true. Операция читает актуальные метаданные, но пишет только в локальный SQLite адаптера. Найденные имена сразу добавляются в существующие строки лексического и векторного индексов; перестраивать embeddings не нужно. По умолчанию объекты без строк code index быстро пропускаются. deep=true нужен только для отдельного фонового заполнения владельцев неиндексированных модулей и не должен использоваться в интерактивном поиске.

Для Qwen3-Embedding клиент автоматически добавляет к векторизуемому запросу англоязычную инструкцию поиска по исходному коду 1С, как рекомендует карточка модели. В query адаптера остаётся исходный русский текст, поэтому лексическая часть гибридного поиска не загрязняется служебным префиксом.

Отдельная векторная БД

На текущем этапе не требуется. Векторы хранятся рядом с индексом адаптера в SQLite и выбираются линейным сканированием. Это проще и гарантирует атомарную проверку актуальности. Отдельный ANN-движок имеет смысл только после замера десятков тысяч актуальных chunks и неприемлемой задержки; источником истины всё равно остаётся 1С/SQL, а ANN должен хранить chunk_id и text_sha1 как проверяемую производную копию.