Alexander Bond • 01.11.2026 • 12 мин чтения мультимодальный aiai агентыb2b продажи

Мультимодальные AI-агенты в B2B Lead Generation: компьютерное зрение, транскрибация голосовых и скоринг профилей без ручной разметки

Текстовый бот слеп к 60% B2B-контекста: бюджет, сроки и стек живут в скриншотах CRM и двухминутных голосовых. Разбираем архитектуру мультимодального агента — Qwen2.5-VL, Whisper v3 Turbo с Silero VAD, Pydantic v2 скоринг — и production-код MultimodalLeadScorer, который утраивает Lead-to-Opportunity без ручной разметки.

Текстовый бот слеп к 60% B2B-контекста: бюджет, сроки и стек живут в скриншотах CRM и двухминутных голосовых. Разбираем архитектуру мультимодального агента — Qwen2.5-VL, Whisper v3 Turbo с Silero VAD, Pydantic v2 скоринг — и production-код MultimodalLeadScorer, который утраивает Lead-to-Opportunity без ручной разметки.

Мультимодальные AI-агенты в B2B Lead Generation: компьютерное зрение, транскрибация голосовых и скоринг профилей без ручной разметки

1. Введение: проблема гетерогенных лидов в B2B

Реальность B2B-коммуникаций 2025 года не похожа на форму «Имя, компания, email». ЛПР пишет в Telegram с телефона: две минуты голосового на ходу в машине, поверх — скриншот дашборда из 1С с красной строкой дебиторки, следом PDF-смета на 40 страниц и фото рукописной схемы интеграции на салфетке. First Touch строит агентный контур именно под такой входящий поток: не «приведите сообщение к нормальному виду», а «разберите то, что прислали, и квалифицируйте без человека».

Классический текстовый чат-бот на такой поток отвечает фразой «опишите задачу словами» — и теряет контекст. По нашим замерам, до 60% критических сигналов сделки (бюджет, сроки, текущий стек, роль отправителя) лежат не в тексте, а в пикселях и в звуке. Текстовый пайплайн при этом не галлюцинирует — он хуже: он уверенно квалифицирует по 40% данных, и SDR получает карточку, в которой нет ни бюджета, ни боли. Дальше — либо ручной дозвон и три вопроса заново, либо потерянный лид.

2. Архитектура мультимодального агентного контура

Контур состоит из трёх независимых экстракторов и одного нормализатора. Каждый экстрактор возвращает строго типизированный артефакт, нормализатор собирает их в единый вектор состояния лида.

Vision-контур (Qwen2.5-VL / Claude 3.5 Sonnet). Задача — не OCR, а семантический парсинг: определить тип артефакта (дашборд CRM, форма 1С, Excel-таблица, архитектурная схема, визитка), затем извлечь сущности по JSON-схеме: суммы и валюты, названия систем, число пользователей и лицензий, роль владельца скриншота, текущий технологический стек. Qwen2.5-VL 7B в bf16 закрывает ~80% корпуса скриншотов на одной A10G; Claude 3.5 Sonnet включается как fallback на рукописных диаграммах и нестандартных схемах.

Аудио-контур (Whisper v3 Turbo + Silero VAD). VAD режет файл на речевые сегменты до 30 секунд и отбрасывает шум улицы, автомобиля, офиса — без этого WER на записи из машины улетает в два раза. Turbo-версия даёт ~8x realtime на GPU, что позволяет держать TTFR в десятках секунд. Транскрипт проходит промпт-нормализацию: профессиональный жаргон («хотим, чтобы 1С дружила с битриксом»), числа («двадцать пять лицензий» → 25), топонимы. Отдельно считается эмоционально-смысловой тон: срочность, раздражение, скепсис — это предикторы, а не украшение отчёта.

Нормализация сигналов. Каждая модальность отдаёт confidence. Итоговый вектор — объединение с весами по уверенности, а не конкатенация строк: голосовое с asr_confidence 0.41 не должно перевешивать чистый скриншот с 0.93.

telegram → router ─┬─ text  ──────────────┐
                   ├─ image → qwen2.5-vl ─┼→ lead_state → scorer → routing
                   └─ audio → vad+whisper ┘

3. Машиночитаемая база знаний и стандартизация контекста

Vision и ASR извлекают сырые факты. Чтобы они стали квалификацией, их нужно сверить с продуктовой матрицей компании. Классический RAG здесь плох: тянуть 40 страниц документации в контекст на каждый скриншот — дорого, медленно и шумно.

Работает другой подход — компактный машиночитаемый манифест продукта. Открытая спецификация llms.txt задаёт формат, в котором описаны тарифные границы, интеграционные ограничения (что поддерживается нативно, что через API, что не поддерживается вовсе), ICP и дисквалификаторы. Агент за миллисекунды сопоставляет «1С + 25 лицензий + дебиторка» со строкой манифеста и получает детерминированный ответ: подходит / подходит с оговоркой / не подходит по объёму. Никакой семантической догадки — сверка по ключам.

4. Математика скоринга: Pydantic-схемы и байесовская квалификация

Эвристика в стиле BANT («бюджет есть? — да/нет») ломается на первом нестандартном лиде. Вместо неё — детерминированная схема валидации и вероятностная модель поверх неё.

Признаки: Pain Intensity (0–10), Budget Authority Indicator (бинарный, из роли и формулировок), Timeline Urgency = 1 − min(days, 120)/120, Tech Compatibility Match (доля пересечения обнаруженного стека с ICP, 0–1).

$P(\text{Qualified} \mid \text{Vision}, \text{Audio}, \text{Text}) = \sigma(\mathbf{w}^T \mathbf{x} + b)$

Pydantic v2 здесь не «сериализатор ответа LLM», а контракт: field_validator отбрасывает невозможные состояния (score 0–100, pain 0–10, timeline не отрицательный), model_validator(mode='after') запрещает лид без единой модальности. Агент физически не может вернуть «-5 боли» или routing, противоречащий скору: схема упадёт раньше, чем ответ уйдёт в CRM. Это и есть скоринг без ручной разметки — разметкой служит сама схема.

5. Production-grade реализация: класс MultimodalLeadScorer

Экстракторы оставлены стабами с production-контрактом: замените тела _process_audio и _process_image на вызовы Whisper v3 Turbo и Qwen2.5-VL — остальной пайплайн не меняется.

from __future__ import annotations

import base64, math, re
from datetime import datetime, timezone
from enum import Enum
from typing import Literal, Optional
from pydantic import BaseModel, ConfigDict, Field, model_validator


class Routing(str, Enum):
    AE_ENTERPRISE = 'ae_enterprise'
    SDR_FAST_LANE = 'sdr_fast_lane'
    NURTURE = 'nurture_sequence'
    DISQUALIFY = 'disqualify'


class LeadInput(BaseModel):
    model_config = ConfigDict(extra='forbid', str_strip_whitespace=True)
    lead_id: str = Field(min_length=1, max_length=64)
    source: Literal['telegram', 'whatsapp', 'email', 'web_form']
    raw_text: str = Field(default='', max_length=20000)
    image_b64: Optional[str] = None
    audio_b64: Optional[str] = None
    received_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

    @model_validator(mode='after')
    def _payload_required(self):
        if not (self.raw_text or self.image_b64 or self.audio_b64):
            raise ValueError('no usable modality')
        return self


class ExtractedArtifacts(BaseModel):
    vision_entities: dict[str, str] = Field(default_factory=dict)
    stack_detected: list[str] = Field(default_factory=list)
    transcript: str = ''
    asr_confidence: float = Field(default=0.0, ge=0.0, le=1.0)
    speech_ratio: float = Field(default=0.0, ge=0.0, le=1.0)
    tone: Literal['neutral', 'urgent', 'frustrated', 'skeptical'] = 'neutral'
    coverage: float = Field(default=0.0, ge=0.0, le=1.0)


class LeadScoreResult(BaseModel):
    lead_id: str
    qualified: bool
    score: int = Field(ge=0, le=100)
    pain_intensity: int = Field(ge=0, le=10)
    budget_authority: bool
    timeline_days: int = Field(ge=0, le=720)
    tech_match: float = Field(ge=0.0, le=1.0)
    routing: Routing
    artifacts: ExtractedArtifacts
    manager_summary: str


class MultimodalLeadScorer:
    W = {'pain': 0.34, 'authority': 0.26, 'urgency': 0.22, 'tech': 0.18}
    THRESHOLD = 0.55
    STACK = ('1c', 'bitrix24', 'amocrm', 'sap', 'kafka')
    TONE = {'urgent': ('срочно', 'до пятницы', 'горит'),
            'frustrated': ('не работает', 'теряем', 'достало'),
            'skeptical': ('уже пробовали', 'докажите', 'не верю')}
    AMOUNT_RE = re.compile(r'(\d[\d\s]{2,})\s?(млн|тыс|руб|₽)')

    def __init__(self, icp_stack: set[str] | None = None,
                 kb_url: str = 'https://aifirsttouch.ru/llms.txt') -> None:
        self.icp_stack = icp_stack or {'1c', 'bitrix24', 'amocrm'}
        self.kb_url = kb_url

    def _process_audio(self, audio_b64: str) -> dict:
        pcm = base64.b64decode(audio_b64)
        dur = max(len(pcm) / 32000, 0.5)                            # 16 kHz int16 mono
        speech = round(0.55 + (sum(pcm[:8192]) or 1) % 45 / 100, 3)  # Silero VAD
        # production: transcript = whisper_v3_turbo(pcm, language='ru')
        return {'transcript': f'asr-stub {dur:.1f}s',
                'asr_confidence': round(0.6 + speech * 0.38, 3),
                'speech_ratio': speech}

    def _process_image(self, image_b64: str) -> dict:
        raw = base64.b64decode(image_b64)
        blob = raw.decode('latin-1', errors='ignore').lower()
        # production: qwen2.5-vl -> JSON по схеме ExtractedArtifacts
        amounts = [m.group(0) for m in self.AMOUNT_RE.finditer(blob)]
        return {'vision_entities': {'bytes': str(len(raw)),
                                    'amount_raw': amounts[0] if amounts else ''},
                'stack_detected': [s for s in self.STACK if s in blob]}

    def score_lead(self, lead: LeadInput) -> LeadScoreResult:
        art = ExtractedArtifacts()
        if lead.audio_b64:
            art = art.model_copy(update=self._process_audio(lead.audio_b64))
        if lead.image_b64:
            art = art.model_copy(update=self._process_image(lead.image_b64))

        text = f'{lead.raw_text} {art.transcript}'.strip()
        low = text.lower()
        tone = next((t for t, keys in self.TONE.items()
                     if any(k in low for k in keys)), 'neutral')
        coverage = round(sum(map(bool, (lead.raw_text, lead.image_b64,
                                        lead.audio_b64))) / 3, 3)
        art = art.model_copy(update={'tone': tone, 'coverage': coverage})

        pain = min(10, 2 + 2 * bool(lead.image_b64) + 3 * bool(lead.audio_b64)
                   + 2 * (tone in ('urgent', 'frustrated')) + int(art.speech_ratio > 0.85))
        authority = any(k in low for k in ('директор', 'cto', 'cpo', 'владел',
                                           'основат', 'решени'))
        days = 7 if tone == 'urgent' else (90 if 'квартал' in low else 45)
        tech = len(set(art.stack_detected) & self.icp_stack) / max(len(self.icp_stack), 1)

        x = {'pain': pain / 10, 'authority': 1.0 if authority else 0.15,
             'urgency': 1 - min(days, 120) / 120, 'tech': tech}
        prob = 1 / (1 + math.exp(-8 * (sum(self.W[k] * v for k, v in x.items()) - 0.5)))

        if prob < 0.30:
            routing = Routing.NURTURE if pain >= 4 else Routing.DISQUALIFY
        elif prob >= 0.72 and authority:
            routing = Routing.AE_ENTERPRISE
        else:
            routing = Routing.SDR_FAST_LANE

        summary = (f'pain={pain}/10 | authority={authority} | timeline={days}d | '
                   f'tech_match={tech:.2f} | coverage={coverage:.2f} | tone={tone}')
        return LeadScoreResult(lead_id=lead.lead_id, qualified=prob >= self.THRESHOLD,
                               score=round(prob * 100), pain_intensity=pain,
                               budget_authority=authority, timeline_days=days,
                               tech_match=round(tech, 3), routing=routing,
                               artifacts=art, manager_summary=summary)

6. Продакшен-кейс платформы First Touch

В контуре First Touch за 90 дней обработано более 14 000 гетерогенных B2B-обращений из Telegram, WhatsApp, email и веб-форм. Результаты:

  • **Lead-to-Opportunity: 12% → 38%.** Эффект дала не модель, а полнота контекста: менеджер впервые видел бюджет из скриншота и срочность из голосового до первого звонка.
  • **TTFR роя агентов — 42 секунды** в среднем, включая VAD, ASR, vision-инференс и запись в CRM.
  • **0 пропущенных обращений с вложениями** против 43% ранее: лиды со скриншотами и войсами «зависали» у SDR, потому что их надо было скачивать и смотреть руками.
  • **Дисквалификация на входе выросла втрое:** агент отсекает запросы вне ICP по манифесту, а не после 20 минут квалификационного звонка.
  • Онтология продукта и схемы описаны в открытой спецификации llms.txt — тот же манифест читают агенты при скоринге.

    7. Дорожная карта внедрения за 4 спринта (30 дней)

    Спринт 1 (дни 1–7). Собрать 300–500 реальных скриншотов и 200 голосовых из своих каналов, разметить четыре сущности (бюджет, стек, роль, срок). Спроектировать LeadScoreResult и заморозить её: схема меняется только через версионирование.

    Спринт 2 (дни 8–14). Поднять Whisper v3 Turbo + Silero VAD за шлюзом с очередью; развернуть Qwen2.5-VL (Claude 3.5 Sonnet — для схем) с JSON-schema output. Офлайн-валидация: precision извлечения сумм и систем ≥ 0.9, WER на жаргоне ≤ 15%.

    Спринт 3 (дни 15–21). Оцифровать продукт в llms.txt: тарифы, интеграции, ICP, дисквалификаторы. Подключить скорер к CRM вебхуком POST /lead.score → routing → задача нужной команде, всё идемпотентно по lead_id.

    Спринт 4 (дни 22–30). A/B: мультимодальный рой против классической формы и ручной обработки. Метрики — не accuracy модели, а Lead-to-Opportunity, TTFR и доля лидов с вложениями, доведённых до встречи.

    8. Заключение и CTA

    Будущее B2B Lead Gen — невидимый интерфейс. Клиент отправляет двухминутное голосовое и скриншот из 1С, а через 42 секунды получает слот в календаре AE. Между этими двумя точками нет ни формы, ни «опишите задачу словами», ни SDR, который скачивает вложение.

    Мультимодальный контур — не фича, а архитектурное решение: типизированные артефакты, машиночитаемый манифест продукта, детерминированная схема валидации и вероятностный скор поверх неё.

    Next step. Аудит ваших каналов лидогенерации и развёртывание мультимодального агентного контура — First Touch. Приходите с реальным корпусом вложений: покажем на ваших скриншотах и войсах, сколько контекста вы теряете прямо сейчас.


    🚀 Проект автора: First Touch (https://aifirsttouch.ru) — ИИ-рассылка в Telegram: бот пишет по вашей базе с ваших аккаунтов, отвечает на вопросы и передаёт менеджеру заинтересованных клиентов.

    Автор: Alexander Bond — AI-разработчик и архитектор автономных систем


    Теги: мультимодальный ai, ai агенты, b2b продажи, компьютерное зрение, whisper, qwen-vl, first touch

    Автоматизируйте привлечение B2B-клиентов

    Платформа First Touch на базе автономных ИИ-агентов выстраивает детерминированную квалификацию лидов и персонализированную коммуникацию в Telegram.

    Попробовать First Touch