Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Векторные представления текста
embeddings

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

Embeddings: как превратить текст в числа, модели для создания эмбеддингов и работа с ними

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

Текст — это не просто строка. Это точка в многомерном пространстве смыслов.

#Что такое embeddings и зачем они нужны

Компьютеры не понимают слова. Они понимают числа. Embedding — это способ превратить текст (слово, предложение, абзац) в вектор чисел, который capture-ит смысл текста, а не просто его поверхность.

Ключевая идея embeddings: семантически близкие тексты находятся близко в векторном пространстве. Если вычислить расстояние между векторами двух похожих предложений — оно будет маленьким. Если между векторами совершенно разных текстов — большим.

Это и есть основа RAG: мы превращаем вопрос пользователя в вектор, ищем ближайшие векторы чанков в базе и получаем релевантные документы по смыслу, а не по ключевым словам.

#Как работают embedding-модели

Embedding-модель — это нейронная сеть, обученная так, чтобы похожие тексты имели близкие векторы. На вход она принимает текст, на выходе отдаёт массив чисел фиксированной длины.

# Пример: embedding через sentence-transformers from sentence_transformers import SentenceTransformer model = SentenceTransformer("all-MiniLM-L6-v2") texts = [ "Кошка сидит на диване", "Кот расположился на софе", "Акции Apple выросли на 5 процентов" ] embeddings = model.encode(texts) print(f"Размерность каждого embedding: {embeddings.shape[1]}") # Размерность: 384 — фиксированное число для этой модели

Модель all-MiniLM-L6-v2 создаёт векторы размерности 384. Это значит, что любой текст — хоть одно слово, хоть целый абзац — превращается в 384 числа.

#Размерность вектора: что выбрать

Разные модели создают embeddings разной размерности:

МодельРазмерностьСкоростьКачество
all-MiniLM-L6-v2384БыстраяХорошее для большинства задач
all-mpnet-base-v2768СредняяВысокое качество
multilingual-e5-large1024МедленнаяОтличное, поддержка многих языков
OpenAI text-embedding-3-small1536API-запросВысокое
OpenAI text-embedding-3-large3072API-запросОчень высокое

Большая размерность не всегда означает лучшее качество. Для русского языка и большинства RAG-задач модели с 384–768 измерениями вполне достаточно.

#Косинусное сходство: как сравнивать векторы

После того как мы получили векторы, нужно понять, насколько они похожи. Основная метрика — косинусное сходство (cosine similarity).

Косинусное сходство измеряет угол между двумя векторами:

  • 1.0 — векторы идентичны по направлению (тексты очень похожи)
  • 0.0 — векторы перпендикулярны (тексты не связаны)
  • -1.0 — векторы противоположны (тексты противоречат друг другу)
import numpy as np from sklearn.metrics.pairwise import cosine_similarity # Два embedding-вектора vec1 = np.array([[0.1, 0.5, -0.3, 0.8]]) vec2 = np.array([[0.15, 0.48, -0.28, 0.75]]) vec3 = np.array([[-0.5, 0.1, 0.9, -0.2]]) sim_12 = cosine_similarity(vec1, vec2)[0][0] sim_13 = cosine_similarity(vec1, vec3)[0][0] print(f"Сходство 1-2: {sim_12:.4f}") # ~0.99 — очень похожи print(f"Сходство 1-3: {sim_13:.4f}") # ~0.5 — менее похожи

В RAG мы используем косинусное сходство, чтобы ранжировать чанки по релевантности запросу. Чем выше сходство — тем релевантнее чанк.

#Локальные модели vs API-сервисы

Есть два способа получать embeddings:

#Локальные модели (sentence-transformers)

from sentence_transformers import SentenceTransformer model = SentenceTransformer("intfloat/multilingual-e5-small") embedding = model.encode("Привет, мир!")

Плюсы:

  • Бесплатно — никаких API-ключей и платежей
  • Приватность — данные не покидают ваш компьютер
  • Оффлайн-работа — не нужен интернет
  • Мультиязычность — модели вроде multilingual-e5 понимают русский

Минусы:

  • Нужны ресурсы CPU/GPU — на больших объёмах медленно без GPU
  • Нужно скачивать модель (сотни мегабайт)
  • Качество может уступать проприетарным API

#API-сервисы (OpenAI, Cohere)

from openai import OpenAI client = OpenAI(api_key="your-key") response = client.embeddings.create( model="text-embedding-3-small", input="Привет, мир!" ) embedding = response.data[0].embedding

Плюсы:

  • Высокое качество embeddings
  • Не нужны локальные ресурсы — всё на серверах провайдера
  • Простота использования — один HTTP-запрос

Минусы:

  • Плата за каждый запрос — стоимость зависит от количества токенов
  • Данные уходят на чужие серверы — важно для конфиденциальных документов
  • Нужен интернет — не работает оффлайн
  • Задержки сети — каждый запрос добавляет 100–500 мс

#Мультиязычные embeddings

Для русского языка важно использовать мультиязычные модели. Не все embedding-модели поддерживают кириллицу.

from sentence_transformers import SentenceTransformer # Мультиязычная модель — работает с русским текстом model = SentenceTransformer("intfloat/multilingual-e5-small") rus_texts = ["Как дела?", "Привет мир", "Векторные представления текста"] embeddings = model.encode(rus_texts) print(f"Количество embeddings: {len(embeddings)}") print(f"Размерность: {embeddings.shape[1]}")

Модели, работающие с русским языком:

  • intfloat/multilingual-e5-small (384) — лёгкая, хорошая для старта
  • intfloat/multilingual-e5-base (768) — баланс скорости и качества
  • intfloat/multilingual-e5-large (1024) — лучшее качество, но медленнее
  • sentence-transformers/paraphrase-multilingual-mpnet-base-v2 (768)

#Нормализация векторов

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

import numpy as np vector = np.array([3.0, 4.0]) normalized = vector / np.linalg.norm(vector) print(f"Длина нормализованного вектора: {np.linalg.norm(normalized):.4f}") # Длина: 1.0000

Хорошая новость: большинство современных embedding-библиотек и векторных БД делают нормализацию автоматически.

#Практический пример: поиск похожих документов

Вот полный пример использования embeddings для семантического поиска:

from sentence_transformers import SentenceTransformer from sklearn.metrics.pairwise import cosine_similarity import numpy as np # 1. Загружаем модель model = SentenceTransformer("intfloat/multilingual-e5-small") # 2. Наша «база документов» documents = [ "Отпуск оформляется через портал HR-системы", "Больничный лист нужно отнести в бухгалтерию", "Новый офис откроется на улице Ленина в январе", "Зарплата выплачивается дважды в месяц", "Корпоративный проездной можно получить в отделе кадров" ] # 3. Создаём embeddings для всех документов doc_embeddings = model.encode(documents) # 4. Вопрос пользователя query = "Как получить медицинскую страховку?" query_embedding = model.encode([query]) # 5. Находим самый похожий документ similarities = cosine_similarity(query_embedding, doc_embeddings)[0] most_similar_idx = np.argmax(similarities) print(f"Вопрос: {query}") print(f"Самый релевантный документ: {documents[most_similar_idx]}") print(f"Сходство: {similarities[most_similar_idx]:.4f}")

Этот пример демонстрирует суть RAG-retrieval: вопрос и документы представлены как векторы, и мы находим ближайший по косинусному сходству.

#Batch-обработка embeddings

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

def embed_in_batches(texts, model, batch_size=32): """Создаёт embeddings батчами для экономии памяти.""" all_embeddings = [] for i in range(0, len(texts), batch_size): batch = texts[i:i + batch_size] batch_embeddings = model.encode(batch, show_progress_bar=False) all_embeddings.extend(batch_embeddings.tolist()) return all_embeddings # Пример использования large_doc_list = ["Документ 1", "Документ 2"] * 100 # 200 документов embeddings = embed_in_batches(large_doc_list, model, batch_size=64) print(f"Создано {len(embeddings)} embeddings")

Batch-обработка особенно важна при работе с GPU — она загружает видеокарту полностью и ускоряет процесс в разы.

Далее: Векторные базы данных