Эмбеддинги и мост к RAG

Чтобы искать по смыслу, а не по словам, текст превращают в вектор чисел — эмбеддинг.

Эмбеддинг — числовой вектор, представляющий смысл текста так, что близкие по смыслу тексты дают близкие векторы.

Зачем это нужно

Обычный поиск по ключевым словам не найдёт «как вернуть товар» по запросу «оформить возврат покупки», если слова не совпали. Эмбеддинги решают это: оба текста переводятся в векторы, и их близость в пространстве отражает близость смысла. Это фундамент семантического поиска и RAG.

Как получить эмбеддинг

У OpenAI есть отдельный эндпоинт embeddings; Anthropic рекомендует партнёрских провайдеров эмбеддингов. Принцип один: шлёте текст — получаете вектор (обычно сотни-тысячи чисел).

from openai import OpenAI
client = OpenAI()

resp = client.embeddings.create(
    model="text-embedding-3-small",
    input="как оформить возврат покупки",
)
vector = resp.data[0].embedding   # список из ~1536 чисел
print(len(vector))

Как из этого получается RAG

1. Заранее: разбить базу знаний на куски, получить эмбеддинг каждого, сложить в векторную БД.
2. Запрос: получить эмбеддинг вопроса пользователя.
3. Поиск: найти куски с самыми близкими векторами (по косинусной близости).
4. Генерация: подложить найденные куски в промпт LLM и попросить ответить по ним.

Так LLM отвечает по вашим данным, даже если их не было в обучении, и не выходит за контекстное окно — в промпт идут только релевантные фрагменты.

Косинусная близость (запускаемо)

Близость двух векторов меряют косинусом угла между ними: 1 — почти одинаковы, 0 — не связаны. Посчитаем на игрушечных векторах — чистый Python:

import math

def cosine(a, b):
    dot = sum(x*y for x, y in zip(a, b))
    na = math.sqrt(sum(x*x for x in a))
    nb = math.sqrt(sum(y*y for y in b))
    return dot / (na * nb)

# Игрушечные «эмбеддинги» (на деле — сотни чисел от API)
query = [0.1, 0.3, 0.9]
docs = {
    "док про погоду":  [0.0, 0.2, 1.0],
    "док про финансы": [0.9, 0.1, 0.0],
    "док про климат":  [0.2, 0.4, 0.8],
}
scored = sorted(((cosine(query, v), name) for name, v in docs.items()), reverse=True)
for score, name in scored:
    print(f"{score:.3f}  {name}")
print("Самый релевантный:", scored[0][1])

Вывод:

0.987  док про погоду
0.984  док про климат
0.139  док про финансы
Самый релевантный: док про погоду

Итог

  • Эмбеддинг превращает текст в вектор смысла; близкие смыслы — близкие векторы.
  • Близость меряют косинусом; это основа семантического поиска.
  • RAG = эмбеддинги + поиск релевантных фрагментов + генерация ответа по ним.
Проверьте себя
1. Что такое эмбеддинг текста?
AСжатая копия текста
BЧисловой вектор, представляющий смысл так, что близкие по смыслу тексты дают близкие векторы
CПеревод текста на английский
DХеш строки
2. Какой метрикой обычно меряют близость двух эмбеддингов?
AДлиной строки
BКосинусной близостью (косинусом угла между векторами)
CЧислом совпавших слов
DРазницей в количестве токенов
3. Какова роль эмбеддингов в RAG?
AОни генерируют финальный ответ
BОни позволяют найти релевантные фрагменты по смыслу, которые затем подкладывают в промпт LLM
CОни заменяют системный промпт
DОни кэшируют запросы
Поддержать проект