Telegram Bot + LLM Function Calling: Full Implementation Flow

Основной сценарий работы Telegram-бота с LLM-ассистантом строится вокруг триады: получение пользовательского сообщения → анализ на LLM → выбор функции → исполнение → ответ.

Happypath: LLM Router → Function Execution

$botToken = getenv('TELEGRAM_BOT_TOKEN');
$chatId = $_GET['chat_id'];

// Формируем промпт для выбора функции
$prompt = "User requested action. Choose one:\n- get_order\n- create_booking";

// Отправляем в Telegram через cURL (не file_get_contents)
$url = "https://api.telegram.org/bot{$botToken}/sendMessage?text={$\"$prompt\"]},"
$resp = @curl_init($url);
if (curl_errno($resp)) { http_response_code(502); exit; }
$decoded = json_decode($resp, true);

// Проверяем статус и валидность JSON
if (isset($decoded && $decoded['ok'] == true && isset($decoded['message'])) {
$funcs = explode('|', $decoded['message']);
if (empty($funcs)) { http_response_code(501); exit; }
$func = $funcs[0];

// Выполняем выбранную операцию в PHP/Yii2
if ($func === "create_booking") {
$booking = createBookingByChatId($chatId);
} else {
$result = getOrderByChatId($chatId);
}

// Отвечаем пользователю
$msg = "Action completed. Result: \"" . ($booking ? json_encode($booking) : "No data") . "\";
echo $msg;
}

Для гарантии надёжности используется идемпотентность: перед выполнением любой операции генерируется уникальный идентификатор (lead_id) через bin2hex(random_bytes(7)), сохраняется в БД, а повторные запросы с таким id отбрасываются.

function processInteraction(\$chatId, int \$opId, array \$payload) {
try {
// Хранилище обработанных операций
\$pdo = getDiPdo();
\$stmt = \$pdo->prepare(
"INSERT INTO telegram_op_results (op_id, chat_id, status, created_at) VALUES (?,?,?,NOW())"
);
\$stmt->execute([\$opId, \$chatId, 'pending']);

// Логика выбора функции от LLM ...
// Здесь должна быть интеграция с LLM-сервисом
// Для примера: выбираем функцию через конечный автомат

switch (\$selectedFunction) {
case "create_booking":
return createBooking(\$chatId);
case "get_order":
return getOrder(\$chatId);
default:
throw new Exception(\"Invalid function\");
}
} catch (\$e) {
// Логирование и возврат ошибки вебхуку
logError(\$opId, \$e->getMessage());
throw \$e;
}
}

При работе с глубокими ссылками t.me/Bot?start= важно помнить, что этот параметр предназначен только для перехода в корневой диалог, а не для продолжения существующих бесед.

Новые статьи — в Telegram

Разбираем, что автоматизировать в бизнесе и как это работает на практике. Без спама.