Image

Использование Yandex Embedder на JavaScript

В прошлом примере я рассказал о том, как можно использовать YDB в качестве векторной базы знаний. Сегодня расскажу про то, как использовать Yandex Embedder.

Но сначала несколько слов о том, почему Embedder — это очень важно.

Итак, у нас есть задача: есть некоторая внутренняя система (у моем случае — YouTrack), есть ИИ (не важно какой). Я хочу получать ответы от ИИ с использованием данных из внутренней системы. Классическое решение — это выгрузка данных из внутренней системы в RAG и использование этих данных для контекста в запросе к ИИ. В качестве RAG используется векторная база данных (например YDB). Важным моментом является то, что в контекст запроса к LLM передается не вся база — а только некоторое количество наиболее близких документов («близость» как раз определяется сравнением векторов). То есть, работает так:

  • мы пишем запрос

  • по этому запросу находим релевантные документы в RAG

  • отправляем запрос в LLM передавая найденные документы

Так вот. То, что вам ответит ИИ зависит от того, что вы найдете в RAG. А это в свою очередь зависит от того, насколько «хорошо» будут сгенерированы векторы. За генерацию векторов как раз и отвечает Embedder.

В моем прошлом примере класс сохранения данных в YDB использовал простой embedder из библиотеки ‘@xenova/transformers’ и результат поиска, если честно, был так себе. Поэтому следующей задачей стало использование уже более «правильного» Embedder-а. В моем случае, так как я в данном прототипе ориентирован на максимально использование сервисов Yandex Cloud то и выбор пал на Yandex Embedder. Доступные модели можно посмотреть в AI Studio в каталоге моделей.

af5404fbfd998e3c35a32f4524b2fe02

Нам нужна та, которая называется Yandex Text embedding (query) 1

Ниже приведен код класса для работы с Yandex Embedder:

// yandex-embedder.js export class YandexEmbedder { constructor(options = {}) { this.apiKey = options.apiKey; this.baseURL = options.baseURL; this.modelUri = options.modelUri; this.requestsPerSecond = options.requestsPerSecond || 8; this.delayBetweenRequests = 1000 / this.requestsPerSecond; this.lastRequestTime = 0; console.log(‘🔧 Yandex Embedder configured:’); console.log(‘ — Model Uri:’, this.modelUri); console.log(‘ — Base URL:’, this.baseURL); console.log(‘ — delayBetweenRequests:’, this.delayBetweenRequests + ‘ms’); } async generateEmbedding(text) { const now = Date.now(); const timeSinceLastRequest = now — this.lastRequestTime; // console.log(Date.now() + » timeSinceLastRequest: » + timeSinceLastRequest); if (timeSinceLastRequest < this.delayBetweenRequests) { const waitTime = this.delayBetweenRequests — timeSinceLastRequest; await new Promise(resolve => setTimeout(resolve, waitTime)); } // console.log(Date.now() + » After timer:»); this.lastRequestTime = Date.now(); return await this.makeRequest(text); } async makeRequest(text) { const controller = new AbortController(); try { // console.log(`🔍 Generating embedding for text: «${text.substring(0, 50)}${text.length > 50 ? ‘…’ : »}»`); const response = await fetch(this.baseURL, { method: ‘POST’, headers: { ‘Authorization’: `Api-Key ${this.apiKey}`, ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ modelUri: this.modelUri, text: text }) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Yandex API error: ${response.status} — ${errorText}`); } const data = await response.json(); if (!data.embedding) { throw new Error(‘No embedding in Yandex API response’); } // console.log(`✅ Embedding generated, dimension: ${data.embedding.length}`); return data.embedding; } catch (error) { console.error(‘❌ Error generating Yandex embedding:’, error.message); throw error; } } // Batch генерация эмбеддингов async generateEmbeddings(texts) { console.log(`🔍 Generating embeddings for ${texts.length} texts…`); const embeddings = []; for (let i = 0; i < texts.length; i++) { try { const embedding = await this.generateEmbedding(texts[i]); embeddings.push(embedding); if ((i + 1) % 10 === 0 || i === texts.length — 1) { console.log(`📊 Progress: ${i + 1}/${texts.length}`); } } catch (error) { console.error(`❌ Failed to generate embedding for text ${i + 1}:`, error.message); embeddings.push(null); } } console.log(`✅ Generated ${embeddings.filter(e => e !== null).length}/${texts.length} embeddings`); return embeddings; } }

При инициализации классу необходимо передать несколько параметров:

  • apiKey — ключ созданный для сервисного аккаунта от имени которого вы будете обращаться к сервису. Генерируется, например, в консоли Yandex Cloud

  • baseURL — URL сервиса — чаще всего это https://llm.api.cloud.yandex.net/foundationModels/v1/textEmbedding

  • modelUri — указатель на используемую модель. Чаще всего будет emb://${YourYandexCloudFolderID}/text-search-query/latest — но тоже могут быть нюансы (теоретически вы можете развернуть свою версию модели)

  • requestsPerSecond — количество запросов в сек, которые можно отправить к сервису.

Вот об этом чуть подробней. Сервис Яндекса обрабатывает не более 10-ти запросов в секунду. Так что запросы надо выстраивать в очередь. Реализация очереди может быть самой разной. Так как в моем случае проект в стадии «прототипа» — то я просто поставил таймер между запросами, но в production решении конечно надо придумывать что-то более надежное.

Могу сказать что с использованием Yandex Embedder-а качество ответов, которые стала выдавать мне программа стало прям на порядок лучше.

Надеюсь, этот пример будет кому-то полезен и съэкономит время. Только учтите — это именно пример на уровне прототипа.

Источник: habr.com

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.
dummy-img
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.
dummy-img
dummy-img
Взаимодействие человека и машины погружается под воду.
Взаимодействие человека и машины погружается под воду.
Дифференциально приватное машинное обучение в масштабе с использованием JAX-Privacy
Image Not Found
Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.

Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.

Вкратце Опубликовано: Изображение предоставлено: Thos Robinson/Getty Images для The New York Times (откроется в новом окне) Джули Борт Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.…

Апр 21, 2026
dummy-img

Как почистить виниловые пластинки (2026): пылесос, ультразвук, чистящий раствор, щетка.

Эти щелчки и треск недопустимы. Приведите свою музыку в порядок с помощью этого удобного руководства. Источник: www.wired.com

Апр 21, 2026
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Это сегодняшний выпуск The Download, нашей ежедневной новостной рассылки, которая предоставляет вам ежедневную порцию событий в мире технологий. Кибермошенники обходят системы безопасности банков с помощью незаконных инструментов, продаваемых в Telegram. В центре по отмыванию денег в Камбодже…

Апр 21, 2026
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Это сегодняшний выпуск The Download, нашей ежедневной новостной рассылки, которая предоставляет вам ежедневную порцию событий в мире технологий. Кибермошенники обходят системы безопасности банков с помощью незаконных инструментов, продаваемых в Telegram. В центре по отмыванию денег в Камбодже…

Апр 21, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых