Skip to content

StasPlov/ai-semantic-search

Repository files navigation

AI Semantic Search

Мини-сервис для поиска c ИИ по смыслу на Python + FastAPI + MySQL + sentence-transformers.

Динамические SQL-запросы, маппинг и ИИ-поиск

Как добавить свой запрос к базе

  1. Создайте SQL-файл в папке queries/, например, fetch_by_price.sql:

    SELECT id, name, short_desc, long_desc
    FROM products
    WHERE price >= {{ min_price }} AND price <= {{ max_price }}
    • id обязательно должен быть в SELECT (для идентификации товара)
    • Все остальные поля (например, name, short_desc, long_desc) будут использоваться для ИИ-поиска по смыслу
    • Используйте {{ param }} для параметров, которые будут передаваться через query params
  2. (Опционально) Создайте файл маппинга в папке mappings/ с именем, соответствующим SQL-файлу, например, fetch_by_price.mapping.json:

    {
      "id": "id",
      "title": "name",
      "description": "short_desc"
    }

    Ключ — имя поля в API, значение — имя поля в базе данных.

  3. Перезапустите сервис (или просто обновите файлы, если сервис уже запущен).

  4. Пользуйтесь новым эндпоинтом:

    • Пример: /query/fetch_by_price?min_price=100&max_price=500
    • Все параметры из {{ param }} в SQL автоматически становятся query params.
    • Если есть файл маппинга, результат будет преобразован согласно ему.

Динамический ИИ-поиск по смыслу

  • Любой эндпоинт /query/имя_запроса поддерживает параметр q для поиска по смыслу среди результатов SQL-запроса.
  • Поиск идёт по всем полям из SELECT, кроме id (например, name, short_desc, long_desc и т.д.).
  • Пример:
    GET /query/fetch_by_price?min_price=100&max_price=500&q=аромат вишни
    
    — сначала фильтрует товары по цене, затем ищет по смыслу среди выбранных товаров.

Пример структуры

queries/
  fetch_products.sql
  fetch_by_price.sql
mappings/
  fetch_products.mapping.json
  fetch_by_price.mapping.json

Преимущества

  • Не нужно менять Python-код для новых выборок!
  • Можно адаптировать под любую структуру БД и любые поля.
  • Маппинг позволяет привести результат к нужному API-формату.
  • ИИ-поиск работает по любым полям, которые ты укажешь в SELECT.

Как работает сервис поиска

Подробная схема работы

flowchart TD
    A["Пользователь"]
    B["FastAPI API /query/имя_запроса"]
    C["База данных MySQL"]
    D["Модель sentence-transformers"]
    E["Сортировка по релевантности"]
    F["Форматирует ответ (JSON)"]

    A -- "Отправляет запрос (например, /query/fetch_by_price?q=...)" --> B
    B -- "Выполняет SQL-запрос из queries/" --> C
    C -- "Список товаров" --> B
    B -- "Если есть q: преобразует все поля (кроме id) в эмбеддинги через ИИ" --> D
    D -- "Векторы товаров и запроса" --> B
    B -- "Сравнивает вектор запроса с векторами товаров (косинусное сходство)" --> E
    E -- "Формирует список наиболее подходящих товаров" --> F
    F -- "Отправляет результат пользователю" --> A
Loading

Этапы подробно:

  1. Пользователь отправляет запрос через API (например, /query/fetch_by_price?...&q=что-то).
  2. FastAPI сервис выполняет SQL-запрос из папки queries/ с нужными параметрами.
  3. Сервис получает список товаров (любые поля, которые указаны в SELECT).
  4. Если есть параметр q:
    • Для каждого товара склеиваются все поля (кроме id) в одну строку.
    • Модель sentence-transformers преобразует эти строки и запрос пользователя в эмбеддинги.
    • Сравниваются векторы, выбираются наиболее релевантные товары.
  5. Формируется JSON-ответ и отправляется пользователю.

ИИ в сервисе — это модель sentence-transformers, которая умеет понимать смысл текста и находить похожие товары даже по синонимам и разным формулировкам.


Вопросы и ответы (FAQ)

Где здесь используется искусственный интеллект?

ИИ — это модель sentence-transformers (на базе нейросетей), которая:

  • Понимает смысл текста на естественном языке.
  • Может находить похожие по смыслу тексты, даже если слова не совпадают.
  • Работает локально, не требует внешних API.

Нужно ли обучать модель под свой магазин?

Нет, модель уже обучена (pretrained) на огромных текстовых данных и умеет понимать смысл фраз на многих языках, в том числе на русском. Ты просто используешь её как инструмент: подаёшь текст — получаешь вектор. Для 99% интернет-магазинов стандартная модель работает отлично «из коробки».

Откуда модель берёт знания о языке и смысле?

Модель обучена на больших датасетах (книги, статьи, диалоги и т.д.), которые подготовили разработчики sentence-transformers. Она не знает ничего о твоих товарах заранее, но умеет понимать смысл любых текстов.

Нужно ли интернет-соединение для работы?

  • Интернет нужен только при первом запуске, чтобы скачать модель (~90 МБ).
  • После этого модель хранится локально и сервис работает полностью оффлайн.
  • Все вычисления происходят на твоём сервере, данные никуда не отправляются.

Как происходит поиск?

  1. Все товары из базы превращаются в векторы (эмбеддинги) с помощью ИИ-модели.
  2. Запрос пользователя тоже превращается в вектор.
  3. Сравниваются векторы — находятся товары, которые ближе всего по смыслу к запросу (даже если слова не совпадают).

Можно ли дообучить модель под свои задачи?

Можно, но для большинства магазинов это не требуется. Если у тебя очень специфические товары или сленг, можно дообучить модель, но это сложнее и требует много данных и вычислительных ресурсов.


Дообучение модели поиска

1. Подготовьте датасет пар "запрос — релевантный товар"

Создайте файл train/data/pairs.jsonl с примерами:

{"query": "король дрифта", "positive": "DRIFT KING Дрифт-легенда R32: Аромат скорости и адреналина."}
{"query": "золотая классика", "positive": "GOLDEN BEAST Золотая классика: Аромат власти и совершенства."}
{"query": "аромат вишни", "positive": "Drift Charm Cherry Подвесной ароматизатор с ароматом вишни."}

Каждая строка — отдельный JSON-объект с полями query и positive.

2. Запустите обучение

Выполните:

python train/train_model.py

После завершения обучения дообученная модель будет сохранена в папке train/model_finetuned.

3. Используйте дообученную модель в поиске

В файле app/search_engine.py замените строку:

self.model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')

на

self.model = SentenceTransformer('train/model_finetuned')

Теперь поиск будет работать на вашей дообученной модели!


Установка вручную

  1. Установите зависимости:
pip install -r requirements.txt
  1. Укажите параметры подключения к MySQL в config.py.

  2. Запустите сервер:

uvicorn main:app --reload

Запуск через Docker

  1. Укажите параметры подключения к MySQL в config.py (должны быть доступны из контейнера).
  2. Соберите и запустите сервис:
docker compose up --build
  1. Сервис будет доступен на http://localhost:8000

💖 Support

Thank you so much for using my projects! If you have any questions, you can always ask me here:

If you want to thank me with a coin TON: UQD-ZbaI-tHINZqu1Mg7GgFSCMm857jlvXJXLxSa1zx0JKGH

Telegram Badge