133 lines
7.6 KiB
Markdown
133 lines
7.6 KiB
Markdown
# Актуальный векторный поиск по коду 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
|
||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_embeddings.ps1 -ConfigOnly
|
||
```
|
||
|
||
Запустить сервис с загрузкой образа:
|
||
|
||
```powershell
|
||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/deploy_embeddings.ps1 -Pull
|
||
```
|
||
|
||
Первый запуск скачивает модель в постоянный кеш и поэтому может занять
|
||
несколько минут. Скрипт ждёт `/health`, проверяет имя модели и делает реальный
|
||
запрос к `/v1/embeddings`.
|
||
|
||
## Обновление векторов
|
||
|
||
Сначала адаптер должен содержать актуальные текстовые chunks. Затем worker
|
||
забирает только отсутствующие либо изменившиеся фрагменты:
|
||
|
||
```powershell
|
||
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`),
|
||
поэтому векторы разных размеров никогда не смешиваются.
|
||
|
||
## Поиск
|
||
|
||
```powershell
|
||
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-хешами как с именами объектов.
|
||
|
||
Перед первым глобальным поиском после обновления адаптера нужно постранично
|
||
заполнить локальную карту владельцев:
|
||
|
||
```json
|
||
{
|
||
"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` как
|
||
проверяемую производную копию.
|