# -*- coding: utf-8 -*- """Пересчёт векторов после смены модели эмбеддера. Векторы разных моделей несовместимы: если половина базы посчитана одной моделью, а половина другой, косинус между ними — шум, и поиск тихо портится, ничем себя не выдавая. Поэтому при смене EMBED_MODEL нужен полный пересчёт. Запуск (сервер лучше остановить, чтобы не писал в базу одновременно): venv\\Scripts\\python.exe tools\\reindex.py """ import io import os import sys import time import shutil sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) try: sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace") except Exception: pass from hlamingo import store, search, ollama, config # noqa: E402 def main(): if not config.DB_FILE.exists(): print("База пуста — пересчитывать нечего.") return 0 if not ollama.check(): print("Ollama недоступна (%s) — без неё векторы не посчитать." % config.OLLAMA_HOST) return 1 db = store.load() total = len(db["items"]) print("Модель эмбеддера: %s" % config.EMBED_MODEL) print("Вещей в базе: %d" % total) if not total: return 0 # Своя копия рядом с автоматическими: пересчёт трогает каждую запись. backup = config.DATA_DIR / "backups" / ("db-before-reindex-%s.json" % time.strftime("%Y%m%d-%H%M%S")) backup.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(str(config.DB_FILE), str(backup)) print("Копия: %s\n" % backup.name) t0 = time.time() done = 0 for item in db["items"].values(): item["emb"] = None for item in db["items"].values(): vector = ollama.embed(search.item_text(item)) if not vector: print(" не удалось посчитать: %s" % item.get("name")) continue item["emb"] = vector done += 1 print(" [%d/%d] %s" % (done, total, item.get("name"))) store.save(db) print("\nГотово: %d из %d за %.1f с." % (done, total, time.time() - t0)) if done < total: print("Часть векторов не посчиталась — запусти ещё раз, когда Ollama ответит.") return 1 return 0 if __name__ == "__main__": sys.exit(main())