Skip to content

Vaynerov Technologies

Мы не просто разрабатываем — мы создаём каждую строку кода и пиксель.

Все статьиИстории сборки

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

Чат-пузырь есть на сайте каждого агентства. Чаще всего это форма в маскарадном костюме. Наш обязан знать работы, местонахождение цен, границы основателя и все двадцать одно эссе этого Журнала — поэтому мы собрали его так же, как собираем всё остальное, и записали, во что он обошёлся.

Edward AmirainОснователь Vaynerov Technologies
Опубликовано 6 мин чтения
На этой странице
  1. Личность без аккаунта
  2. Всегда 200
  3. Файл, который мы написали для чужих роботов
  4. Учим его Журналу
  5. Когда нас хотят нанять
  6. Числа, которые можно напечатать
  7. Пределы, названные вслух

В углу этой страницы есть небольшая таблетка с надписью спросить студию. За ней — то, что каждый сайт консалтинга обещает с 2016 года и почти ни один не выполнил: чат, который действительно знает компанию, от лица которой говорит. Спросите, что входит в проект веб-платформы, — он перечислит настоящие результаты. Спросите, что мы думаем о сгенерированном коде, — он процитирует эссе. Спросите, где живёт Эдвард, — он вежливо откажется, потому что вместе с фактами мы преподали ему манеры.

Можно было вставить сторонний виджет над футером и пойти дальше. Но мы напечатали под собственным именем мы не просто разрабатываем — мы создаём каждую строку кода и пиксель, и арендованный чат-пузырь, транслирующий чужой брендинг из нашего угла, спорил бы с каждой страницей, над которой всплывает. Поэтому консьерж наш от начала до конца: Supabase Edge Function, модель OpenAI, клиент размером с визитную карточку и слой знаний с историей, которую мы не собирались рассказывать.

Личность без аккаунта

Первое проектное решение — кто такой посетитель. История чата должна переживать перезагрузку страницы — потерять разговор из-за того, что вы заглянули на страницу цен, это самодеятельность, — но никто не хочет заводить аккаунт, чтобы задать вопрос, а мы не хотели поднимать анонимную аутентификацию ради того, что по устройству — гостевая книга с мнениями.

Поэтому личность — это токен: виджет чеканит случайный идентификатор треда и секрет в хранилище вашего браузера, а сервер держит только хеш секрета. Предъявите пару — разговор продолжится; потеряете — просто начнёте заново. Таблицы тредов закрыты на сервисную роль: публичной политики чтения не существует вовсе, так что неправильно настраивать нечего. Это та же форма, что и у токенов доступа, которыми наши страницы со сметами пользуются с первого дня, — ровно поэтому мы ей и доверились.

Всегда 200

Ответы льются токен за токеном по server-sent events, и у транспорта одно правило, унаследованное от генератора /blueprint: ответ — всегда поток событий с HTTP 200, даже когда это дурные вести. Упёрлись в лимит? Это событие error. Токен треда недействителен? Событие error. Альтернатива — голый 4xx после того, как CORS-preflight уже прошёл успешно, — это отказ, который браузер видит, а ваш JavaScript прочитать не может: худшее из обоих миров.

Поток несёт не только текст. Когда модель заканчивает, событие done доставляет идентификатор сохранённого ответа — на нём и держатся маленькие «пальцы» под ответом. Когда посреди разговора пойман лид, событие lead сообщает об этом странице, чтобы наша аналитика его посчитала. Протокол шириной в три глагола, и таким мы намерены его держать.

Злоупотребления ограничены арифметикой, а не оптимизмом: десять запросов в минуту на адрес через тот же долговечный ограничитель, что и у контактных форм, две тысячи символов на сообщение, окно контекста в двадцать сообщений, тысяча токенов на ответ. Боту, желающему потратить наш бюджет на инференс, придётся встать в очередь за чужими curl.

Файл, который мы написали для чужих роботов

Интересной задачей было знание. Консьерж, отвечающий из общей выучки модели, — это неприятность в хорошем костюме: он выдумает услуги, которых мы не продаём, и цены, которых мы не называли. Всё, что он говорит о студии, должно исходить от студии.

А вот часть, которую мы не планировали. Несколько месяцев назад мы опубликовали /llms-full.txt — машиночитаемый дайджест всего сайта, поддерживаемый автоматически из того же контента, что рендерят страницы, — чтобы чужие AI-ассистенты описывали нас точно. Когда мы отправились искать корпус для заземления собственного консьержа, он уже лежал на месте: актуальный, полный и полгода как испытанный чужими роботами. Функция забирает его, ненадолго кеширует и вручает модели с каждым вопросом. Файл, написанный для чужих роботов, оказался мозгом нашего.

Три яруса, один ответ: неизменный канон, живой дайджест сайта и всё, что Журналу есть сказать по вашему вопросу.

Поверх дайджеста — ещё два яруса. Короткий, написанный от руки канон несёт правила, которым нельзя дрейфовать: запрещённые слова бренда, отказ выдумывать числа и профиль основателя с явной границей — всё, что консьержу позволено говорить об Эдварде лично, умещается в шесть пунктов, и седьмой ему предписано отклонять. Не потому, что иначе модель принялась бы сплетничать, а потому, что пределы публичного бота должны быть проектным решением, записанным на бумаге, а не эмерджентным свойством.

Учим его Журналу

Третий ярус — этот Журнал. Двадцать одно эссе о том, как мы строим вещи, — ровно тот материал, которого требуют самые трудные вопросы посетителя: как вы сделали Safari быстрым, что сломалось в музее, зачем вообще публиковать цены, — но при своих примерно шестидесяти тысячах слов он не может ездить в каждом запросе.

Поэтому эссе нарезаются на пассажи и превращаются в векторы, и каждый входящий вопрос эмбеддится тем же способом и сверяется с ними. Четыре ближайших пассажа выше порога схожести едут вместе с промптом; модели велено свободно цитировать и ссылаться на источник. Спросите, как мы ускорили мобильный Safari, — и консьерж ответит настоящими числами из /articles/making-mobile-safari-fast: TTFB от 250 до 950 миллисекунд, ставший однозначным, 91 килобайт JavaScript, покинувший начальный бандл, — потому что он читает те же абзацы, что читали бы вы.

Индекс пересобирается автоматически при каждом деплое. Что порождает фразу, которую приятно набирать: к моменту, когда вы это читаете, консьерж это уже прочитал. Статьи о машине становятся частью машины — спросите его, как он устроен, и он процитирует вам эту самую страницу.

Когда нас хотят нанять

У чата на сайте студии одна коммерческая задача: заметить момент, когда разговор перестаёт быть любопытством и становится проектом. Для этого у модели один-единственный инструмент — она может завести лид с именем, почтой и брифом в одну строку, и ей предписано использовать его не более одного раза, только с данными, которые посетитель действительно напечатал, и никогда не спрашивать дважды. Лид ложится в ту же таблицу, что и у контактной формы, студии приходит уведомление, а посетитель получает одно предложение подтверждения вместо серии писем-догонялок.

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

Числа, которые можно напечатать

~5,800
промпт-токенов едет с каждым вопросом
130
пассажей Журнала в векторном индексе
6
локалей, на которых консьерж здоровается
10/min
запросов на посетителя, прежде чем возразит ограничитель

Измерено в день релиза, а не оценено — ответ, породивший счётчик токенов, целиком гласил: «OK».

Каждый ответ записывает собственные токен-квитанции в базу, так что месячная стоимость консьержа — это запрос к базе, а не догадка. Мы видим и то, какие ответы зарабатывают палец вверх, а какие нет: оценки ложатся рядом с квитанциями. Функция, которую нельзя измерить, — это функция, которую нельзя защитить; эта выходит с собственной бухгалтерией.

Пределы, названные вслух

  • Индекс Журнала пока только английский. Межъязыковое сопоставление срабатывает чаще, чем имеет право, но русский вопрос встречает английские пассажи; честное решение — заэмбеддить переведённые эссе, и оно в списке.
  • Модель видит последние двадцать сообщений треда. Начало длинного разговора со временем выпадает из виду; скользящее резюме спроектировано, но не построено.
  • Ограничение частоты — на адрес, так что офис за одним роутером делит одну квоту. Пока в неё никто не упёрся; в день, когда это случится, ключ поумнеет.
  • Консьерж говорит от имени студии, но остаётся языковой моделью. Он заземлён, ограничен и измерен — и если он когда-нибудь скажет то, чего сайт не говорит, прав сайт.

Уместен ли чат на сайте студии вообще — вопрос справедливый: мы написали целое эссе об инструментах, которые вас уважают, а плохой консьерж — их противоположность. Наш ответ — держать его по той же планке, что и всё остальное здесь: он стримит, потому что заставлять ждать невежливо; отказывает, потому что границы — тоже контент; цитирует, потому что читал источники; и уходит, когда вы на странице, у которой своя мебель. Музей держит собственный чат — наш остаётся за кадром.