Инженерный блог

«Сен кімсің?»: Как мы подключили Vertex AI к WhatsApp и научили ЦОН-бота понимать шала-казахский

12.08.2026
Шарафутдинов Р.

Каждый казахстанец хотя бы раз в жизни испытывал эту боль. Вы пишете в официальный WhatsApp-бот какого-нибудь ведомства или банка: «Сәлеметсіз бе! Менің ЭЦП кілтімнің мерзімі өтіп кетті, қалай жаңартсам болады? Только без похода в ЦОН, пожалуйста». А в ответ получаете бездушное:

  • [1] Узнать статус заявки
  • [2] Адреса отделений
  • [3] Позвать оператора (Ожидание: 4 часа)

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

Месяц назад к нам в OZAT обратился крупный квазигосударственный сектор с задачей: «Нам нужен умный ассистент для WhatsApp. Он должен консультировать по госуслугам, бронировать очередь и, самое главное, разговаривать с людьми как живой человек, понимая сленг и опечатки». Мы сразу поняли — время расчехлять Vertex AI и модели Gemini.

Почему именно Gemini и Vertex AI?

В мире LLM (Large Language Models) много крутых игроков. Но для проектов в госсекторе и финтехе Казахстана у Google Cloud (а именно Vertex AI) есть два убийственных преимущества:

  1. Мультиязычность из коробки. Gemini (особенно последние модели 1.5 Pro и Flash) феноменально хорошо понимает казахский язык. Более того, модель не «спотыкается», когда пользователь переключается между языками прямо посреди предложения.
  2. Enterprise Security (GDPR/SOC2). Использовать публичный API ChatGPT или Claude для обработки данных граждан — это прямой путь к уголовному делу или огромным штрафам. Данные, отправляемые в Vertex AI, не используются для дообучения базовых моделей Google, а весь трафик можно изолировать внутри VPC Service Controls. Данные не покидают защищенный периметр.

Архитектура решения: От WhatsApp до LLM и обратно

Мы построили легковесную и бесконечно масштабируемую serverless-архитектуру на базе сервисов GCP. Никаких виртуальных машин, которые нужно администрировать — только код и управляемые сервисы.

  1. WhatsApp Business API: Принимает сообщения от пользователей и шлет Webhook на наш бэкенд.
  2. Cloud Run: Сервис на Node.js (TypeScript), который выступает в роли оркестратора. Он валидирует вебхук, извлекает текст и управляет бизнес-логикой.
  3. Firestore: NoSQL база данных, где мы храним контекст диалога (Memory) для каждого номера телефона.
  4. Vertex AI (Gemini 1.5 Flash): Наш «мозг», который понимает текст, принимает решения и формулирует ответы. Скорость Flash-модели идеальна для чатов (ответ генерируется за 1-1.5 секунды).
  5. Google Cloud Secret Manager: Хранит API-ключи от WhatsApp и токены внутренних систем.

Инициализация Vertex AI на TypeScript

Для работы с Vertex AI мы используем официальный SDK от Google @google/genai. Важный момент: мы используем метод аутентификации через Application Default Credentials (ADC), который автоматически подхватывает сервисный аккаунт нашего Cloud Run. Никаких хардкодов JSON-ключей!

import { GoogleGenAI } from '@google/genai';

// Инициализация клиента Vertex AI.
// Так как код крутится в Cloud Run, учетные данные (ADC)
// и проект подтягиваются автоматически из среды окружения.
const ai = new GoogleGenAI();

export async function generateBotReply(userMessage: string, chatHistory: any[]) {
  // Формируем системный промпт (System Instruction), 
  // задающий персону и ограничения нашего ЦОН-бота
  const systemInstruction = `
Ты — официальный виртуальный ассистент Центров Обслуживания Населения (ЦОН) Казахстана.
Твоя цель — вежливо и точно консультировать граждан по вопросам получения госуслуг.
Правила:
1. Отвечай на том языке, на котором пишет пользователь. Если пользователь использует смешанный (шала-казахский), старайся отвечать на чистом казахском или русском, в зависимости от преобладающего языка.
2. Будь краток и эмпатичен. Никаких длинных простыней текста.
3. Никогда не запрашивай полный ИИН в целях безопасности, проси только последние 4 цифры для верификации, если это необходимо для вызова функции.`;

  const response = await ai.models.generateContent({
    model: 'gemini-1.5-flash',
    contents: [
      ...chatHistory,
      { role: 'user', parts: [{ text: userMessage }] }
    ],
    config: {
      systemInstruction: systemInstruction,
      temperature: 0.3, // Низкая температура для большей точности и предсказуемости
      maxOutputTokens: 500,
    }
  });

  return response.text;
}

Смотреть код на GitHub (OZAT-kz)

Обратите внимание на temperature: 0.3. Для креативных задач (например, написания стихов) температуру завышают. Но бот госуслуг не должен фантазировать и галлюцинировать. Ему нужна хирургическая точность.

Проблема: «Шала-казахский» и распознавание намерений

Давайте посмотрим, как классический бот с NLP-модулем (например, Dialogflow ES) и Gemini реагируют на реальный запрос из логов.

Запрос пользователя: «Брат, менің правам срок бітіп қалды, новый алу үшін қайда барам? Шоферская справка керек па?»

Классический бот: Извините, я не понял ваш запрос. Выберите пункт меню: [1] Получить ЭЦП... (NLP-движок не смог вычленить entity и intent из смеси сленга и двух языков).

Наш бот на Vertex AI (Gemini): «Сәлеметсіз бе! Жүргізуші куәлігін (права) ауыстыру үшін сізге Мамандандырылған ХҚКО-ға (СпецЦОН) бару қажет немесе eGov.kz порталы арқылы онлайн өтінім қалдыра аласыз. Иә, 073/у формалы медициналық анықтама (шоферская справка) міндетті түрде қажет.»

Gemini блестяще справляется с деконструкцией смешанного языка, понимая контекст «права» (водительское удостоверение) и «срок бітіп қалды» (истек срок действия).

Точность классификации намерений (Intent Recognition)

Вызов функций (Function Calling): Учим LLM нажимать кнопки

Консультировать — это хорошо. Но настоящая магия начинается тогда, когда ИИ может совершать реальные действия в бэкенд-системах. Пользователь пишет: «Забронируй мне очередь в Алмалинский ЦОН на завтра на 10 утра». LLM сама по себе не может записать вас в базу данных. Для этого используется механизм Function Calling (или Tools).

Мы описываем для Gemini список доступных функций в виде JSON-схемы (названия функций, их описание и требуемые параметры). Если Gemini понимает, что для ответа на запрос пользователя ей нужно выполнить действие, она возвращает не текст ответа, а структурированный JSON с названием функции и извлеченными параметрами.

import { GoogleGenAI, Type } from '@google/genai';

const ai = new GoogleGenAI();

// Описываем инструмент (функцию), которую может вызывать Gemini
const bookAppointmentTool = {
  functionDeclarations: [
    {
      name: 'book_con_appointment',
      description: 'Бронирование очереди в ЦОН. Вызывай эту функцию, если пользователь просит забронировать очередь, записаться в ЦОН или взять талон.',
      parameters: {
        type: Type.OBJECT,
        properties: {
          con_name: {
            type: Type.STRING,
            description: 'Название или район ЦОНа (например, "Алмалинский", "СпецЦОН Астана")'
          },
          date_time: {
            type: Type.STRING,
            description: 'Желаемая дата и время в формате ISO 8601 (например, "2026-08-15T10:00:00")'
          }
        },
        required: ['con_name', 'date_time'],
      },
    },
  ],
};

// Функция обработки диалога с поддержкой Tools
export async function handleUserMessageWithTools(userMessage: string) {
  const response = await ai.models.generateContent({
    model: 'gemini-1.5-flash',
    contents: [{ role: 'user', parts: [{ text: userMessage }] }],
    config: {
      tools: [bookAppointmentTool], // Передаем наши инструменты модели
    }
  });

  // Проверяем, решила ли модель вызвать функцию
  if (response.functionCalls && response.functionCalls.length > 0) {
    const call = response.functionCalls[0];
    if (call.name === 'book_con_appointment') {
      const args = call.args as any;
      console.log(`[System] Модель хочет забронировать очередь: ЦОН - ${args.con_name}, Время - ${args.date_time}`);
      
      // Здесь мы делаем реальный HTTP-запрос к API базы данных бронирования
      // const result = await api.book(args.con_name, args.date_time);
      
      // Возвращаем результат выполнения функции обратно в модель, 
      // чтобы она сформировала человечный ответ
      const functionResponse = await ai.models.generateContent({
        model: 'gemini-1.5-flash',
        contents: [
          { role: 'user', parts: [{ text: userMessage }] },
          // Добавляем запрос функции от модели в историю
          { role: 'model', parts: [{ functionCall: call }] }, 
          // Возвращаем результат выполнения
          { role: 'function', parts: [{ functionResponse: { name: call.name, response: { status: 'success', booking_id: 'A-123' } } }] }
        ]
      });
      return functionResponse.text;
    }
  }

  // Если функция не вызывалась, просто возвращаем текст ответа
  return response.text;
}

Смотреть код на GitHub (OZAT-kz)

Таким образом, когда пользователь пишет неструктурированный текст «Братан, запиши на завтра после обеда в Бостандыкский», Gemini извлекает con_name: "Бостандыкский" и вычисляет date_time на основе текущего времени, вызывая наш внутренний API. Пользователь получает ответ: «Сіздің кезегіңіз Бостандық ауданының ХҚКО-на ертең сағат 14:00-ге сәтті брондалды. Талон нөмірі: A-123.»

Безопасность и PII (Персональные данные)

В работе с государственными и финансовыми ботами критически важно не скармливать в LLM чувствительные данные (номера паспортов, ИИН, полные номера банковских карт). Да, Vertex AI не использует данные для обучения, но хранить PII в логах чат-истории — плохая практика.

Поэтому перед отправкой текста в Vertex AI мы пропускаем сообщение пользователя через Google Cloud DLP (Data Loss Prevention) API (сейчас переименован в Sensitive Data Protection). Этот сервис на лету с помощью регулярных выражений и машинного обучения находит ИИН (12 цифр, подпадающих под контрольную сумму) и маскирует их.

Пользователь пишет: «Мой ИИН 900101300123, проверь статус».
Vertex AI получает: «Мой ИИН [IIN_MASKED], проверь статус».

ИИН извлекается на уровне нашего Node.js бэкенда, сохраняется в защищенную переменную и используется ТОЛЬКО для запроса к внутренним API ЦОНа, минуя «мозг» LLM.

Выводы

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

Наш опыт показывает, что использование Vertex AI в связке с Function Calling позволяет создать не просто «болталку», а полноценного цифрового сотрудника, который понимает локальную специфику (тот самый шала-казахский), выполняет бизнес-процедуры и соблюдает строгие enterprise-стандарты безопасности.

Архитектура на базе Cloud Run делает это решение невероятно дешевым (оплата только за реальное время работы процессора при обработке запроса) и отказоустойчивым. Ни один вирусный репост в WhatsApp, вызывающий шквал обращений, не положит ваш бэкенд.

Если ваша компания все еще мучает клиентов фразами «Нажмите 0 для возврата в главное меню» — самое время написать нам в OZAT. Пора переходить на светлую сторону ИИ!

Рустам Шарафутдинов

Рустам Шарафутдинов

Автор инженерного блога

Эксперт в области архитектуры Google Cloud и Senior Full-Stack разработчик с более чем 15-летним опытом. Специализируется на отказоустойчивых архитектурах, оптимизации высоконагруженных проектов и интеграции AI (Vertex AI).

Экспертность: GCP, Kubernetes, Микросервисы, React, Node.js

Комментарии (0)