#Веб-поиск + LLM (RAG)
Связка `POST /v1/search` с `POST /v1/ai/chat/completions` для ответов LLM, опирающихся на свежие источники из интернета.
#Сценарий
- AI-агент получает вопрос от пользователя.
- Делает веб-поиск через
/v1/search— получает массивresultsсо ссылками на релевантные страницы. - Передаёт LLM системный промпт с инструкцией цитировать источники по
[N]и блокSources:со спискомid,title,url,content. - LLM формирует ответ с маркерами
[N], которые соответствуютresults[].id.
#Полный пример
const VIBE_KEY = process.env.VIBE_API_KEY
const BASE = 'https://vibecode.bitrix24.tech'
// ── 1. Веб-поиск ────────────────────────────────────────────
const searchRes = await fetch(`${BASE}/v1/search`, {
method: 'POST',
headers: {
'X-Api-Key': VIBE_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: 'обновления Битрикс24 за последний месяц',
search_depth: 'advanced',
max_results: 5,
lang: 'ru',
}),
})
const search = await searchRes.json()
// ── 2. Собираем блок источников для LLM ─────────────────────
const sourcesBlock = search.results
.map((r) => `[${r.id}] ${r.title}\n${r.url}\n${r.content}`)
.join('\n\n')
// ── 3. Запрос к LLM с инструкцией цитировать ────────────────
const chatRes = await fetch(`${BASE}/v1/ai/chat/completions`, {
method: 'POST',
headers: {
'X-Api-Key': VIBE_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'bitrix/bitrixgpt-5.5',
messages: [
{
role: 'system',
content:
'Отвечай только на основе источников ниже. Каждый факт сопровождай маркером [N], где N — id источника.',
},
{
role: 'user',
content: `Вопрос: ${search.query}\n\nИсточники:\n${sourcesBlock}`,
},
],
}),
})
const chat = await chatRes.json()
console.log(chat.choices[0].message.content)
#Стоимость одного цикла
- Поиск: 5 Ꝟ для
bitrix-searchв режимеadvanced. Для BYOK Tavily / Brave — 0 Ꝟ. - LLM: зависит от модели и количества токенов. Прайс — в AI Router.
#Какой провайдер выбрать
- Русскоязычные источники →
provider: "bitrix-search"(используется по умолчанию). Выдача уже содержит синтезированныйanswerс маркерами[N]— иногда LLM-шаг можно пропустить. - Англоязычные источники с фильтрами по доменам или времени →
provider: "tavily"(BYOK). Нужен токен Tavily — добавляется через `POST /v1/search/credentials`. - Англоязычный поиск без синтеза, для RAG поверх своей LLM →
provider: "brave"(BYOK).
Подробнее о различиях — Web Search для AI.
#Потоковый вариант
Когда интерфейс показывает прогресс (chat-приложение, ассистент), используйте stream: true — события приходят по мере готовности.
const streamRes = await fetch(`${BASE}/v1/search`, {
method: 'POST',
headers: {
'X-Api-Key': VIBE_KEY,
'Content-Type': 'application/json',
Accept: 'text/event-stream',
},
body: JSON.stringify({
query: 'обновления Битрикс24 за последний месяц',
search_depth: 'advanced',
stream: true,
}),
})
const reader = streamRes.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
while (true) {
const { value, done } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
let idx
while ((idx = buffer.indexOf('\n\n')) !== -1) {
const block = buffer.slice(0, idx)
buffer = buffer.slice(idx + 2)
const eventLine = block.match(/^event: (.+)$/m)
const dataLine = block.match(/^data: (.+)$/m)
if (!eventLine || !dataLine) continue
const event = eventLine[1]
const payload = JSON.parse(dataLine[1])
if (event === 'thinking') process.stdout.write('.')
if (event === 'answer_delta') process.stdout.write(payload.content)
if (event === 'done') console.log('\nГотово')
}
}
Полный список SSE-событий и полей — `POST /v1/search`.
#Смотрите также
- Web Search для AI — обзор раздела, тарификация, миграция с Tavily
- Поиск (POST /v1/search) — параметры запроса, формат потоковой передачи
- Свои ключи (BYOK) — добавление BYOK-ключей Tavily и Brave
- AI Router — единый интерфейс к чат-моделям
- Лимиты и оптимизация — общие правила частоты запросов