В современном мире автоматизация процессов стала ключевым фактором успеха многих бизнесов. Один из таких процессов — квалификация лидов. В данном кейсе мы рассмотрим, как был создан Telegram-бот для квалификации лидов в юридической компании. Бот подключен к сайту, отвечает на вопросы посетителей сайта. И при условии прохождения модерации предлагает записаться на консультацию к юристу.
Основные компоненты бота
- Telegram Bot API
- OpenAI GPT-3.5 Turbo
- PostgreSQL база данных
- Асинхронное программирование на Python
Структура и логика работы бота
1. Инициализация и подключение к базе данных
Бот начинает работу с установки соединения с базой данных PostgreSQL:
async def db_connect():
try:
connection = await asyncpg.connect(user='user', password='password', database='database', host='localhost')
logger.info("Успешное подключение к базе данных")
return connection
except Exception as e:
logger.error(f"Ошибка подключения к базе данных: {e}")
raise
Это позволяет боту сохранять информацию о пользователях и их взаимодействиях.
2. Обработка команды /start
Когда пользователь запускает бота, срабатывает функция `start`:
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
telegram_id = update.effective_user.id
username = update.effective_user.username
full_name = update.effective_user.full_name
welcome_message = """Приветствую Вас, {}. Меня зовут Виктория, я AI-ассистент в юридической компании. Чем я могу быть для вас полезна?""".format(full_name)
await context.bot.send_message(
chat_id=update.effective_chat.id,
text=welcome_message,
parse_mode='HTML',
disable_web_page_preview=True
)
await save_user_data_if_not_exists(context, telegram_id, username, full_name)
Эта функция отправляет приветственное сообщение и сохраняет данные пользователя в базе данных, если его там еще нет.
3. Обработка сообщений пользователя
Основная логика бота реализована в функции `handle_message`:
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
telegram_id = update.effective_user.id
user_message = update.message.text
chat_id = update.effective_chat.id
username = update.effective_user.username
full_name = update.effective_user.full_name
# Обновление истории чата
update_chat_history(chat_id, "user", user_message)
# Формирование контекста для GPT
messages_with_context = personal_context + chat_histories.get(chat_id, [])
# Запрос к GPT
chat_completion = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=messages_with_context,
)
answer = chat_completion.choices[0].message.content
# Проверка на ключевое слово
if "[Отправила ваши данные адвокату]" in answer:
await send_info_to_admin(update, context, chat_id)
else:
update_chat_history(chat_id, "assistant", answer)
await context.bot.send_message(chat_id=chat_id, text=answer)
Эта функция обрабатывает входящие сообщения, отправляет их в GPT для генерации ответа, и в зависимости от ответа либо продолжает диалог, либо передает информацию администратору.
4. Интеграция с GPT
Бот использует GPT-3.5 Turbo для генерации ответов. Важным элементом является предустановленный контекст:
personal_context = [
{"role": "system", "content": "Ты AI-ассистент в юридической компании, тебя зовут Виктория. ..."}
]
Этот контекст задает роль и поведение AI-ассистента, обеспечивая релевантные и профессиональные ответы.
5. Квалификация лидов
Бот квалифицирует лидов, задавая уточняющие вопросы и собирая контактную информацию. Когда бот получает достаточно информации, он использует ключевую фразу «[Отправила ваши данные адвокату]», которая служит триггером для передачи информации администратору:
async def send_info_to_admin(update: Update, context: ContextTypes.DEFAULT_TYPE, chat_id):
admin_chat_id = 'admin_id'
if admin_chat_id:
chat_history = chat_histories.get(chat_id, [])
messages = [message["content"] for message in chat_history if message["role"] == "user"]
info_message = f"Пользователь {update.effective_user.full_name} (@{update.effective_user.username}) запросил связь с адвокатом. Вот история диалога:\n\n"
info_message += "\n".join(messages)
await context.bot.send_message(chat_id=admin_chat_id, text=info_message)
else:
logger.error("Admin chat id is not set.")
6. Рассылка сообщений
Бот также имеет функционал для рассылки сообщений всем пользователям:
async def sendall_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
user_id = update.effective_user.id
if user_id == admin_id:
admin_state[user_id] = "awaiting_message_text"
await update.message.reply_text("Пожалуйста, отправьте текст для рассылки.")
else:
await update.message.reply_text("У вас нет прав для выполнения этой команды.")
Заключение
Данный бот представляет собой комплексное решение для автоматизации процесса квалификации лидов. Он использует передовые технологии искусственного интеллекта для ведения естественного диалога, собирает необходимую информацию и передает квалифицированные лиды напрямую менеджерам.
Ключевые преимущества этого решения:
- Автоматизация первичного общения с клиентами
- Круглосуточная доступность
- Сбор и структурирование информации о потенциальных клиентах
- Возможность масштабирования без увеличения нагрузки на персонал
Для успешной работы с таким ботом необходимы знания Python, асинхронного программирования, работы с API Telegram и OpenAI, а также навыки работы с базами данных PostgreSQL.
Код чат-бота на Python
import asyncio
from telegram import Update, Bot
from telegram.ext import Application, MessageHandler, filters, ContextTypes, CommandHandler
from openai import AsyncOpenAI
import csv
import logging
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from functools import partial
import os
import aiohttp
import asyncpg
from aiohttp import TCPConnector
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
admin_state = {}
user_uses = {}
user_states = {}
# Словарь, сопоставляющий команды с URL каналов (Ссылки приглашения в тг Каналы вставьте свои)
channels = {
'channel1': ('https://t.me/+JsobbT1ArkY3M2Zi', 'Эй-Ай 🤖 Искусственный интеллект'),
'channel2': ('https://t.me/+oWkVbBbGQtFiYTAy', 'ИИ инструменты в маркетинге'),
'channel3': ('https://t.me/+Z_20lkPs2ItlNDcy', 'Богатый ремесленник')
}
async def db_connect():
try:
connection = await asyncpg.connect(user='Ваш логин', password='Ваш пароль', database='Название базы данных', host='localhost')
logger.info("Успешное подключение к базе данных")
return connection
except Exception as e:
logger.error(f"Ошибка подключения к базе данных: {e}")
raise
async def channel_command(update: Update, context: ContextTypes.DEFAULT_TYPE, channel_url, channel_name):
keyboard = [[InlineKeyboardButton("Перейти в канал", url=channel_url)]]
reply_markup = InlineKeyboardMarkup(keyboard)
await context.bot.send_message(chat_id=update.effective_chat.id, text=f"Подписаться на канал: {channel_name}", reply_markup=reply_markup)
def get_main_menu():
keyboard = [
[InlineKeyboardButton("Эй-Ай 🤖 Искусственный интеллект", url="https://t.me/+JsobbT1ArkY3M2Zi")],
[InlineKeyboardButton("ИИ инструменты в маркетинге", url="https://t.me/+oWkVbBbGQtFiYTAy")],
[InlineKeyboardButton("Богатый ремесленник", url="https://t.me/+Z_20lkPs2ItlNDcy")]
]
return InlineKeyboardMarkup(keyboard)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
telegram_id = update.effective_user.id
username = update.effective_user.username
full_name = update.effective_user.full_name
welcome_message = """Приветствую Вас, {}. Меня зовут Виктория, я AI-ассистент в юр компании. Чем я могу быть для вас полезна?""".format(full_name)
await context.bot.send_message(
chat_id=update.effective_chat.id,
text=welcome_message,
parse_mode='HTML',
disable_web_page_preview=True
)
await save_user_data_if_not_exists(context, telegram_id, username, full_name)
async def notify_admin(context: ContextTypes.DEFAULT_TYPE, message: str):
admin_chat_id = 'chat_id администратора' # Замените на chat_id администратора или пользователя
try:
await context.bot.send_message(chat_id=admin_chat_id, text=message)
except Exception as e:
logger.error(f"Ошибка при отправке сообщения администратору: {e}")
async def save_user_data_if_not_exists(context, telegram_id, username, full_name):
conn = await db_connect()
try:
user_exists = await conn.fetchval('SELECT EXISTS(SELECT 1 FROM users WHERE telegram_id = $1)', telegram_id)
if not user_exists:
await conn.execute('INSERT INTO users(telegram_id, username, full_name) VALUES ($1, $2, $3)', telegram_id, username, full_name)
logger.info(f"Новый пользователь сохранен: {full_name} (@{username})")
await notify_admin(context, f"Новый пользователь: {full_name} (@{username})")
except Exception as e:
logger.error(f"Ошибка при сохранении данных пользователя: {e}")
finally:
await conn.close()
async def send_broadcast_message(bot, message_text):
conn = await db_connect()
try:
subscribers = await conn.fetch('SELECT telegram_id FROM users')
logger.info("Получен список подписчиков для рассылки")
except Exception as e:
logger.error(f"Ошибка при получении списка подписчиков: {e}")
return 0, 0, []
finally:
await conn.close()
success_count = 0
failed_count = 0
failed_subscribers = []
for record in subscribers:
subscriber_id = record['telegram_id']
try:
await bot.send_message(chat_id=subscriber_id, text=message_text)
success_count += 1
except Exception as e:
logger.error(f"Не удалось отправить сообщение {subscriber_id}: {e}")
failed_count += 1
failed_subscribers.append(subscriber_id)
logger.info(f"Рассылка завершена. Успешно: {success_count}, Не удалось: {failed_count}")
return success_count, failed_count, failed_subscribers
openai_api_key = "Ваш API ключ"
telegram_token = "Ваш ТГ токен"
bot = Bot(token=telegram_token)
client = AsyncOpenAI(api_key=openai_api_key)
chat_histories = {}
# Функция для добавления сообщения в историю чата
def update_chat_history(chat_id, role, content):
if chat_id not in chat_histories:
chat_histories[chat_id] = []
# Ограничиваем историю, например, последними 5 обменами сообщениями
if len(chat_histories[chat_id]) > 10:
chat_histories[chat_id].pop(0) # Удаляем самое старое сообщение
chat_histories[chat_id].append({"role": role, "content": content})
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
telegram_id = update.effective_user.id
user_message = update.message.text
chat_id = update.effective_chat.id
username = update.effective_user.username
full_name = update.effective_user.full_name
# Логика для обработки текста рассылки от администратора
if admin_state.get(telegram_id) == "awaiting_message_text":
if telegram_id == ваш Telegram ID:
success_count, failed_count, failed_subscribers = await send_broadcast_message(context.bot, user_message)
admin_state[telegram_id] = None # Сброс состояния
report_message = f"Рассылка выполнена.\nУспешно отправлено сообщений: {success_count}.\nНе удалось отправить сообщений: {failed_count}."
if failed_count > 0:
report_message += f"\nНе удалось отправить следующим пользователям: {', '.join(failed_subscribers)}"
await update.message.reply_text(report_message)
return
# Сохраняем данные пользователя, если они еще не были сохранены
await save_user_data_if_not_exists(context, telegram_id, username, full_name)
# Обновляем историю диалога для текущего чата
update_chat_history(chat_id, "user", user_message)
# Предустановленный контекст и т.д.
personal_context = [
{"role": "system", "content": "Ты AI-ассистент в юр компании, тебя зовут Виктория. Твоя первая задача - вежливо и строго, но приветливо отвечать на все вопросы пользователей. Используй формальный тон общения. Веди беседу, задавай уточняющие вопросы и в ходе живой беседы выяви потребность клиента. Уточни в какой он стране. Твоя вторая задача - получить контакты клиента для связи, это номер для звонка или whatsapp для связи или telegram для связи. Вежливо узнай когда ему будет удобно связаться и в какие время: предложи выбор сегодня или завтра. Обязательно попроси прислать актуальнный номер для связи. Когда клиент расскажет как ему удобно связаться и ты получил актуальный номер для связи, ответь ему используя фразу \"[Отправила ваши данные адвокату]\" строго придерживаясь формулировки, не меняй эту формулировку, это важно. Эта фраза является сигналом для операторов бота о необходимости вмешательства человека. Обязательно уведоми клиента, что его данные переданы адвокату. Дополнительная информация о компании: Название компании предоставляет комплексную юридическую поддержку для физических и юридических лиц в Турции и России. Компания имеет более 20 лет юридической практики в этих странах и специализируется на уголовном праве, гражданском праве, корпоративном праве и международном праве. Успешно решено более 1000 юридических дел разной сложности. В команде работают русско-турецко-англоязычные специалисты. Главный офис в Турции расположен в Адрес Наш сайт компании https://ссылка. Самые популярные услуги включают оформление рабочей визы в Турции под ключ с гарантией (выдается при наличии действующего ВНЖ или при законченном ВНЖ), подготовку визы с минимальным сроком действия - 1 год с пролонгацией, помощь в оформлении туристического ВНЖ для членов семьи. Льготы при получении рабочей визы включают получение ВНЖ для супруга или супруги и детей, возможность приобрести авто в Турции с 50% скидкой с регистрацией в Турции и право на гражданство Турции при неоднократном продлении рабочей визы. Семья и дети получают доступ к бесплатной медицине, а также детские сады и школы. "},
]
messages_with_context = personal_context + chat_histories.get(chat_id, [])
# Генерация и отправка запроса к ChatGPT
chat_completion = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=messages_with_context,
)
answer = chat_completion.choices[0].message.content
# Проверяем, содержит ли ответ ключевое слово для связи с менеджером
if "[Отправила ваши данные адвокату]" in answer:
# Если содержит, отправляем историю диалога администратору
await send_info_to_admin(update, context, chat_id)
else:
# Если не содержит, отправляем ответ пользователю
update_chat_history(chat_id, "assistant", answer)
await context.bot.send_message(chat_id=chat_id, text=answer)
async def sendall_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
user_id = update.effective_user.id
if user_id == ваш Telegram ID: # Замените на ваш Telegram ID администратора
admin_state[user_id] = "awaiting_message_text"
await update.message.reply_text("Пожалуйста, отправьте текст для рассылки.")
else:
await update.message.reply_text("У вас нет прав для выполнения этой команды.")
async def send_info_to_admin(update: Update, context: ContextTypes.DEFAULT_TYPE, chat_id):
admin_chat_id = 'ваш Telegram ID' # Замените на chat_id администратора
if admin_chat_id:
chat_history = chat_histories.get(chat_id, [])
messages = [message["content"] for message in chat_history if message["role"] == "user"]
info_message = f"Пользователь {update.effective_user.full_name} (@{update.effective_user.username}) запросил связь с адвокатом. Вот история диалога:\n\n"
info_message += "\n".join(messages)
await context.bot.send_message(chat_id=admin_chat_id, text=info_message)
else:
logger.error("Admin chat id is not set.")
if __name__ == '__main__':
application = Application.builder().token(telegram_token).build()
application.add_handler(CommandHandler('start', start))
application.add_handler(CommandHandler('sendall', sendall_command))
for command, (url, name) in channels.items():
handler = CommandHandler(command, partial(channel_command, channel_url=url, channel_name=name))
application.add_handler(handler)
application.add_handler(MessageHandler(filters.TEXT, handle_message))
asyncio.run(application.run_polling())