PHPackages                             isamarin/alisa - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. isamarin/alisa

ActiveLibrary

isamarin/alisa
==============

YandexAlisa PHP Bot

1.0.2(6y ago)6104MITPHPPHP ^7.1

Since Aug 4Pushed 6y ago1 watchersCompare

[ Source](https://github.com/isamarin/alisa)[ Packagist](https://packagist.org/packages/isamarin/alisa)[ RSS](/packages/isamarin-alisa/feed)WikiDiscussions master Synced yesterday

READMEChangelog (10)Dependencies (3)Versions (45)Used By (0)

Бот для Яндекс.Алиса
====================

[](#бот-для-яндексалиса)

Предварительная настройка
-------------------------

[](#предварительная-настройка)

### Морфологический словарь

[](#морфологический-словарь)

Бот использует преобразование слов в первую форму для более точного распознавания пользовательского запроса. Для корректной работы необходимо иметь словарь слов с нужным языком. Для русского языка подойдет [этот набор](https://sourceforge.net/projects/phpmorphy/files/phpmorphy-dictionaries/0.3.x/ru_RU/morphy-0.3.x-ru_RU-withjo-utf-8.zip/download). В обязательном порядке необходимо указать путь до словаря.

```
$bot = new Alisa('NAME');
//Такой используется по умолчанию
$bot->setDictionaryPath($_SERVER['DOCUMENT_ROOT'] . '/dicts/');
```

### Директория хранения сессий

[](#директория-хранения-сессий)

Сессии – \*.json файл в котором хранится вся сервисная информация в рамках сущности одного диалога. Необходимо указать путь до дирректории, в которую будут складироваться данные.

```
$bot = new Alisa('NAME');
//Такой используется по умолчанию
$bot->setDictionaryPath($_SERVER['DOCUMENT_ROOT'] . '/sessions/');
```

Протокол работы
---------------

[](#протокол-работы)

```
//Создаем бота. Аргумент – название навыка
$bot = new Alisa('myawesomebot');

//Создаем триггер, в качестве аргумента строка с уникальным именем
$helloTrigger = new Trigger('HELLO');

//Привязываем к триггеру токены – в данном случае в одну группу.
//Токены – ключевые слова, объединенные в группы
$helloTrigger->linkTokens(['привет','здравствуйте','приветсвую']);

$bayTrigger = new Trigger('bay');
$bayTrigger->linkTokens(['пока','до свидания','прощай']);

//Привязываем триггеры боту
$bot->addTrigger($helloTrigger,$bayTrigger);

//Отправляем ответ, если распознан $helloTrigger
$bot->sendResponse($helloTrigger,static function(){
    //$answer - экземпляр отправляемого ответа

    $answer = new Response();
    $answer->addText('Привет!');
    $answer->addText('Доброго времени суток!');

    //обязательно возвращаем объект Response
    return $answer;
);

//Отправляем ответ, если распознан $bayTrigger
$bot->sendResponse($bayTrigger,static function(){
    $answer = new Response();
    $answer->addText('Прошай!');
    $answer->addText('Всего доброго');

    //обязательно возвращаем объект Response
    return $answer;
);
```

Стандартные триггеры
--------------------

[](#стандартные-триггеры)

По протоколу работы бот обязан иметь как минимум триггер для приветствия, обработку ошибки (вызов помощи).

```
//Будет вызван автоматически, при первом обращении пользователя к навыку
$helloTrigger = new Trigger('HELLO');
$helloTrigger->setAsInit(true);

//Будет вызыван автоматически, если ну удалось распознать запрос
$mistakeTrigger = new Trigger('MISTAKE');
$mistakeTrigger->setAsMistake(true);

//Отправляем ответ, если распознан $mistakeTrigger
$bot->sendResponse($mistakeTrigger,static function(){
    $answer = new Answer();
    $answer->addText('Не удалось понять вашу команду :( ');
    return $answer;
);
```

В случае, если данные триггеры не определены, бот отошлет ответ по умолчанию со ссылкой на данный пункт. И если это причина, по которой ты читаешь этот текст – шалость удалась.

Триггеры
--------

[](#триггеры)

### Триггер

[](#триггер)

Триггер – команда, на которую должен отреагрировать бот.

### Токены

[](#токены)

Токены – ключевые слова, или варианты запроса (зависит от выбранного типа распознования)

#### MORPHY\_STRICT

[](#morphy_strict)

Данный режим использует поочередное сравнение групп токенов, отбирая только подходящие варинты. Разбор идет слева направо – если первая группа не прошла поиск – остальные группы перебираться не будут и бот приступит к просмотру следующего триггера. При первом вхождении всех групп – триггер будет помечен как распознанный, остыльне учавствовать в разборе не будут

```
$greenTea->linkTokens(['дай','хочу','налей'],['чай'],['зеленый']);
$blackTea->linkTokens(['дай','хочу','налей'],['чай'],['черный','индийский']);
$coffeTrigger->linkTokens(['дай','хочу','налей'],['кофе']);
```

При запросе "Налейка, пожалуйста черного чая" сработает $blackTea; При запросе "Сил нет как хочу бодрящего такого кофе" – $coffeTrigger;

Плюсы:

- Хорошо различает очень похожие запросы
- При первом свопадении всех групп токенов, обработка следующих триггеров прекращается
- Очередностью добавления триггеров можно определить те триггеры, которые будут обрабатываться первым. См пункт выше.
- Может вызывать триггер с ошибкой, если команда не была распознана. В данном примере, попросив налить пива, бот скажет что такими полномочиями не обладает.

Минусы:

- Необходимо строго определять важность того или иного ключевого слова. В случае с $greenTea и $blackTea, с аналогичными двумя первыми группами, решающим фактором сыграет третья гурппа токенов – черный чай или все таки чай зеленый.
- И колличество триггеров, и колличеество групп токенов сказывается на скорости работы.

#### Дамерау-Левенштейн

[](#дамерау-левенштейн)

В отличие от MORPHY\_STRICT ключевые слова будут определяться автоматически, но необходимо прописать несколько вариантов запросов. В разборе учавствуют все триггеры, за распознный будет выбираться триггер с наилучшим совпаденеием запроса.

```
$greenTea->linkTokens(['Налей зеленого чая'],['Хочу зеленого чая'],['Дай зеленый чай']);
$blackTeas->linkTokens(['Налей чергого чая'],['Хочу черного чая'],['Дай черный чай']);
$coffeTrigger->linkTokens(['Налей кофе'],['Хочу кофе'],['Дай кофе']);
```

Плюсы:

- Не нужно определять группы ключевых слов. Достаточно прописать только несколько возможных вариантов, которые может запросить пользователь
- Как правило, запрос обрабатывается быстрее, чем аналогичная вариация MORPHY\_STRICT

Минусы:

- Обрабатываются все триггеры, для которых прописаны токены. Даже если правильный триггер был выбран первым, остальные триггеры все равно пройдут проверку. Результирующий триггер – триггер с наибольшим совпадением. Соответвено чем больше триггеров, тем медленее работает.
- В отличие от MORPHY\_STRICT не может вызывать сообщение с ошибкой распознования. Данный режим всегда выдает какой-либо триггер. В данном примере, попросив налить пива, по какой-то причине бот наливает кофе.

### Делегирование

[](#делегирование)

В случаях, когда бот используется для последовательного выполнения команд, можно привязать к триггеру следующий триггер. Например если нужно собрать какую-либо информацию от пользователя, например имя, фамилию итд.

```
// Декларируем триггеры
$nameTrigger = new Trigger('NAME');
$sNameTrigger = new Trigger('SECOND_NAME');
$yoTrigger = new Trigger('YEARS');
$personTrigger = new Trigger('PERSON');

// Назначаем токены для триггера
$nameTrigger->setTokens(['давай','хочу','может'],['знакомиться','познакомиться','представлюсь']);

// Привязываем следующие триггеры
$nameTrigger->nextDelegate($sNameTrigger);
$sNameTrigger->nextDelegate($yoTrigger);
$yoTrigger->nextDelegate($personTrigger);

// Обрабочтик запроса. Сработает если пользователь произнес "Давай познакомимся"
$bot->sendResponse($nameTrigger,static function() use ($bot){
    $answer = new Response();
    $answer->addText('Какое твое имя?');
    return $answer;
});

// После шага $nameTrigger сработает обработчик $sNameTrigger
$bot->sendResponse($sNameTrigger,static function() use ($bot){
    $answer = new Response();
    $answer->addText('А фамилия?');
    return $answer;
});

// После шага $sNameTrigger сработает обработчик $yoTrigger
$bot->sendResponse($yoTrigger,static function() use ($bot){
    $answer = new Response();
    $answer->addText('Сколько тебе лет?');
    return $answer;
});
```

Для каждого из триггеров нужно создать обработчик с вопросом. При запросе пользователя "Ну давай познакомимся" сработает триггер $nameTrigger. Для триггеров $sNameTrigger и $yoTrigger токены не нужны (в общем то в данном случае они и не смогут сработать, тк пользотваель будет передавать информацию, и в ней нельзя распознать команду), они будут вызваны автоматически друг за другом.

### Данные

[](#данные)

Триггеры можно использовать не только как способ определения команды пользователя, но и для сбора информации.

```
//$personTrigger – назначен как следующий триггер после $yoTrigger
$bot->sendResponse($personTrigger,static function() use ($bot){

    //В качестве аргумента строка, уникальное название триггера
    $name = $bot->getTriggerData('NAME');
    $sName = $bot->getTriggerData('SECOND_NAME');
    $yo = $bot->getTriggerData('YEARS');
    $answer = new Answer();
    $answer->addText("Хорошо {$name} {$sName}, я тебя запомнила, и что тебе {$yo} лет – тоже");
    return $answer;
);
```

Бот сохраняет только один экземпляр данных для триггера, таким образом получить можно только последние полученные данные

Ответы
------

[](#ответы)

Ответы – это информация, которую бот отсылает пользователю, как только сработал триггер.

### Текст и TTS

[](#текст-и-tts)

```
//$personTrigger – назначен как следующий триггер после $yoTrigger
$bot->sendResponse($personTrigger,static function() use ($bot){
    $answer = new Answer();
    $answer->addText('Один вариант ответа','Од!ин вари!ант отв!ета');
    return $answer;
);
```

В методе addText два строчных аргумента. Первый используется для вывода текста, который будет отображен пользователю, второй – тот же самый текст в формате TTS.

### Варианты

[](#варианты)

Для большей интерактивности следует использовать несколько возможных вариантов ответа. Вариант при отправке будет выбран случайно.

```
$bot->sendResponse($bullshitTrigger,static function() {
    $answer = new Answer();
    $answer->addText('Да не может быть!');
    $answer->addText('Чушь собачья!');
    $answer->addText('Не верю!');
    return $answer;
);
```

### Кнопки

[](#кнопки)

Для ответа можно прикрепить кнопку. Это может быть ссылка на веб-страницу или кнопка, при нажатии на которую будет вызван триггер. Кнопок может быть несколько и разных видов.

```
$bot->sendResponse($helloPerson,static function() {
    $answer = new Answer();
    $answer->addText('Может познакомимся?');
    $buttonY = new Button('Давай');
    $answer->addButton($button);
    $buttonN = new Button();
    $buttonN->setTitle('Неа');
    return $answer;
);
```

В данном примере при нажатии на кнопку будет вызван $nameTrigger из примера в пункте "Делегирование". Таким образом $nameTrigger может быть взыван как голосом пользователя, так и нажатием на кнопку, если пользователь не разговорчив.

Кнопки
------

[](#кнопки-1)

### Виды кнопок

[](#виды-кнопок)

Бот Алисы может выводить пользователи кнопки в двух разных видах – как кнопка, размещенная под диалогом, так и ссылка внутри отправляемого ответа.

```
$bButton = new Button('Это кнопка');
//Будет отображена как кнопка, под диалогом. Со следующем ответом отображена не будет, если ее не привязатели к ответу Response
$bButton->setHide(true);

$bLink = new Button('Это кнопка, но как ссылка')
//Будет отображена в ответе. Даже если пользователь выбирал что-то другие, эта ссылка так и останется в сообщении.
$bButton->setHide(false);
```

### Базовые возможности

[](#базовые-возможности)

```
$bButton = new Button('Это кнопка');

* * *

// Можно установить заголовок не в конструкторе, а в методе. Можно использовать как способ изменеия заголовка имеющейся кнопки, тем самым создавая вариативность
$bButton->setTitle('Это все еще кнопка')

// К кнопке можно добавить ссылку. При клике на нее произойдет переход по адресу в браузере.
$bButton->addLink('www.SITENAME.DOMAIN');

// Кнопке можно добавить обработчик какого-нибудь тригера. При клике на кнопку бот в первую очередь проверяет есть ли связанный Триггер для кнопки, и если есть – вызывает именно его.
$bButton->linkTrigger(Trigger $trigger);

//Кнопке можно передать какие-нибудь данные, которые можно будет забрать и использовать, если пользователь нажимал на эту кнопку.
$bButton->addPayload(['DATA'=>'SOME_DATA']);
```

Сохранение данных
-----------------

[](#сохранение-данных)

Помимо отправленных пользователем данных, которые привязывается и сохраняеются триггером, можно сохранить и свои данные.

```
$bot->sendResponse($firstRequest,static function() use($bot) {
    * * *
   $bot->storeCommonData('Черный чай','TEA');
   $bot->getCommonData('TEA'); // Вернет "Черный чай", в т.ч. если пользователь уже перешел к другому запросу
    * * *
);
```

```
$bot->sendResponse($secondRequest,static function() use($bot) {
    * * *
   $bot->getCommonData('TEA'); // Вернет "Черный чай", в т.ч. если пользователь уже перешел к другому запросу
    * * *
);
```

Больше возможностей
-------------------

[](#больше-возможностей)

### Зацкиливание триггера

[](#зацкиливание-триггера)

В случаях, когда триггер предполагает не только принятие данных, но и валидацию, следует использовать зацикливание

```
//Допустим что код триггера $chooseMeds – "MEDS"
$bot->sendResponse($chooseMeds, static function () use ($bot) {
    $answer = new Response();

    //Проверяем, это первичный запрос или цикл?
    if ( ! $bot->isRepeatedRequest()) {
        //Нет, значит это первичный запрос со стороны пользователя, предлагаем выбор
        $answer->addText('Какую таблетку ты выберешь, Нео?');
        //Задаем циклирование, результат будем проверять в этом же триггере
        $bot->setRepeat(true);
    } else {
        //Неправильный выбор?
        if ($bot->getTriggerData('MEDS') !== 'Синяя') {
            $answer->addText('Неверный выбор, Нео');
            //Задать цикл
            $bot->setRepeat(true);
        } else {
            //Все ок, выход из триггера
            $answer->addText('Ты сделал правильный выбор о-о');
        }
    }
    return $answer;
});
```

### Внутреннее делегирование

[](#внутреннее-делегирование)

### Ручная подстановка данных для триггера

[](#ручная-подстановка-данных-для-триггера)

### Пост обработка ответа

[](#пост-обработка-ответа)

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity66

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

44

Last Release

2358d ago

Major Versions

0.5.0.1-beta → 1.0-RC12019-11-24

### Community

Maintainers

![](https://www.gravatar.com/avatar/959be03c427f636b98870cfe3a6bb6e60ddc9643b3a4b7ff581ae7e4ce92e758?d=identicon)[isamarin](/maintainers/isamarin)

---

Top Contributors

[![isamarin](https://avatars.githubusercontent.com/u/17625884?v=4)](https://github.com/isamarin "isamarin (131 commits)")

---

Tags

alisaphp-libraryphp7yandexyandex-alice

### Embed Badge

![Health badge](/badges/isamarin-alisa/health.svg)

```
[![Health](https://phpackages.com/badges/isamarin-alisa/health.svg)](https://phpackages.com/packages/isamarin-alisa)
```

###  Alternatives

[neuron-core/neuron-ai

The PHP Agentic Framework.

1.8k245.3k21](/packages/neuron-core-neuron-ai)[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3731.2M42](/packages/tencentcloud-tencentcloud-sdk-php)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
