Перейти к основному содержанию
Эмбеддинг — это представление текста в виде вектора (списка чисел). Близкие по смыслу фразы дают близкие векторы, даже если в них нет общих слов. На этом строится семантический поиск: вы ищете не по совпадению слов, а по смыслу. И именно это лежит в основе RAG (retrieval-augmented generation) — когда модель отвечает, опираясь на ваши документы. Эмбеддинги в RuAPI работают через тот же OpenAI-совместимый эндпоинт, что и чат: https://www.ruapi.ai/v1, тот же ключ sk-.... Менять в коде нужно только base_url.
Если вы ещё не получили ключ — начните с Быстрого старта. Дальше предполагается, что ключ sk-... у вас уже есть.

Первый вектор

Python (OpenAI SDK)
from openai import OpenAI

client = OpenAI(
    api_key="sk-ВАШ_КЛЮЧ",
    base_url="https://www.ruapi.ai/v1",
)

resp = client.embeddings.create(
    model="text-embedding-3-small",
    input="Москва — столица России",
)

vector = resp.data[0].embedding
print(len(vector))   # размерность вектора
print(vector[:5])    # первые пять чисел
resp.data — это список: на один входной текст приходится один элемент с полем .embedding. У text-embedding-3-small вектор содержит 1536 чисел. Нужно качество повыше — возьмите text-embedding-3-large (3072 числа на вектор). Он точнее на сложных текстах, но дороже и медленнее. Для большинства задач -small достаточно.

Сразу несколько текстов

Передавайте список в input — за один запрос вернётся вектор для каждого элемента. Это и быстрее, и дешевле, чем слать тексты по одному.
resp = client.embeddings.create(
    model="text-embedding-3-small",
    input=[
        "Как пополнить баланс?",
        "Минимальная сумма пополнения — 10 USDT.",
        "Кошка спит на подоконнике.",
    ],
)

vectors = [item.embedding for item in resp.data]
Порядок ответов совпадает с порядком входных текстов.

Сквозной RAG за пять шагов

Идея простая: заранее разбиваем документы на куски и считаем для них векторы, а на запрос пользователя находим самые близкие куски и отдаём их чат-модели как контекст. 1. Разбиваем текст на куски (chunks). Слишком длинные куски «размывают» смысл, слишком короткие теряют контекст. Обычно берут абзацы или окна по 200-500 слов.
docs = [
    "RuAPI принимает оплату в USDT. Минимум — 10 USDT.",
    "Эмбеддинги и чат используют один ключ и один base_url.",
    "Базовый адрес для OpenAI-совместимых клиентов — https://www.ruapi.ai/v1",
]
2. Считаем векторы и складываем их в хранилище. На небольшом объёме хватит обычного списка в памяти. Для продакшена возьмите векторную базу — FAISS, pgvector или Chroma; они умеют быстро искать по миллионам векторов.
import numpy as np

emb = client.embeddings.create(model="text-embedding-3-small", input=docs)
index = np.array([item.embedding for item in emb.data])
3. Считаем вектор запроса — тем же эмбеддингом, что и документы (это важно, см. ниже).
question = "Сколько минимум нужно для пополнения?"
q = np.array(
    client.embeddings.create(
        model="text-embedding-3-small", input=question
    ).data[0].embedding
)
4. Ищем ближайшие куски по косинусной близости. Косинус измеряет угол между векторами: 1 — почти одинаковы, 0 — не связаны.
def cosine(a, b):
    return a @ b / (np.linalg.norm(a) * np.linalg.norm(b))

scores = [cosine(q, v) for v in index]
top = sorted(range(len(scores)), key=lambda i: scores[i], reverse=True)[:2]
context = "\n".join(docs[i] for i in top)
5. Отдаём найденное чат-модели. Лучшие куски кладём в системный промпт как контекст — модель отвечает по делу, а не наугад. Под ответ подойдёт любая чат-модель тем же ключом — например, из линейки GPT.
answer = client.chat.completions.create(
    model="claude-opus-4-8",
    messages=[
        {"role": "system", "content": f"Отвечай только по контексту:\n{context}"},
        {"role": "user", "content": question},
    ],
)

print(answer.choices[0].message.content)
Векторную базу из шага 2 считают один раз и переиспользуют — пересчитывать эмбеддинги на каждый запрос не нужно.

Подводные камни

Векторы из text-embedding-3-small и text-embedding-3-large несравнимы между собой — у них разная размерность и разное пространство смыслов. Каким эмбеддингом построили индекс, тем же считайте и вектор запроса. Сменили модель — пересоберите весь индекс заново.
Отправлять тексты по одному — медленно и дороже по числу запросов. Передавайте список в input (обычно до нескольких сотен строк за раз) — ответы вернутся в том же порядке.
text-embedding-3-small — 1536 чисел на вектор, дешевле и быстрее, подходит для большинства задач. text-embedding-3-large — 3072 числа, точнее на сложных и длинных текстах, но дороже и занимает вдвое больше места в хранилище. Начните с -small и переходите на -large, только если качества поиска не хватает.

Что дальше

  • Быстрый старт — регистрация, ключ и первый запрос
  • Справочник API — эндпоинты, протоколы и базовые адреса
  • LangChain — готовые цепочки и RAG поверх RuAPI без ручного кода