Initial project import

This commit is contained in:
2026-08-14 09:40:51 +03:00
parent 00040e5ce4
commit d7099bf80d
146 changed files with 30509 additions and 1055 deletions
+132
View File
@@ -0,0 +1,132 @@
# Актуальный векторный поиск по коду 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` как
проверяемую производную копию.