Эмбеддинги и мост к 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 = эмбеддинги + поиск релевантных фрагментов + генерация ответа по ним.