Эмбеддер bge-m3: смысловой поиск на русском наконец разделяет смыслы

nomic-embed-text на русском не работал: в замере «велосипедная камера»
набирала мультиметру 0.704 — больше, чем верный ответ на «паяльник» (0.691).
Зазор −0.013, то есть мусор систематически обгонял правильное и порогом это
не лечилось.

bge-m3 на том же наборе: верные не ниже 0.537, мусор не выше 0.460,
зазор +0.077. Префиксы задачи ему не нужны, поэтому обнулены.

Порог откалиброван на настоящей базе, а не на придуманном наборе, и картина
там честнее: абстрактное «чем посветить» набирает лампам 0.411, а посторонняя
«детская коляска» — 0.535. Полностью не разделяются, поэтому SEMANTIC_MIN
выставлен так, чтобы отсечь весь мусор ценой слабых догадок — уверенно
показанное не то хуже честного «не нашёл». Точных запросов это не касается:
они находятся по словам и тегам.

Добавлен tools/reindex.py: смена эмбеддера требует полного пересчёта векторов,
иначе смешанная база тихо портит поиск. Скрипт делает копию перед работой.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 18:23:22 +03:00
co-authored by Claude Opus 5
parent 781690365e
commit 39c807d4de
5 changed files with 127 additions and 33 deletions
+20 -12
View File
@@ -17,7 +17,7 @@
```
ollama pull qwen2.5:7b разбор фраз и теги
ollama pull nomic-embed-text поиск по смыслу (необязательно)
ollama pull bge-m3 поиск по смыслу (необязательно)
```
## Установка
@@ -62,7 +62,7 @@ start.cmd запускает сервер и печатает адреса
|---|---|---|
| `OLLAMA_HOST` | `http://localhost:11434` | адрес Ollama |
| `HLAMINGO_CHAT_MODEL` | `qwen2.5:7b` | разбор фраз и теги |
| `HLAMINGO_EMBED_MODEL` | `nomic-embed-text:latest` | поиск по смыслу |
| `HLAMINGO_EMBED_MODEL` | `bge-m3` | поиск по смыслу |
| `HLAMINGO_PORT` | `5000` | порт веб-интерфейса |
| `HLAMINGO_DATA_DIR` | — | другая папка для данных и `.env`; используется тестами |
@@ -168,20 +168,28 @@ Photo Picker, в котором опции «Камера» нет вообще
3. **По смыслу (эмбеддинги)** — только если по словам ничего не нашлось,
с высоким порогом и с пометкой «похоже по смыслу».
Почему семантика на третьем месте, а не на первом: замер на `nomic-embed-text`
показал, что на русском он почти не разделяет смыслы — «велосипедная камера»
давала мультиметру 0.689, а верное попадание на «паяльник» 0.691. Порогом
такое не разделить, поэтому лучше честное «не нашёл», чем уверенно показанное
не то. Хочется настоящего смыслового поиска — нужен многоязычный эмбеддер:
Эмбеддер — **`bge-m3`**, многоязычный. Прежний `nomic-embed-text` на русском
смыслы почти не разделял: «велосипедная камера» набирала мультиметру 0.704 —
больше верного ответа на «паяльник» (0.691). Порогом такое не разделить.
С `bge-m3` разделение появилось: мусор ушёл ниже 0.46, верные держатся выше 0.53.
Но и с ним семантика остаётся догадкой, а не основой. Замер на настоящей базе
из шести десятков вещей честнее лабораторного: абстрактное «чем посветить»
набирало лампам всего 0.411, а посторонняя «детская коляска» — 0.535. Полностью
они не разделяются, поэтому `SEMANTIC_MIN` в `search.py` выставлен так, чтобы
отсечь весь мусор ценой слабых догадок: помощник, уверенно показывающий не то,
хуже промолчавшего. Точных запросов это не касается — они находятся по словам
и тегам.
**При смене эмбеддера** поменять `EMBED_MODEL` в `config.py`, перемерить порог
(у каждой модели своя шкала) и обязательно пересчитать векторы:
```
ollama pull bge-m3
venv\Scripts\python.exe tools\reindex.py
```
затем в `hlamingo\config.py` сменить `EMBED_MODEL`, обнулить `EMBED_DOC_PREFIX`
и `EMBED_QUERY_PREFIX` и **один раз пересчитать векторы**`search.reindex(db)`.
Пересчёт обязателен: векторы разных моделей несовместимы, и смешанная база
тихо испортит поиск, ничем себя не выдав.
Пересчёт не опция: векторы разных моделей несовместимы, и смешанная база тихо
испортит поиск, ничем себя не выдав. Скрипт сам делает копию базы перед работой.
## Что если Ollama выключен