Разработка AI-бота для Telegram на базе LLM

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Разработка AI-бота для Telegram на базе LLM
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

Разработка AI-бота для Telegram на базе LLM

Telegram Bot с LLM — самый быстрый способ дать пользователям доступ к AI-ассистенту. Telegram Bot API поддерживает: текст, голосовые сообщения (через Whisper), изображения (через vision API), встроенные кнопки, группы и каналы.

Базовый AI-бот с aiogram 3.x

import asyncio
from aiogram import Bot, Dispatcher, Router, types, F
from aiogram.filters import CommandStart, Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.storage.redis import RedisStorage
from anthropic import AsyncAnthropic

BOT_TOKEN = "BOT_TOKEN"
ANTHROPIC_API_KEY = "ANTHROPIC_API_KEY"

bot = Bot(token=BOT_TOKEN)
storage = RedisStorage.from_url("redis://localhost:6379")
dp = Dispatcher(storage=storage)
router = Router()
dp.include_router(router)
anthropic_client = AsyncAnthropic(api_key=ANTHROPIC_API_KEY)

# История диалога — хранится в FSM context
@router.message(CommandStart())
async def start(message: types.Message, state: FSMContext):
    await state.update_data(history=[])
    await message.answer(
        "Привет! Я AI-ассистент на базе Claude. Задай любой вопрос.",
        reply_markup=get_main_keyboard()
    )

def get_main_keyboard():
    from aiogram.utils.keyboard import ReplyKeyboardBuilder
    builder = ReplyKeyboardBuilder()
    builder.button(text="🗑 Очистить историю")
    builder.button(text="ℹ️ О боте")
    builder.adjust(2)
    return builder.as_markup(resize_keyboard=True)

@router.message(F.text == "🗑 Очистить историю")
async def clear_history(message: types.Message, state: FSMContext):
    await state.update_data(history=[])
    await message.answer("История диалога очищена.")

@router.message(F.text & ~F.text.startswith("/"))
async def handle_text(message: types.Message, state: FSMContext):
    data = await state.get_data()
    history = data.get("history", [])

    # Добавляем сообщение пользователя в историю
    history.append({"role": "user", "content": message.text})

    # Показываем "печатает..."
    await bot.send_chat_action(message.chat.id, "typing")

    # Streaming ответ
    full_response = ""
    sent_message = await message.answer("...")

    async with anthropic_client.messages.stream(
        model="claude-haiku-4-5",
        max_tokens=2048,
        system="Ты — полезный ассистент. Отвечай кратко и по существу.",
        messages=history,
    ) as stream:
        async for text in stream.text_stream:
            full_response += text
            # Обновляем сообщение каждые 50 символов
            if len(full_response) % 50 == 0:
                await sent_message.edit_text(full_response)

    await sent_message.edit_text(full_response)

    # Сохраняем ответ в историю
    history.append({"role": "assistant", "content": full_response})
    # Ограничиваем историю — 20 сообщений
    await state.update_data(history=history[-20:])

Обработка голосовых сообщений

import io
from groq import AsyncGroq

groq_client = AsyncGroq(api_key="GROQ_API_KEY")

@router.message(F.voice)
async def handle_voice(message: types.Message, state: FSMContext):
    await bot.send_chat_action(message.chat.id, "typing")

    # Скачиваем голосовое сообщение
    voice = message.voice
    file = await bot.get_file(voice.file_id)
    file_bytes = await bot.download_file(file.file_path)

    # Транскрибируем через Whisper на Groq (быстро)
    transcription = await groq_client.audio.transcriptions.create(
        file=("voice.ogg", file_bytes.read()),
        model="whisper-large-v3",
        language="ru",
    )

    text = transcription.text
    await message.answer(f"📝 Распознано: {text}")

    # Обрабатываем как текстовое сообщение
    await handle_text_with_content(message, state, text)

Обработка изображений

import base64

@router.message(F.photo)
async def handle_photo(message: types.Message, state: FSMContext):
    await bot.send_chat_action(message.chat.id, "typing")

    # Берём фото наилучшего качества
    photo = message.photo[-1]
    file = await bot.get_file(photo.file_id)
    file_bytes = await bot.download_file(file.file_path)

    image_data = base64.standard_b64encode(file_bytes.read()).decode()
    caption = message.caption or "Что на этом изображении?"

    response = await anthropic_client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1024,
        messages=[{
            "role": "user",
            "content": [
                {"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": image_data}},
                {"type": "text", "text": caption},
            ]
        }]
    )

    await message.answer(response.content[0].text)

Rate limiting и billing защита

from aiogram.filters import BaseFilter
from collections import defaultdict
import time

class RateLimitFilter(BaseFilter):
    def __init__(self, rate_limit: int = 10, period: int = 60):
        self.rate_limit = rate_limit
        self.period = period
        self.user_requests = defaultdict(list)

    async def __call__(self, message: types.Message) -> bool:
        user_id = message.from_user.id
        now = time.time()

        # Убираем старые запросы
        self.user_requests[user_id] = [
            t for t in self.user_requests[user_id]
            if now - t < self.period
        ]

        if len(self.user_requests[user_id]) >= self.rate_limit:
            await message.answer("⏳ Слишком много запросов. Подождите минуту.")
            return False

        self.user_requests[user_id].append(now)
        return True

# Применяем фильтр
@router.message(RateLimitFilter(rate_limit=10), F.text)
async def handle_with_limit(message: types.Message, state: FSMContext):
    await handle_text(message, state)

Практический кейс: клиентская поддержка

Результат: Telegram-бот для SaaS-продукта. 73% обращений обрабатывались без участия поддержки. Время ответа: 24 часа → мгновенно.

Сроки

  • Базовый бот с диалогом: 2–3 дня
  • Голос + изображения: 2–3 дня
  • Rate limiting + admin panel: 1 неделя
  • Публикация + мониторинг: +2–3 дня