Введение в векторные представления (Embeddings) с Gemini

40 минут Урок 19

Введение в векторные представления (Embeddings) с Gemini

Добро пожаловать в четвертый модуль курса. До этого момента мы взаимодействовали с Gemini в основном посредством текстовых промптов, отправляя инструкции и получая ответы. Мы полагались на «врожденные» знания модели или контекст, который вручную помещали в окно ввода.

Однако, когда речь заходит о создании Enterprise-решений, работе с длинным контекстом и реализации долгосрочной памяти, простой отправки текста недостаточно. Нам нужен способ эффективно искать, сортировать и сравнивать огромные массивы информации, прежде чем передать их в LLM. Здесь на сцену выходят векторные представления или эмбеддинги (embeddings).

Что такое эмбеддинги?

Представьте, что вы библиотекарь в самой большой библиотеке мира. Если книги расставлены по цвету обложки, найти нужную информацию о «квантовой физике» будет невозможно. Если они расставлены по алфавиту — чуть проще, но вам всё равно нужно знать точное название.

Эмбеддинги — это способ расстановки книг (данных) по смыслу. В мире машинного обучения эмбеддинг — это перевод текста (слова, предложения или целого документа) в последовательность чисел (вектор). Но это не случайные числа.

  • Слова с похожим смыслом будут иметь похожие векторы.
  • Векторы «король» и «королева» будут находиться в математическом пространстве так же близко друг к другу, как «мужчина» и «женщина».

Для Gemini текст — это не просто набор букв, а точка в многомерном семантическом пространстве. Используя API эмбеддингов Gemini, мы можем превратить любой текст в такой вектор и использовать математику для поиска смысловых связей.

Как это работает: От слов к цифрам

Традиционный поиск работает по ключевым словам (keyword search). Если вы ищете «мобильный телефон», система не найдет документы, где написано только «смартфон» или «iPhone», пока вы явно не пропишете синонимы.

Семантический поиск на основе эмбеддингов решает эту проблему. Модель Gemini обучена на колоссальном объеме данных и «понимает», что понятия «мобильный телефон», «гаджет», «сотовая связь» и «Android» семантически близки.

Когда мы запрашиваем эмбеддинг у Gemini, модель возвращает нам массив чисел с плавающей точкой. Например, модель text-embedding-004 обычно возвращает вектор размерностью 768. Это означает, что смысл вашего текста описывается координатами по 768 осям.

Ключевая концепция: Чем ближе два вектора друг к другу в этом 768-мерном пространстве, тем более схож их смысл.

python
import google.generativeai as genai
import os

# Настройка API ключа
# Предполагается, что ключ сохранен в переменных окружения
genai.configure(api_key=os.environ["GEMINI_API_KEY"])

# Текст для векторизации
text = "Искусственный интеллект меняет мир разработки ПО."

# Получение эмбеддинга
# Используем актуальную модель text-embedding-004
result = genai.embed_content(
    model="models/text-embedding-004",
    content=text,
    task_type="retrieval_document",
    title="AI Tech Intro" # Опционально, полезно для document retrieval
)

# Вывод результатов
embedding_vector = result['embedding']

print(f"Первые 10 компонентов вектора: {embedding_vector[:10]}")
print(f"Общая размерность вектора: {len(embedding_vector)}")

Типы задач (Task Types) в Gemini API

Одной из отличительных особенностей Gemini API является параметр task_type. Многие разработчики игнорируют его, используя настройки по умолчанию, но для Enterprise-решений это критически важно.

Почему это нужно? Контекст использования вектора меняет то, как мы хотим его представить. Вопрос пользователя и текст абзаца из учебника играют разные роли. Gemini оптимизирует векторы в зависимости от вашей цели.

Основные типы задач:

  • RETRIEVAL_QUERY: Используется для текста запроса (вопроса) пользователя. Например: «Как приготовить борщ?». Вектор будет оптимизирован так, чтобы «тянуться» к ответам.
  • RETRIEVAL_DOCUMENT: Используется для текстов, по которым будет производиться поиск (база знаний).
  • SEMANTIC_SIMILARITY: Для сравнения схожести двух небольших текстов (например, оценка эссе студентов).
  • CLASSIFICATION: Если векторы будут использоваться как входные данные для модели классификатора.
  • CLUSTERING: Для задач кластеризации (группировки данных).

Если вы создаете систему RAG (Retrieval Augmented Generation), вы будете использовать RETRIEVAL_DOCUMENT при индексации вашей базы данных и RETRIEVAL_QUERY, когда пользователь задает вопрос к этой базе.

Измерение расстояния: Косинусное сходство

Получив векторы, мы должны научиться их сравнивать. Самый популярный метод в NLP (Natural Language Processing) — это Косинусное сходство (Cosine Similarity).

Не пугайтесь математического термина. По сути, мы измеряем косинус угла между двумя векторами.

  • Если векторы указывают в одном направлении (угол 0°), косинус равен 1. Это означает полное совпадение смысла.
  • Если векторы перпендикулярны (угол 90°), косинус равен 0. Смыслы не пересекаются.
  • Если векторы направлены в разные стороны (угол 180°), косинус равен -1. Смыслы противоположны.

В отличие от Евклидова расстояния (которое измеряет длину прямой линии между точками), косинусное сходство менее чувствительно к длине текста (магнитуде вектора) и больше фокусируется на сути содержимого.

Давайте посмотрим, как реализовать сравнение на практике.

python
import numpy as np

def cosine_similarity(v1, v2):
    """
    Вычисляет косинусное сходство между двумя векторами.
    """
    dot_product = np.dot(v1, v2)
    norm_v1 = np.linalg.norm(v1)
    norm_v2 = np.linalg.norm(v2)
    return dot_product / (norm_v1 * norm_v2)

# Определим три фразы
phrases = [
    "Как научиться программировать на Python?",  # Запрос 1
    "Лучшие курсы по языку Python для новичков", # Ответ 1 (релевантный)
    "Рецепт вкусного яблочного пирога"           # Ответ 2 (нерелевантный)
]

# Получаем эмбеддинги для всех фраз пакетом (batch)
result = genai.embed_content(
    model="models/text-embedding-004",
    content=phrases,
    task_type="semantic_similarity"
)

vectors = result['embedding']
query_vector = vectors[0]
relev_doc_vector = vectors[1]
irrelev_doc_vector = vectors[2]

# Считаем сходство
sim_relevant = cosine_similarity(query_vector, relev_doc_vector)
sim_irrelevant = cosine_similarity(query_vector, irrelev_doc_vector)

print(f"Сходство (Запрос vs Курсы): {sim_relevant:.4f}")
print(f"Сходство (Запрос vs Пирог): {sim_irrelevant:.4f}")

# Ожидаемый результат: первое число должно быть значительно выше второго

Применение эмбеддингов в реальных задачах

Теперь, когда мы понимаем механизм, давайте рассмотрим, где это применяется в контексте модуля «Работа с длинным контекстом и памятью».

  1. Семантический поиск (Semantic Search): Вместо того чтобы заставлять пользователя угадывать ключевые слова, вы позволяете ему описывать проблему своими словами.
  2. RAG (Retrieval-Augmented Generation): Это главная техника для обхода ограничений контекстного окна. У вас может быть база знаний на 10 000 страниц. Вы не можете отправить их все в промпт. Вы векторизуете базу знаний, сохраняете в векторную БД. Когда приходит вопрос, вы ищете топ-3 самых релевантных куска текста (через косинусное сходство) и отправляете в Gemini только их.
  3. Классификация без обучения (Zero-shot classification): Вы можете сравнивать вектор текста с векторами названий категорий (например, «Спорт», «Политика», «Технологии») и относить текст к той категории, к которой он ближе, без тренировки модели.
  4. Рекомендательные системы: Если пользователю понравилась статья А, найдите в базе статьи с максимально похожими векторами.

Особенности модели text-embedding-004

Gemini предлагает несколько моделей. text-embedding-004 — наиболее современная и эффективная (на момент создания этого урока). Важно помнить:

  • Лимит токенов на вход: Модель может принять только определенное количество токенов (обычно 2048). Если текст длиннее, его нужно разбивать на части (chunking). О стратегиях чанкинга мы поговорим в следующем уроке.
  • Размерность: Вы можете запросить усеченный вектор (меньше 768 измерений), если нужно экономить место в базе данных, но это может незначительно снизить точность.

Упражнение

Создайте мини-систему классификации новостей. <br>1. Дан список заголовков: <br> - 'Акции технологических компаний растут на фоне отчетов'<br> - 'Новый вид бабочек обнаружен в Амазонии'<br> - 'Футбольный матч закончился со счетом 2:0'<br>2. Даны категории: 'Экономика', 'Природа', 'Спорт'.<br>3. Напишите скрипт, который берет один произвольный заголовок (например, про бабочек) и автоматически определяет для него правильную категорию, сравнивая его вектор с векторами категорий.

Вопрос

Вы разрабатываете систему «Вопрос-Ответ» (QA bot) для корпоративной документации. Вы используете Gemini Embeddings. Какой task_type следует выбрать при генерации вектора для ВОПРОСА пользователя, и какой для ДОКУМЕНТОВ в базе?