Alice Skills Examples

repository·master·Indexed 41 days ago

https://github.com/yandex/alice-skills

Practical examples and templates for developing skills for Alice, Yandex's voice assistant, using the Yandex Dialogs platform. Includes implementations in Node.js and Python for deployment on Vercel, Yandex Cloud Functions, Google Cloud, and Azure, featuring webhook examples using Express and Flask.

Tokens
4.5K
Snippets
11
Records
17
Agent score
51%

What's inside Alice Skills

  1. Overview of Alice Skills examples

    master
    This repository contains examples of using Yandex Dialogs to create skills for Alice, Yandex's voice assistant. For instructions on how to deploy and publish these skills, refer to the official Yandex Dialogs documentation.
  2. Deploy the Morning Show skill template to Yandex Cloud Functions

    master

    This template is designed to be deployed as a Yandex Cloud Function using a Python 3.7 runtime. The skill provides content for the 'Morning Show' based on the current date, pulling data from a static CSV file. If no content is found for the current date, it returns a random entry from the file.

    To deploy this template, follow these steps:

    1. Prepare Content: Add your desired content to the data/data.csv file.
    2. Create Cloud Function: Create a new cloud function in the Yandex Cloud console.
    3. Upload Code: Copy all files from the show-template directory into the function editor.
    4. Set Runtime: Ensure the runtime environment is set to python/3.7.
    5. Configure Entry Point: Set the function's entry point method to skill.handle_dialog_yacloud.
    6. Deploy Version: Create a new version of the function.
    7. Register Skill: Create a new skill on the Yandex Dialogs platform and set the Backend to the Yandex Cloud function you just created.
  3. Handle Alice Skill dialog logic

    master

    The core logic of an Alice Skill is typically implemented in a handler function (e.g., handle_dialog(req, res)) that processes the incoming request and modifies the response object in place.

    Common logic patterns include:

    1. New User Detection: Check req['session']['new'] to initialize user-specific state or provide a welcome message.
    2. Intent Recognition: Inspect req['request']['original_utterance'] to determine user intent (e.g., checking if the user said 'ладно' or 'куплю').
    3. Session Management: Use a storage mechanism (like a dictionary or database) keyed by req['session']['user_id'] to maintain state across turns.
    4. Response Construction: Set res['response']['text'] for speech and res['response']['buttons'] for UI suggestions.
  4. Implement an Alice Skill endpoint with Express

    master

    To deploy a parrot-style Alice skill to Google Cloud, use an Express.js server that listens for POST requests on the root path (/). The server must parse JSON bodies and respond with a specific JSON structure containing version, session, and response (which includes text and end_session).

    This implementation demonstrates how to handle different command scenarios to test session and version persistence:

    • no text: Returns an empty string for text.
    • no version: Omits the version field from the response.
    • no session: Omits the session field from the response.
    • end session: Sets end_session: true in the response.
    • Default: Echoes the command text back to the user and keeps the session active.
    const express = require('express');
    const port = process.env.PORT || 3000;
    const app = express();
    
    app.use(express.json());
    
    app.post('/', function (req, res) {
      // Logic to handle req.body.request.command and return Alice-compatible JSON
      if (req.body.request.command == "no text") {
        res.json({
          version: req.body.version,
          session: req.body.session,
          response: {
            text: "",
            end_session: false,
          },
        });
      } else {
        // ... other command handlers
      }
    });
    
    app.listen(port);
  5. Implement an Alice Skill webhook with Flask

    master

    To deploy an Alice Skill as a web service (e.g., on Google Cloud), you can use a Flask application to handle incoming POST requests from Yandex. The webhook must receive a JSON payload containing the version, session, and request objects, and return a JSON response containing the version, session, and a response object.

    Key requirements for the response object:

    • version: Must match the version received in the request.
    • session: Must match the session received in the request.
    • response: Contains text (the speech output), buttons (suggested replies), and end_session (boolean to close the session).
    from flask import Flask, request
    import json
    
    app = Flask(__name__)
    
    @app.route("/", methods=['POST'])
    def main():
        req_data = request.json
        response = {
            "version": req_data['version'],
            "session": req_data['session'],
            "response": {
                "end_session": False
            }
        }
        
        # Logic to populate response['response'] goes here
        
        return json.dumps(response, ensure_ascii=False, indent=2)
  6. Implement an Alice Skill webhook using Flask

    master

    To deploy an Alice skill to a web service like Azure, you can use a Flask application to handle incoming POST requests from Yandex. The webhook must receive a JSON payload containing the version, session, and request objects, and return a JSON response containing the version, session, and response objects.

    Key requirements for the response structure:

    • version: Must match the version received in the request.
    • session: Must match the session received in the request.
    • response: Must contain text (the speech response) and optionally buttons or end_session.
    from flask import Flask, request
    import json
    
    app = Flask(__name__)
    
    @app.route("/", methods=['POST'])
    def main():
        # request.json contains the Alice request payload
        request_data = request.json
        
        response = {
            "version": request_data['version'],
            "session": request_data['session'],
            "response": {
                "end_session": False
            }
        }
    
        # Logic to populate response['response'] goes here
        # handle_dialog(request_data, response)
    
        return json.dumps(response, ensure_ascii=False, indent=2)
  7. Deploy a Parrot skill to Vercel/Now

    master

    This entrypoint is designed for deploying an Alice skill as an asynchronous serverless function on Vercel (formerly Now). It uses the micro package to handle JSON parsing.

    When the function is invoked, it extracts request, session, and version from the incoming JSON request. It then returns a response containing the same version and session to maintain the dialogue state, along with a response object.

    To prevent the dialogue from closing immediately, set response.end_session to false. To respond to the user, use response.text (e.g., echoing the request.original_utterance).

    const { json } = require('micro');
    
    module.exports = async (req, res) => {
        const { request, session, version } = await json(req);
    
        res.end(JSON.stringify({
            version,
            session,
            response: {
                text: request.original_utterance || 'Hello!',
                end_session: false,
            },
        }));
    };
  8. Implement the Alice skill handler for Universal Translator

    master

    The handler(event, context) function serves as the entrypoint for the Universal Translator skill when deployed to Yandex Cloud. It processes incoming Alice requests and manages the translation state.

    Input Structure

    The event object is expected to follow the Yandex Dialogs request format, specifically requiring:

    • event['request']['nlu']['intents']: A dictionary of detected intents (e.g., translate_main, translate_ellipsis, exit, YANDEX.HELP, YANDEX.REPEAT).
    • event['request']['command']: The raw command string.
    • event['state']['session']['translate']: A dictionary containing the current translation state (text, lang_from, lang_to).
    • event['state']['session']['last_phrase']: The text of the last response sent to the user.

    Output Structure

    The handler must return a dictionary compatible with the Yandex Dialogs response format:

    {
      "version": "string",
      "session": { ... },
      "response": {
        "text": "string",
        "end_session": "true" | "false"
      },
      "session_state": {
        "translate": { "text": "...", "lang_from": "...", "lang_to": "..." },
        "last_phrase": "string"
      }
    }
    def handler(event, context):
        # ... implementation logic ...
        return {
            'version': event['version'],
            'session': event['session'],
            'response': {
                'text': text,
                'end_session': end_session
            },
            'session_state': {'translate': translate_state, 'last_phrase': text}
        }
  9. Manage translation state with do_translate

    master

    The do_translate(form, translate_state) function handles the core logic of extracting translation parameters from an intent and performing the translation.

    Parameters

    • form: The intent object containing slots. Expected slots are phrase (the text to translate), from (source language), and to (target language).
    • translate_state: A dictionary representing the persistent session state used to accumulate missing parameters across multiple turns (ellipses).

    Logic Flow

    1. Extraction: It pulls phrase, from, and to from the form['slots'].
    2. Language Normalization: It uses lang_to_code to convert language names into ISO-like codes.
    3. State Accumulation: It updates translate_state with any newly provided information.
    4. Validation:
      • If text is missing, it asks for the text.
      • If the text is Russian-like but lang_to is missing, it asks for the target language.
      • If the text is not Russian-like but lang_from is missing, it asks for the source language.
    5. Execution: Once all parameters are present, it calls translate(**translate_state).

    Returns

    Returns a tuple of (response_text, updated_translate_state).

    def do_translate(form, translate_state):
        # ... logic to extract slots and update state ...
        tran_error, tran_result = translate(**translate_state)
        text = tran_error or tran_result
        return text, translate_state