Only this pageAll pages
Powered by GitBook
1 of 26

E.D.D.I

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Getting started

Version: ≥5.0.x

Welcome to EDDI!

This article will help you to get started with EDDI.

You have two options to run EDDI, The most convenient way is to run EDDI with Docker. Alternatively, of course, you can run EDDI also from the source by checking out the git repository and build the project with maven using either the mvn command line or an IDE such as eclipse.

Option 1 - EDDI with Docker

There are two ways to use Docker with EDDI, either with docker-compose or launch the container manually.

Prerequisite: You need an up and running Docker environment. (For references, see: )

Use docker-compose (recommended)

  1. Checkout the docker-compose file from Github:

  2. Run Docker Command:

Use launch docker containers manually

  1. Create a shared network

  2. Start a MongoDB instance using the MongoDB Docker image:

  3. Start EDDI :

Option 2 - Run from Source

Prerequisites:

  • Java 21

  • Maven 3.8.4

  • MongoDB > 4.0

How to run the project

Setup a local mongodb (> v4.0)

If no mongodb instance is available on the give host, quarkus will try to run a mongodb container on startup, given the host has a docker running server

On a terminal, under project root folder, run the following command:

  1. Go to Browser -->

Note: If running locally inside an IDE you need lombok to be enabled (otherwise you will get compile errors complaining about missing constructors). Either download as plugin (e.g. inside Intellij) or follow instructions here [https://projectlombok.org/](https://projectlombok.org/

Build App & Docker image

Download from Docker hub registry

Run Docker image

For production, launch standalone mongodb and then start an eddi instance as defined in the docker-compose file

For development, use

For integration testing run

or

Important for eclipse users: If you are planning to browse and build EDDI's code from eclipse, you must take in consideration that EDDI uses project Lombok, so you must add it to eclipse classpath, this can be done easily by executing this jar:.m2\repository\org\projectlombok\lombok\1.16.26\lombok-1.16.26.jar

https://docs.docker.com/learn/
https://github.com/labsai/EDDI/blob/master/docker-compose.yml
http://localhost:7070
https://hub.docker.com/r/labsai/eddi
 docker-compose up
docker network create eddi-network
docker run --name mongodb --network=eddi-network -d mongo
docker run --name eddi --network=eddi-network -p 7070:7070 -d labsai/eddi
./mvnw compile quarkus:dev
./mvnw clean package '-Dquarkus.container-image.build=true'
docker pull labsai/eddi
docker-compose up
docker-compose -f docker-compose.yml -f docker-compose.local.yml up
./integration-tests.sh
docker-compose -f docker-compose.yml -f docker-compose.local.yml -f docker-compose.testing.yml -p ci up -d

Creating your first Chatbots

Prerequisites: Up and Running instance of EDDI (see: Getting started)

How does it work?

In order to build a Chatbot with EDDI, you will have to create a few configuration files and POST them to the corresponding REST APIs.

A chatbot can consists of the following elements:

  1. (Regular) Dictionary to define the inputs from the users as well as their meanings in respective categories, expressed by a expression language e.g. apple -> fruit(apple)

  2. Behavior Rules triggering actions based on execution of behavior rules checking on certain conditions within the current conversation

Example of a resource reference

eddi://ai.labs.regulardictionary/regulardictionarystore/regulardictionaries/ID?version=VERSION

eddi:// URI resources starting with this protocol are to be related with in EDDI

ai.labs.regulardictionary Type of resource

/regulardictionarystore/regulardictionaries API path

ID ID of the resources

VERSION Read-only version of the resource (each change is a new version)

Version of this resource (each update operation will create a new version of the resource)

Git support

Git support

As part of EDDI's features, Git is supported, this means you can init, commit, push and pull a Chabot to a Git repository.

Understanding your first bot

The components of the generated bots

The Bot Father generates EDDI specific configuration in order to deploy a bot that utilises the ChatGPT API. EDDI is an middleware and therefore it enables the user to create a structured flow for parsing and manipulating user input, to be used by different chatbot APIs. The generated bots enable you to take the user input and to prepare the input to use the ChatGPT API without the need to have any knowledge of the API. This approach can be used with any chatbot engine. Therefore EDDI becomes the abstraction layer of your bot infrastructure.

In order to see the configuration necessary for a bot, we are going to open the bot manager that can be found on the dashboard.

After opening the bot manager a new tab opens that shows and overview of all currently configured bots.

Click on your created bot ("My first bot") in this example to see the bot configuration

The bot consists of different resources. These resources separate the different functions that are necessary to create a flow. The execution sequence of the packages is:

  1. Property (eddi://ai.labs.property)

  2. Parser (eddi://ai.labs.parser)

  3. Behavior (eddi://ai.labs.parser)

  4. HttpCalls (eddi://ai.labs.httpcalls)

  5. Output (eddi://ai.labs.output)

  6. Templating (eddi://ai.labs.templating)

When a user enters an input all resources are executed in the sequence above. After the execution of all the resources the bot output is generated. The user can then add another input, which triggers the next execution sequence to generate the next output.

Property

This resource holds all necessary properties to be stored for usage. For the case of generated bot these are:

  • chatGptApi - the URL of the ChatGPT API

  • chatGptModel - the model of ChatGPT that should be used

  • chatGptToken - the API key of ChatGPT

  • chatGptSystemPrompt - the prompt used to configure ChatGPT

  • chatGptIntroPrompt - the promt that is displayed to the user on starting the conversation

Parser

This resource parses the user input. It can be configured to understand different phrases. In the example bot there is no parser configuration necessary.

Behavior

This resource defines behaviors depending on user input, properties, http calls or context through behavior rules. In our example it is configured to take any input and create and action called "send_message".

HTTP Calls

This resource represents http calls to APIs. It is configured to call the ChatGPT API using the API key, whenever a user input has triggered the "send_message" action. As all user input triggers the "send_message" action, the package always calls the ChatGPT API with the user input.

It is also configured to build the output. The ChatGPT API responds with a JSON response. This is automatically parsed and the human readable output of the API is found and converted into an output. This output will be put in the chat.

Output

All output that is not handled via ChatGPT is created in this resource. In the example bot the only output necessary is the conversation start prompt.

Templating

This is an internal resource that enables EDDI to substitute template strings with values from the conversation.

EDDI Dashboard with deployed demo bot
EDDI bot manager overview
Configuration overview of the example bot
Http Connector
requests/sends data to a Rest API and makes the json response available within the conversation (e.g for Output
)
  • Output to answer the user's request based on actions triggered by behavior rules

  • Package to define which `LifecycleTasks` (such as the parser, behavior rules, rest api connector, output generation, ...) should be executed in order by how they are defined

  • Bot to define which packages should be executed in this bot

  • gitinit a Chatbot:

    Exporting a bot is a fairly simple process, send a POST request to the following API endpoint and you will receive the location of the exported zip file on the response headers, specifically the location header.

    Export Chatbot REST API Endpoint

    Element

    Value

    Http Method

    POST

    API endpoint

    /backup/export/{botId}?botVersion={botVersion}

    {botId}

    (Path parameter):String id of the bot that you wish to export.

    {botVersion}

    (Path parameter):Integer version of the bot.

    Example:

    Request URL:

    http://localhost:7070/backup/export/5aaf90e29f7dd421ac3c7dd4?botVersion=1

    Response Body: no content Response Code: 200 Response Headers:

    Importing a bot :

    Same process as exporting; send a POST request to the following API endpoint , you will receive the id of the imported bot on the response headers.

    Import Chatbot REST API Endpoint

    Element

    Value

    Http Method

    POST

    API endpoint

    /backup/import

    HTTP Content Type Header

    application/zip

    Request body

    the zip file binary.

    Example:

    For the sake of simplifying things you can use Postman to upload the zip file of the exported bot just don't forget to add the http header of content type : application/zip.

    Take a look at he image below to understand how can you upload the zip file in Postman:

    Important: The bot will not be deployed after import you will have to deploy it yourself by using the corresponding api endpoint, please referrer to Deploying a bot.

    {
        "access-control-allow-origin": "*",
        "date": "Mon, 19 Mar 2018 10:41:41 GMT",
        "access-control-allow-headers": "authorization, Content-Type",
        "content-length": "0",
        "location": "http://localhost:7070/backup/export/5aaf90e29f7dd421ac3c7dd4-1.zip",
        "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
        "content-type": null
    }

    Metrics

    E.D.D.I exposes all kinds of internal JVM metrics as prometheus export.

    These metrics are viewable here:

    http://<eddi-instance>/q/metrics

    In order to visualize these metrics, you can use this predefined dashboard for E.D.D.I:

    E.D.D.I dashboardData for Grafana

    E.D.D.I Documentation

    Prompt & Conversation Management Middleware for Conversational AI APIs. Developed in Java, powered by Quarkus, provided with Docker, and orchestrated with Kubernetes or Openshift.

    E.D.D.I (Enhanced Dialog Driven Interface) is a middleware to connect and manage LLM API bots with advanced prompt and conversation management for APIs such as OpenAI ChatGPT, Facebook Hugging Face, Anthropic Claude, Google Gemini and Ollama

    Developed in Java using Quarkus, it is lean, RESTful, scalable, and cloud-native. It comes as Docker container and can be orchestrated with Kubernetes or Openshift. The Docker image has been certified by IBM/Red Hat.

    Latest stable version: 5.5.1

    License: Apache License 2.0

    Project website:

    Intro

    E.D.D.I is a high performance middleware for managing conversations in AI-driven applications. It is designed to run efficiently in cloud environments such as Docker, Kubernetes, and Openshift. E.D.D.I offers seamless API integration capabilities, allowing easy connection with various conversational services or traditional REST APIs with runtime configurations. It supports the integration of multiple chatbots, even multiple versions of the same bot, for smooth upgrading and transitions.

    Notable features include:

    • Seamless integration with conversational or traditional REST APIs

    • Configurable NLP and Behavior rules to orchestrate LLM involvement

    • Support for multiple chatbots, including multiple versions of the same bot, running concurrently

    • Support for Major AI API integrations via langchain4j: OpenAI, Hugging Face (text only), Claude, Gemini, Ollama (and more to come)

    Technical specifications:

    • Resource-/REST-oriented architecture

    • Java Quarkus framework

    • JAX-RS

    • Dependency Injection

    • Prometheus integration (Metrics endpoint)

    • Kubernetes integration (Liveness/Readiness endpoint)

    • MongoDB for storing bot configurations and conversation logs

    • OAuth 2.0 (Keycloak) for authentication and user management

    • HTML, CSS, Javascript (Dashboard)

    • React (Basic Chat UI)

    here
    alt text

    Docker

    Setup

    1. Option: Use docker-compose (recommended)

      1. 1. Checkout the docker-compose file from github:

        1. 2. Run Docker Command:docker-compose up

    2. Option: Launch docker containers manually

    Start a MongoDB instance using the MongoDB docker image:

    Start EDDI:

    Langchain

    Version: ≥5.3.x

    The Langchain lifecycle task (using the langchain4j library) allows EDDI to leverage the capabilities of various large language model (LLM) APIs. This task seamlessly integrates with a range of currently supported APIs, including OpenAI's ChatGPT, Hugging Face models, Anthropic Claude, Google Gemini, and Ollama, thereby facilitating advanced natural language processing within EDDI bots.

    Note: To streamline the initial setup and configuration of the Langchain lifecycle task, you can utilize the "Bot Father" bot. The "Bot Father" bot guides you through the process of creating and configuring tasks, ensuring that you properly integrate the various LLM APIs. By using "Bot Father," you can quickly get your Langchain configurations up and running with ease, leveraging its intuitive interface and automated assistance to minimize errors and enhance productivity.

    Configuration

    RedHat Openshift

    E.D.D.I is enterprise certified to run on RedHat Openshift and is therefore offered with support on the redhat marketplace:

    EDDI-operator

    Output Templating

    One of the coolest features of EDDI is it will allow you dynamically template your output based on data that you would receive from httpCalls or context information for instance, that makes EDDI's replies to user interactions richly and dynamically.

    The output templating is evaluated by thymeleaf templating engine, that means you can use the majority of thymeleaf tags and expression language to define how you would like your output to be.

    docker run --name mongodb -e MONGODB_DBNAME=eddi -d mongo
    docker run --name eddi --link mongodb:mongodb -p 7070:7070 -d labsai/eddi
    https://github.com/labsai/EDDI/blob/master/docker-compose.yml
    Enabling the feature:

    Basically while creating the bot you must include eddi://ai.labs.output to one of the packages that will be part of the bot.

    Important: The templating feature will not work if it is included before eddi://ai.labs.output extension, it must be included after.

    Example

    Here is how the output templating should be specified inside of a package.

    Make sure the templating is defined after the output, not before.

    Additional Information :

    Thymeleaf documentation.

    {
      "packageExtensions": [
        {
          "type": "eddi://ai.labs.output",
          "config": {
            "uri": "eddi://ai.labs.output/outputstore/outputsets/{{outputset_id}}?version=1"
          }
        },
        {
          "type": "eddi://ai.labs.templating"
        }
      ]
    }
    The Langchain task is configured through a JSON object that defines a list of tasks, where each task can interact with a specific LLM API. These tasks can be tailored to specific use cases, utilizing unique parameters and settings.

    Configuration Parameters

    • actions: Defines the actions that the lifecycle task is responsible for.

    • id: A unique identifier for the lifecycle task.

    • type: Specifies the type of API (e.g., openai, huggingface, anthropic, gemini, ollama).

    • description: Brief description of what the task accomplishes.

    • parameters: Key-value pairs for API configuration such as API keys, model identifiers, and other API-specific settings.

      • systemMessage: Optional message to include in the system context.

      • prompt: User input to override before the request to the LLM. If not set or empty, the user input will be taken

      • sendConversation: Boolean indicating whether to send the entire conversation or only user input (

    Example Configuration

    Here’s an example of how to configure a Langchain task for various LLM APIs:

    OpenAI Configuration

    Hugging Face Configuration

    Anthropic Configuration

    Note: Anthropic doesn't allow the first message to be from the bot, therefore includeFirstBotMessage should be set to false for anthropic api calls.

    Vertex Gemini Configuration

    Ollama Configuration

    API Endpoints

    The Langchain task can be managed via specific API endpoints, facilitating easy setup, management, and operation within the EDDI ecosystem.

    Endpoints Overview

    1. Read JSON Schema

      • Endpoint: GET /langchainstore/langchains/jsonSchema

      • Description: Retrieves the JSON schema for validating Langchain configurations

    2. List Langchain Descriptors

      • Endpoint: GET /langchainstore/langchains/descriptors

      • Description: Returns a list of all Langchain configurations with optional filters

    3. Read Langchain Configuration

      • Endpoint: GET /langchainstore/langchains/{id}

      • Description: Fetches a specific Langchain configuration by its ID

    4. Update Langchain Configuration

      • Endpoint: PUT /langchainstore/langchains/{id}

      • Description: Updates an existing Langchain configuration

    5. Create Langchain Configuration

      • Endpoint: POST /langchainstore/langchains

      • Description: Creates a new Langchain configuration

    6. Duplicate Langchain Configuration

      • Endpoint: POST /langchainstore/langchains/{id}

      • Description: Duplicates an existing Langchain configuration

    7. Delete Langchain Configuration

      • Endpoint: DELETE /langchainstore/langchains/{id}

      • Description: Deletes a specific Langchain configuration

    Sure, here is the extended section for the configuration options:

    Extended Configuration Options

    The LangChain lifecycle task offers extended configuration options to fine-tune the behavior of tasks before and after they interact with LLM APIs. These configurations help in managing properties, handling responses, and controlling retries.

    Example of Extended Configuration

    Below is an example configuration showcasing more advanced options such as preRequest, postResponse, and retryHttpCallInstruction.

    Configuration Parameters Explained

    • preRequest.propertyInstructions: Defines properties to be set before making the request to the LLM API. Each instruction specifies:

      • name: The property name.

      • valueString: The value to be assigned to the property.

      • scope: The scope of the property (e.g., step, conversation, longTerm).

    • postResponse.propertyInstructions: Defines properties to be set based on the response from the LLM API. Each instruction specifies:

      • name: The property name.

      • valueString: The value to be assigned to the property.

      • scope: The scope of the property (e.g., step

    • postResponse.outputBuildInstructions: Configures how the response should be transformed into output. This is an alternative to addToOutput if you want to manipulate the llm results before adding them to the bot output. Each instruction specifies:

      • pathToTargetArray: The path to the array in the response where data is located.

      • iterationObjectName: The name of the object for iterating over the array.

    • postResponse.qrBuildInstructions: Configures quick replies based on the response. Each instruction specifies:

      • pathToTargetArray: The path to the array in the response where quick replies are located.

      • iterationObjectName: The name of the object for iterating over the array.

      • quickReplyValue: The value for the quick reply.

    This extended configuration provides more control and flexibility in managing tasks and handling responses, ensuring that your LangChain tasks operate efficiently and effectively.

    Common Issues and Troubleshooting

    • API Key Expiry: Ensure API keys are valid and renew them before expiry.

    • Model Misconfiguration: Verify model names and parameters to ensure they match those supported by the LLM provider.

    • Timeouts and Performance: Adjust timeout settings based on network performance and API responsiveness.

    Usage

    Openshift Setup

    Prerequisites

    • Openshift 4.3+ Deployment

    • Block Storage (Preferable with storage class)

    Installing the Operator from the RedHat Marketplace

    1. Head to the Operator section in the Admin Overview and go to the OperatorHub

    2. Choose which version of the EDDI Operator to use (Marketplace or normal)

    3. Click install and leave the defaults (All Namespaces, Update Channel alpha and Approval Strategy Automatic)

    4. Click subscribe

    Using the operator

    After the installation of the operator, go to the installed Operators menu point and click on the first EDDI menu on top and create a new Instance. Below is a minimal CustomResource. The storageclass_name has to be changed to the name of an existing StorageClass, the environment variable will be added as a label to the mongoDB deployment.

    The operator will create a route automatically so you can access the EDDI admin panel. Per default the route will take the name of the CR. With the CR from above the route would look like this: eddi-route-$NAMESPACE.apps.ocp.example.com ($NAMESPACE will be the name of the project where the CR was created.)

    https://marketplace.redhat.com/en-us/products/labsai

    Your first bot

    How to use the godfather bot

    After EDDI has started point your browser to this URL:

    You should be seeing this on the page

    EDDI start screen without bots deployed

    Click on "Deploy Example Bot". This will deploy the Bot Father bot, to help you create your own bots utilizing ChatGPT.

    EDDI start screen with Bot Father bot deployed

    This bot walks you through the process of creating a new bot that talks to ChatGPT. In order to create that bot, you will need to get an API key from ChatGPT. This key can be obtained here:

    As soon as you have your key, click on Open and the first conversation with the Bot Father will start.

    Bot Father conversation start

    Click on "Let's get started!" to start the process.

    First you need to type the name of your bot.

    Next, you need to define the purpose of the bot.

    Every bot needs an introduction to set the tone and the context of the bot for ChatGPT. This is the first prompt. This defines how ChatGPT is going to reply.

    Now, the Bot Father needs the ChatGPT API key. Please enter the key here without any leading or trailing blanks.

    Everything is now set up. When clicking on "Create the bot!" the Bot Father will create a new bot and you can start talking to it.

    The new bot is deployed and by clicking on open, you can instantly talk to the bot.

    CircleCI

    Bot Manager GUI

    Bot Manager (GUI)

    Documentation in progress

    The bot manager is a friendly Graphical user interface that help EDDI's bot developers to deploy, chat, edit bots packages and also update a bot if an updated package is available!

    {
      "tasks": [
        {
          "actions": ["send_message"],
          "id": "enhancedOpenAIQuery",
          "type": "openai",
          "description": "Generates text responses using OpenAI's GPT-4o model, tailored with specific response characteristics.",
          "parameters": {
            "apiKey": "your-openai-api-key",
            "modelName": "gpt-4o",
            "temperature": "0.7",
            "timeout": "15000",
            "logRequests": "true",
            "logResponses": "true",
            "systemMessage": "",
            "sendConversation": "true",
            "includeFirstBotMessage": "true",
            "logSizeLimit": "-1",
            "convertToObject": "false",
            "addToOutput": "true"
          }
        }
      ]
    }
    {
      "tasks": [
        {
          "actions": [
            "send_message"
          ],
          "id": "huggingFaceQuery",
          "type": "huggingface",
          "description": "Generates text using Hugging Face's transformers.",
          "parameters": {
            "accessToken": "your-huggingface-access-token",
            "modelId": "llama3",
            "temperature": "0.7",
            "timeout": "15000",
            "systemMessage": "",
            "prompt": "",
            "sendConversation": "true",
            "includeFirstBotMessage": "true",
            "logSizeLimit": "-1",
            "convertToObject": "false",
            "addToOutput": "true"
          }
        }
      ]
    }
    {
      "tasks": [
        {
          "actions": ["send_message"],
          "id": "anthropicQuery",
          "type": "anthropic",
          "description": "Generates text using Anthropic's AI model.",
          "parameters": {
            "apiKey": "your-anthropic-api-key",
            "modelName": "Claude",
            "temperature": "0.7",
            "timeout": "15000",
            "logRequests": "true",
            "logResponses": "true",
            "systemMessage": "",
            "prompt": "",
            "sendConversation": "true",
            "includeFirstBotMessage": "false",
            "logSizeLimit": "-1",
            "convertToObject": "false",
            "addToOutput": "true"
          }
        }
      ]
    }
    {
      "tasks": [
        {
          "actions": ["send_message"],
          "id": "vertexGeminiQuery",
          "type": "gemini",
          "description": "Generates text using Vertex AI Gemini model.",
          "parameters": {
            "publisher": "vertex-ai",
            "projectId": "your-project-id",
            "modelId": "vertex-gemini-large",
            "temperature": "0.7",
            "timeout": "15000",
            "logRequests": "true",
            "logResponses": "true",
            "systemMessage": "",
            "prompt": "",
            "sendConversation": "true",
            "includeFirstBotMessage": "true",
            "logSizeLimit": "-1",
            "convertToObject": "false",
            "addToOutput": "true"
          }
        }
      ]
    }
    {
      "tasks": [
        {
          "actions": ["send_message"],
          "id": "ollamaQuery",
          "type": "ollama",
          "description": "Generates text using Ollama's language model.",
          "parameters": {
            "model": "ollama-v1",
            "timeout": "15000",
            "logRequests": "true",
            "logResponses": "true",
            "systemMessage": "",
            "prompt": "",
            "sendConversation": "true",
            "includeFirstBotMessage": "true",
            "logSizeLimit": "-1",
            "convertToObject": "false",
            "addToOutput": "true"
          }
        }
      ]
    }
    {
      "tasks": [
        {
          "id": "task_1",
          "type": "example_type",
          "description": "This is an example task description",
          "actions": [
            "action_1",
            "action_2"
          ],
          "preRequest": {
            "propertyInstructions": [
              {
                "name": "exampleProperty",
                "valueString": "exampleValue",
                "scope": "step"
              }
            ]
          },
          "postResponse": {
            "propertyInstructions": [
              {
                "name": "exampleResponseProperty",
                "valueString": "responseValue",
                "scope": "conversation"
              }
            ],
            "outputBuildInstructions": [
              {
                "pathToTargetArray": "response.data",
                "iterationObjectName": "item",
                "outputType": "exampleType",
                "outputValue": "exampleOutputValue"
              }
            ],
            "qrBuildInstructions": [
              {
                "pathToTargetArray": "response.quickReplies",
                "iterationObjectName": "item",
                "quickReplyValue": "exampleQuickReplyValue",
                "quickReplyExpressions": "exampleExpression"
              }
            ]
          },
          "parameters": {
            "apiKey": "<apiKey>"
          }
        }
      ]
    }
    apiVersion: labs.ai/v1alpha1
    kind: Eddi
    metadata:
      name: eddi
    spec:
      size: 1
      mongodb:
        environment: prod
        storageclass_name: managed-nfs-storage
        storage_size: 20G
    true
    or
    false
    , default:
    true
    ).
  • includeFirstBotMessage: Boolean indicating whether to include the first bot message in the conversation (true or false, default: true).

  • logSizeLimit: Limit for the size of the log (-1 for no limit).

  • convertToObject: Boolean indicating whether to convert the LLM response to an object (true or false, default: false). Note: For this to work, the response from your LLM needs to be in valid JSON format!

  • addToOutput: Boolean indicating whether the LLM output should automatically be added to the output (true or false, default: false).

  • ,
    conversation
    ,
    longTerm
    ).

    outputType: The type of output to generate.

  • outputValue: The value to be used for output.

  • quickReplyExpressions: The expressions for the quick reply.

  • Access to the bot manager:

    You can access to bot manager via:

    http://localhost:7070/manage?apiUrl=http%3A%2F%2Flocalhost%3A7070

    Main page

    1. Allows you to log out from the bot manager and redirects you to login page.

    2. This is the bots view where you can see the list of all bots both deployed and non deployed bots.

    3. You can use the text box next t o this label to enter your search criteria such as a bot name .

    4. This is the list of all bots in this image example for brevity we showed only one bot, but most likely you will find a lot of bots (deployed and non deployed).

    5. Name of the bot.

    6. Version of that bot that it is deployed.

    7. Last modification date of the entire bot resources.

    8. Opens the chat with the bot by using the chat screen, more details later

    9. Undeploy this bot from this EDDI instance.

    10. Packages used in this bot

    11. Packages view: coming soon.

    Bot overview

    1. The login allow connection with social Media such as GitHub or Google

    2. Use login and password as credentials for registered users, basically you will have to go through the registration form which is pretty straightforward.

    Bot Overview

    Edit bot description modal

    Edit JSON

    Bot's packages edit view

    Bot packages updates

    Dictionary selection from package editing view

    Provide a name for the bot
    Define the purpose of the bot
    Introduction prompt
    Enter ChatGPT API Key
    Bot creation screen
    EDDI Dashboard with deployed first bot

    FAQs

    How to...?

    ...start a conversation with a welcome / intro message?

    You will need behavior rules

    Import/Export a Chatbot

    In this tutorial we will talk about importing/exporting bots, this is a very useful feature that will allow our bots to be very portable and easy to re-use in other machines/instances of EDDI and of course to backup and restore our bots and maintain them and keep them shiny.

    Exporting a Chatbot:

    Exporting a bot is a fairly simple process, send a POST request to the following API endpoint and you will receive the location of the exported zip file on the response headers, specifically the location header.

    Passing context information

    In this section we will explain how EDDI handles the context of a conversation and which data can be passed within the scope of a conversation.

    In order to talk to EDDI within a context, a POST request shall be sent to /bots/{environment}/{botId}/{conversationId}, (same way as interacting in a normal conversation in EDDI) but this time we must provide more parameters:

    and an
    outputset
    for that.

    For the behavior rules, you have three possibilities (ordered by recommendation):

    1) Match for the action CONVERSATION_START

    2) check if the triggered action has never be triggered before

    3) Check how often this rule has succeeded before.

    Outputset:

    ...say something based on what the bot previously said?

    (Think of a form-like behavior, asking a couple of questions and sending these results somewhere.)

    Check whether a certain action had been triggered in the previous conversation step.

    Have a question that is not covered? Drop us an email at [email protected], we are happy to enhance our documentation!

    {
      "behaviorGroups": [
        {
          "name": "Onboarding",
          "behaviorRules": [
            {
              "name": "Welcome",
              "actions": [
                "welcome"
              ],
              "conditions": [
                {
                  "type": "actionmatcher",
                  "configs": {
                    "actions": "CONVERSATION_START"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "behaviorGroups": [
        {
          "name": "Onboarding",
          "behaviorRules": [
            {
              "name": "Welcome",
              "actions": [
                "welcome"
              ],
              "conditions": [
                {
                  "type": "actionmatcher",
                  "configs": {
                    "actions": "welcome",
                    "occurrence": "never"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "behaviorGroups": [
        {
          "name": "Onboarding",
          "behaviorRules": [
            {
              "name": "Welcome",
              "actions": [
                "welcome"
              ],
              "conditions": [
                {
                  "type": "occurrence",
                  "configs": {
                    "maxTimesOccurred": "0",
                    "behaviorRuleName": "Welcome"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "outputSet": [
        {
          "action": "welcome",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Some output here...",
                  "delay": 3000
                }
              ]
            }
          ],
          "quickReplies": [
            // quickreplies here
          ]
        }
      ]
    }
    {
      "behaviorGroups": [
        {
          "name": "Onboarding",
          "behaviorRules": [
            {
              "name": "Ask for Name",
              "actions": [
                "ask_for_name"
              ],
              "conditions": [
                {
                  "type": "actionmatcher",
                  "configs": {
                    "actions": "some_previous_action",
                    "occurrence": "lastStep"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
    Export Chatbot REST API Endpoint

    Export a chatbot

    POST http://localhost:7070/backup/export/:botId?botVersion=:botVersion

    Path Parameters

    Name
    Type
    Description

    botId

    string

    Id of the bot you wish to export

    Query Parameters

    Name
    Type
    Description

    botVersion

    string

    Version of the bot

    {
    "access-control-allow-origin": "*",
    "date": "Mon, 19 Mar 2018 10:41:41 GMT",
    "access-control-allow-headers": "authorization, Content-Type",
    "content-length": "0",
    "location": "http://localhost:7070/backup/export/5aaf90e29f7dd421ac3c7dd4-1.zip",
    "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS"
    

    Example:

    Request URL:

    http://localhost:7070/backup/export/5aaf90e29f7dd421ac3c7dd4?botVersion=1

    Response Body: no content Response Code: 200 Response Headers:

    Importing a bot:

    Same process as exporting; send a POST request to the following API endpoint , you will receive the id of the imported bot on the response headers.

    Import Chatbot REST API Endpoint

    Element

    Value

    Http Method

    POST

    API endpoint

    /backup/import

    HTTP Content Type Header

    application/zip

    Request body

    the zip file binary.

    Example:

    For the sake of simplifying things you can use Postman to upload the zip file of the exported bot just don't forget to add the http header of content type : application/zip.

    Take a look at he image below to understand how can you upload the zip file in Postman:

    Important: The bot will not be deployed after import you will have to deploy it yourself by using the corresponding API endpoint, please referrer to Deploying a bot.

    Send message in a conversation with a Chatbot REST API Endpoint

    Element

    Tags

    HTTP Method

    POST

    API endpoint

    /bots/{environment}/{botId}/{conversationId}

    {environment}

    (Path parameter):String Deployment environment (e.g: restricted,unrestricted,test)

    {botId}

    (Path parameter):String Id of the bot that you wish to continue a conversation with.

    {conversationId}

    (Path parameter): String Id of the conversation that you wish to send the message to.

    Example

    Here is an example of a JSON object of the input data:

    Additional information:

    We can also use http://localhost:7070/chat to test the context parameters by providing Context Type,Context Name, Context Value. see image below :

    Callbacks

    Semantic Parser

    In this section we will be showcasing the semantic parser, which is a very important module of EDDI that plays the part of the engine that parses the semantics introduced in EDDI Chabot's definitions.

    We will need regular dictionaries in order to store our custom words and phrases .

    First, we will make a POST to /regulardictionarystore/regulardictionaries with a JSON in the body like this:

    The API should return with 201 with a URI referencing the newly created dictionary :

    eddi://ai.labs.regulardictionary/regulardictionarystore/regulardictionaries/<UNIQUE_ID>?version=<VERSION>

    This URI will be used in the parser configuration.

    The next step is to create a parser configuration, including the reference to the previously created dictionary .

    A POST to /parserstore/parsers must be performed.

    Submit this type of JSON

    Important: Don't forget to replace the <UNIQUE_ID> and <VERSION> !

    Example of a parser configuration

    Description of Semantic Parser types

    In order to use the parser based on the created configurations, we will have to make a POST to /parser/<PARSER_ID>?version=<VERSION>

    In the body just put plain text, it is what you would like to be parsed.

    The parser will return expressions representing the elements from your plain text

    Note: Keep in mind that this parser is made for human dialog, not parsing (full-text) documents.

    Output Configuration

    Output Configurations are rather simple as they contain prepared sentences that the Chatbot should reply to the user (depending on the actions coming from the Behavior Rules).

    Simple Output Configuration looks like this:

    The configuration contains an array of outputSet, which can contain one or more output objects.

    The minimum amount of values that you need to provide in order be functional are action and outputs.

    {
    "access-control-allow-origin": "*",
    "date": "Mon, 19 Mar 2018 10:41:41 GMT",
    "access-control-allow-headers": "authorization, Content-Type",
    "content-length": "0",
    "location": "http://localhost:7070/backup/export/5aaf90e29f7dd421ac3c7dd4-1.zip",
    "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
    "content-type": null
    }
    {
      "input": "",
      "context": {
        "onboardingOfUser": {
          "type": "string",
          "value": "true"
        },
        "userInfo": {
          "type": "object",
          "value": {
            "username": "Barbara"
          }
        }
      }
    }
    {
      "language": "en",
      "words": [
        {
          "word": "hello",
          "expressions": "greeting(hello)",
          "frequency": 0
        }
      ],
      "phrases": [
        {
          "phrase": "good afternoon",
          "expressions": "greeting(good_afternoon),language(english)"
        }
      ]
    }

    Matches an email address with regex (\b[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}\b)

    Time

    eddi://ai.labs.parser.dictionaries.time

    Matches the following time formats: e.g : 01:20 , 01h20 , 22:40 , 13:43:23

    Number

    eddi://ai.labs.parser.dictionaries.ordinalNumber

    Ordinal numbers in English language such as 1st, 2nd, 3rd, 4th, 5th, ...

    Regular

    eddi://ai.labs.parser.dictionaries.regular

    URI to a regular dictionary resource: eddi://ai.labs.regulardictionary/regulardictionarystore/regulardictionaries/<UNIQUE_ID>version <VERSION>

    Type

    EDDI URI

    Description

    Integer

    eddi://ai.labs.parser.dictionaries.integer

    Matches all positive integers

    Decimal

    eddi://ai.labs.parser.dictionaries.decimal

    Matches decimal numbers with . as well as , as a fractional separator

    Punctuation

    eddi://ai.labs.parser.dictionaries.punctuation

    Matches common punctuation:

    !(exclamation_mark)

    ? (question_mark)

    . (dot)

    , (comma)

    : (colon)

    ; (semicolon)

    Email

    eddi://ai.labs.parser.dictionaries.email

    {
      "extensions": {
        "dictionaries": [
          {
            "type": "eddi://ai.labs.parser.dictionaries.integer"
          },
          {
            "type": "eddi://ai.labs.parser.dictionaries.decimal"
          },
          {
            "type": "eddi://ai.labs.parser.dictionaries.punctuation"
          },
          {
            "type": "eddi://ai.labs.parser.dictionaries.email"
          },
          {
            "type": "eddi://ai.labs.parser.dictionaries.time"
          },
          {
            "type": " eddi://ai.labs.parser.dictionaries.ordinalNumber"
          },
          {
            "type": "eddi://ai.labs.parser.dictionaries.regular",
            "config": {
              "uri": "eddi://ai.labs.regulardictionary/regulardictionarystore/regulardictionaries/<UNIQUE_ID>?version=<VERSION>"
            }
          }
        ],
        "corrections": [
          {
            "type": "eddi://ai.labs.parser.corrections.stemming",
            "config": {
              "language": "english",
              "lookupIfKnown": "false"
            }
          },
          {
            "type": "eddi://ai.labs.parser.corrections.levenshtein",
            "config": {
              "distance": "2"
            }
          },
          {
            "type": "eddi://ai.labs.parser.corrections.mergedTerms"
          }
        ]
      },
      "config": null
    }
    ,
    "content-type": null
    }

    Now let's look at a more complex output configuration file:

    Explanation of model

    Key

    Description

    action

    This will be the "actions" coming from the Behavior Rules. If a rule succeeds, the defined action will be stored in the conversation memory.

    outputs

    This array of output objects are the outputs that will be replied back to the user in case the action matched the action key. You can define multiple output objects, which represent separate chat bubbles on the client side. If more than one valueAlternatives is defined, one will be picked randomly. If this output will be triggered again in a future conversationStep, then another output of this array will be favored in order to avoid repetition. (If all available outputs have been selected, it is randomized again like in the beginning). The type is mainly there to be able to distinguish the type of output on the client side (e.g. image, video

    quickReplies

    This is an array of QuickReply objects. Each object must contain a value, which is the text that should be displayed to the user (e.g. as button) in the conversation flow. The expressions is optional, you can define one or more comma separated expressions that define the meaning of this QuickReply. Those expressions will be temporarily taken into account in the semantic parser in the next conversationStep. So if a user chooses one of the quick replies, the parser would recognize them (even if not defined in any of the dictionaries explicitly) and resolve them with the expressions

    timesOccurred

    How often this action should have occurred within that conversation in order to be selected as output to the user (thus, if value of 1, it would be chosen if the action occurs for the second time)

    returnDetailed (Optional)

    (Query parameter):Boolean - Default : false Will return all sub results of the entire conversation steps, otherwise only public ones such as input, action, output & quickReplies.

    returnCurrentStepOnly (Optional)

    (Query parameter):Boolean - Default : true Will return only the latest conversationStep that has just been processed, otherwise returns all conversationSteps since the beginning of this conversation.

    Request Body

    a JSON object sent in the request body consists of the usual input text (message to the bot) only this time we are going to provide context information through a key value data structure ; the Context value must have one of the following : string,object or expressions.

    Deployement management of Chatbots

    Deployement management of Chatbots

    In this section we will discuss the deployment management of Chatbots which consists of deployment/undeployment, checking status of deployment and list all the deployed Chatbots.

    After all the resources required of the chatbot has been well created and configured ( Dictionary ,Behavior Rules,Output,Package,etc..) and the Chatbot is created through a POST to the API endpoint /botstore/bots, the deployment management of the Chatbots is offered by EDDI is key to have granular control over the deployed bots.

    Deployment of a Chatbot :

    The deployment of a specific chatbot is done through a POST to /administration/{environment}/deploy/{botId}

    Deploy Chatbot REST API Endpoint

    Example :

    Request URL:

    http://localhost:7070/administration/unrestricted/deploy/5aaf98e19f7dd421ac3c7de9?version=1&autoDeploy=true

    Response Body:

    no content

    Response Code:

    202

    Response Headers:

    Undeployment of a Chatbot

    The undeployment of a specific chatbot is done through a POST to /administration/{environment}/undeploy/{botId}

    Undeploy Chatbot REST API Endpoint

    Example :

    Undeploy a chatbot

    Request URL

    http://localhost:7070/administration/unrestricted/undeploy/5aaf98e19f7dd421ac3c7de9?version=1

    Response Body

    no content

    Response Code

    202

    Response Headers

    Check the deployment status of a chatbot:

    Check the deployment status of a bot is done through a GET to /administration/{environment}/deploymentstatus/{botId}

    Deployment status of a Chatbot REST API Endpoint

    Example:

    Request URL

    http://localhost:7070/administration/unrestricted/deploymentstatus/5aaf98e19f7dd421ac3c7de9?version=1

    Response Body

    READY

    Response Code

    200

    Response Headers

    List all deployed Chatbots:

    To list all the deployed Chabots a GET to /administration/{environment}/deploymentstore/{botId}:

    List of Deployed Chatbots REST API Endpoint

    Example :

    Request URL

    http://localhost:7070/deploymentstore/deployments

    Response Code

    200

    Response Body

    Response Headers

    Setting Up EDDI on AWS with MongoDB Atlas

    This guide provides step-by-step instructions to set up EDDI on Amazon ECS and connect it to a MongoDB Atlas cluster.

    Prerequisites

    1. AWS Account: Ensure you have an AWS account with the necessary permissions to create ECS clusters, task definitions, and IAM roles

    2. MongoDB Atlas Account: Create an account on if you don't have one

    Step 1: Set Up MongoDB Atlas

    1. Create a MongoDB Atlas Cluster

    1. Sign Up / Log In:

      • Go to and log in

    2. Create a New Cluster:

      • Click "Build a Cluster"

    2. Create a Database User

    1. Add Database User:

      • Navigate to "Database Access" under the "Security" tab

      • Click "Add New Database User"

      • Create a user with the required roles and note the username and password

    3. Whitelist IP Addresses

    1. Network Access:

      • Navigate to "Network Access" under the "Security" tab

      • Click "Add IP Address"

      • Add the IP addresses that need access, including your local machine and ECS IP range

    Step 2: Set Up Amazon ECS

    1. Create a Task Definition

    1. Navigate to ECS:

      • Go to the Amazon ECS console

      • Click "Task Definitions" and then "Create new Task Definition"

      • Select "FARGATE" as the launch type

    2. Create an ECS Cluster

    1. Create Cluster:

      • Navigate to "Clusters" and click "Create Cluster"

      • Choose "Networking only" (Fargate) and follow the prompts

    3. Create a Service

    1. Create Service:

      • Go to "Services" and click "Create"

      • Select your cluster and task definition

      • Configure the service with the desired number of tasks and networking settings

    Step 3: Connect EDDI to MongoDB Atlas

    1. Modify Application Configuration:

      • Ensure that your EDDI application uses the MongoDB connection string from the environment variables

      • Update any necessary configuration files

    2. Deploy the Application:

    Security Considerations

    1. Encryption:

      • Use TLS/SSL for encrypted connections (ssl=true in the connection string)

    2. IAM Roles:


    By following these steps, you can set up EDDI on Amazon ECS and connect it to MongoDB Atlas securely and efficiently. If you encounter any issues or have further questions, please refer to the AWS and MongoDB Atlas documentation or contact support.

    Create a "Hello World" bot

    Prerequisites: Up and Running instance of EDDI (see: )

    Let's get started

    Follow these steps to create the configuration files you will need:

    {
      "outputSet": [
        {
          "action": "welcome",
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Welcome! I am E.D.D.I."
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "outputSet": [
        {
          "action": "welcome",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Welcome!"
                }
              ]
            },
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "I am E.D.D.I. How are you doing today?"
                }
              ]
            }
          ],
          "quickReplies": [
            {
              "value": "I am fine",
              "expressions": "feeling(fine)"
            },
            {
              "value": "not so good",
              "expressions": "feeling(not_good)"
            }
          ]
        },
        {
          "action": "greet",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Hi there! Nice to meet up! :-)"
                },
                {
                  "type": "text",
                  "text": "Hello you! It is a pleasure meeting you.. :-)"
                }
              ]
            }
          ]
        },
        {
          "action": "greet",
          "timesOccurred": 1,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Did we already say hi ?! Well, twice is better than not at all! ;-)"
                },
                {
                  "type": "text",
                  "text": "I like it if people are polite and greet twice, rather than not at all ;-)"
                }
              ]
            }
          ]
        },
        {
          "action": "say_goodbye",
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "See you soon!"
                }
              ]
            }
          ]
        }
      ]
    }
    ,
    audio
    , etc).
    defined within this quick reply.

    Element

    Value

    HTTP Method

    POST

    API endpoint

    /administration/{environment}/deploy/{botId}

    {environment}

    (Path parameter):String deployment environment (e.g: restricted,unrestricted,test)

    {botId}

    (Path parameter):String id of the bot that you wish to deploy.

    Element

    Value

    HTTP Method

    POST

    API endpoint

    /administration/{environment}/undeploy/{botId}

    {environment}

    (Path parameter):String deployment environment (e.g: restricted,unrestricted,test)

    {botId}

    (Path parameter):String id of the bot that you wish to undeploy.

    Element

    Value

    HTTP Method

    GET

    Api endpoint

    /administration/{environment}/deploymentstatus/{botId}

    {environment}

    (Path parameter):String deployment environment (e.g: restricted,unrestricted,test)

    {botId}

    (Path parameter):String id of the bot that you wish to check its deployment status.

    Response

    NOT_FOUND, IN_PROGRESS, ERROR and READY.

    Element

    Value

    HTTP Method

    GET

    API endpoint

    /deploymentstore/deployments

    Choose AWS as the cloud provider and select a region

  • Choose the free tier (for development) or an appropriate plan for production purposes

  • Click "Create Cluster"

  • Configure Cluster:

    • After the cluster is created, click on "Connect"

    • Select "Connect Your Application"

    • Copy the connection string (e.g., mongodb+srv://<user>:<password>@<host>/eddi?retryWrites=true&w=majority -Dmongodb.database=eddi)

  • Configure Task Definition:

    • Use the following JSON configuration:

  • Deploy your EDDI application to ECS using the service created

  • Test the Connection:

    • Verify that the application connects to MongoDB Atlas by checking application logs and MongoDB Atlas metrics

  • Assign IAM roles to ECS tasks to limit permissions
  • Network Configuration:

    • Place ECS tasks in private subnets and use a NAT gateway for internet access

    • Configure security groups for ECS tasks and MongoDB Atlas

  • MongoDB Atlas
    MongoDB Atlas
    {
    "access-control-allow-origin": "*",
    "date": "Mon, 19 Mar 2018 16:32:58 GMT",
    "access-control-allow-headers": "authorization, Content-Type",
    "content-length": "0",
    "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
    "content-type": null
    }
    {
    "access-control-allow-origin": "*",
    "date": "Mon, 19 Mar 2018 16:38:36 GMT",
    "access-control-allow-headers": "authorization, Content-Type",
    "content-length": "0",
    "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
    "content-type": null
    
    }
    {
    "access-control-allow-origin": "*",
    "date": "Mon, 19 Mar 2018 16:33:08 GMT",
    "access-control-allow-headers": "authorization, Content-Type",
    "content-length": "5",
    "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
    "content-type": "text/plain;charset=utf-8"
    }
    [
      {
        "botId": "5aaf90e29f7dd421ac3c7dd4",
        "botVersion": 1,
        "environment": "unrestricted",
        "deploymentStatus": "deployed"
      },
      {
        "botId": "5aaf90e29f7dd421ac3c7dd4",
        "botVersion": 1,
        "environment": "restricted",
        "deploymentStatus": "deployed"
      },
      {
        "botId": "5aaf98e19f7dd421ac3c7de9",
        "botVersion": 1,
        "environment": "unrestricted",
        "deploymentStatus": "deployed"
      }
    ]
    {
    "access-control-allow-origin": "*",
    "date": "Mon, 19 Mar 2018 16:33:29 GMT",
    "access-control-allow-headers": "authorization, Content-Type",
    "content-length": "414",
    "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
    "content-type": "application/json"
    }
    {
       "containerDefinitions": [
       {
       "name": "eddi",
       "image": "<image-id>.dkr.ecr.<region>.amazonaws.com/eddi:latest",
       "cpu": 1024,
       "memoryReservation": 2048,
       "portMappings": [
       {
       "containerPort": 7070,
       "hostPort": 7070,
       "protocol": "tcp"
       }
       ],
       "essential": true,
       "command": [
       "/bin/bash"
       ],
       "environment": [
       {
       "name": "JAVA_OPTS_APPEND",
       "value": "-Dmongodb.connectionString=mongodb+srv://<user>:<password>@<host>/eddi?retryWrites=true&w=majority -Dmongodb.database=eddi"
       }
       ],
       "mountPoints": [],
       "volumesFrom": [],
       "logConfiguration": {
       "logDriver": "awslogs",
       "options": {
       "awslogs-group": "eddi",
       "awslogs-region": "<region>",
       "awslogs-stream-prefix": "eddi"
       }
       },
       "healthCheck": {
       "command": [
       "CMD-SHELL",
       "curl -f http://localhost:7070/q/health || exit 1"
       ],
       "interval": 30,
       "timeout": 5,
       "retries": 3
       }
       }
       ],
       "networkMode": "awsvpc",
       "revision": 1,
       "volumes": [],
       "status": "ACTIVE",
       "requiresAttributes": [
       {
       "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
       },
       {
       "name": "com.amazonaws.ecs.capability.docker-remote-api.1.24"
       },
       {
       "name": "ecs.capability.execution-role-awslogs"
       },
       {
       "name": "com.amazonaws.ecs.capability.ecr-auth"
       },
       {
       "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
       },
       {
       "name": "com.amazonaws.ecs.capability.docker-remote-api.1.21"
       },
       {
       "name": "com.amazonaws.ecs.capability.task-iam-role"
       },
       {
       "name": "ecs.capability.container-health-check"
       },
       {
       "name": "ecs.capability.execution-role-ecr-pull"
       },
       {
       "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
       },
       {
       "name": "ecs.capability.task-eni"
       }
       ],
       "placementConstraints": [],
       "compatibilities": [
       "EC2",
       "FARGATE"
       ],
       "requiresCompatibilities": [
       "EC2",
       "FARGATE"
       ],
       "cpu": "1024",
       "memory": "2048"
    }
    1. Creating Output

    See also Output Configuration.

    You have guessed it correctly, another POST to /outputstore/outputsets creates the bot's Output with a JSON in the body like this:

    You should again get a return code of 201 with a URI in the location header referencing the newly created output :

    eddi://ai.labs.output/outputstore/outputsets/<UNIQUE_OUTPUTSET_ID>?version=<OUTPUTSET_VERSION>

    Example :

    eddi://ai.labs.output/outputstore/outputsets/5a26d97417312628b46119fc?version=1

    4. Creating the Package

    Now we will align the just created LifecycleTasks in the Package. Make a POST to /packagestore/packages with a JSON in the body like this:

    Package parameters

    Name

    Description

    Required

    packageextensions

    Array of PackageExtension

    PackageExtension.type

    possible values, see table below "Extension Types"

    PackageExtension.extensions

    Array of Object

    False

    PackageExtension.config

    Extension Types in this examples

    Extension

    Config

    eddi://ai.labs.output

    Object Config contains param uri with Link to output set, e.g. eddi://ai.labs.output/outputstore/outputsets/5a26d97417312628b46119fc?version=1

    eddi://ai.labs.package/packagestore/packages/<UNIQUE_PACKAGE_ID>?version=<PACKAGE_VERSION>

    Example

    eddi://ai.labs.package/packagestore/packages/5a2ae60f17312624f8b8a445?version=1

    See also the API documentation at http://localhost:7070/view#!/configurations/createPackage

    5. Creating a Bot

    Make a POST to /botstore/bots with a JSON like this:

    Bot parameters

    Name

    Description

    packages

    Array of String, references to Packages

    b. You should again get a return code of 201 with a URI in the location header referencing the newly created bot :

    eddi://ai.labs.bot/botstore/bots/<UNIQUE_BOT_ID>?version=<BOT_VERSION>

    Example:

    eddi://ai.labs.bot/botstore/bots/5a2ae68a17312624f8b8a446?version=1

    See also the API documentation at http://localhost:7070/view#!/configurations/createBot

    6. Launching the Bot

    Finally, we are ready to let the bot fly. From here on, you have the possibility to let an UI do it for you or you do it step by step.

    The UI that automates these steps can be reached here: /chat/unrestricted/<UNIQUE_BOT_ID>

    Otherwise via REST:

    1. Deploy the Bot:

      Make a POST to /administration/unrestricted/deploy/<UNIQUE_BOT_ID>?version=<BOT_VERSION>

      You will receive a 202 http code.

    2. Since deployment could take a while it has been made asynchronous.

    3. Make a GET to /administration/unrestricted/deploymentstatus/<UNIQUE_BOT_ID>?version=<BOT_VERSION> to find out the status of deployment.

    NOT_FOUND, IN_PROGRESS, ERROR and READY is what you can expect to be returned in the body.

    1. As soon as the Bot is deployed and has READY status, make a POST to /bots/unrestricted/<UNIQUE_BOT_ID>

      1. You will receive a 201 with the URI for the newly created Conversation, like this:

        1. e.g.

          eddi://ai.labs.conversation/conversationstore/conversations/<UNIQUE_CONVERSATION_ID>

    2. Now it's time to start talking to our Bot 1. Make a POST to /bots/unrestricted/<UNIQUE_BOT_ID>/<UNIQUE_CONVERSATION_ID>

    Option 1: is to hand over the input text as contentType text/plain. Include the User Input in the body as text/plain (e.g. Hello)

    Option 2: is to hand over the input as contentType application/json, which also allows you to handover context information that you can use with the eddi configurations 1. Include the User Input in the body as application/json (e.g. Hello)

    1. You have two query params you can use to config the returned output 1. returnDetailed - default is false - will return all sub results of the entire conversation steps, otherwise only public ones such as input, action, output & quickreplies 2. returnCurrentStepOnly - default is true - will return only the latest conversation step that has just been processed, otherwise returns all conversation steps since the beginning of this conversation

    2. The output from the bot will be returned as JSON

    3. If you are interested in fetching the conversationmemory at any given time, make a GET to /bots/unrestricted/<UNIQUE_BOT_ID>/<UNIQUE_CONVERSATION_ID>?returnDetailed=true (the query param is optional, default is false)

    If you made it till here, CONGRATULATIONS, you have created your first Chatbot with EDDI !

    By the way you can use the attached postman collection below to do all of the steps mentioned above by clicking send on each request in postman.

    1. Create outputSet

    2. Creating package

    3. Creating bot

    4. Deploy the bot

    5. Create conversation

    6. Say Hello to the bot

    External Links

    Using collections in postman

    Getting started
    21KB
    Creating and chatting with a bot.postman_collection.json
    Open
    Example to download

    Managed Bots

    Managed Bots

    This feature will allow you to take advantage of EDDI's automatic management of bots, it is possible to avoid creating conversations and managing them yourself, but let them be managed by EDDI.

    This will act as a shortcut to start directly a conversation with a bot that covers a specific intent.

    But first you will have to set up a BotTrigger.

    OpenAI Platformplatform.openai.com
    Link to get a ChatGPT API key
    http://localhost:7070/localhost
    Default EDDI URL when starting EDDI via docker
    {
      "outputSet": [
        {
          "action": "CONVERSATION_START",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Hello World!"
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "packageExtensions": [
        {
          "type": "eddi://ai.labs.output",
          "config": {
            "uri": "eddi://ai.labs.output/outputstore/outputsets/<UNIQUE_OUTPUTSET_ID>?version=<OUTPUTSET_VERSION>"
          }
        }
      ]
    }
    {
         "packages": [
              "eddi://ai.labs.package/packagestore/packages/<UNIQUE_PACKAGE_ID>?version=<PACKAGE_VERSION>"
         ]
    }
    {
         "input": "some user input"
    }

    Config object, but can be empty.

    True

    BotTrigger

    The request model

    Description of the request model

    Element

    Description

    intent

    (String) keyword or phrase (camel case or with '-') that will be used in managed bots to trigger the bots defined in this model

    botDeployments

    (Array:<BotDeployment>) array of BotDeployment. If multiple botDeployments are defined, one will be picked randomly.

    environment

    (String) the environment that you would like (restricted, unrestricted, test)

    botId

    (String) the id of the bot that you want to create the botTrigger for it.

    initialContext

    (Array <Object> ) As context can be handed over on each request to the bot, initialContext allows the definition of context the bot should get at the very first conversation step when a conversation with the bot is started (only way to get context to the bot in the first conversation step)

    BotTrigger API endpoints

    HTTP Method

    API Endpoint

    Request Body

    Response

    DELETE

    /bottriggerstore/bottriggers/{intent}

    N/A

    N/A

    GET

    /bottriggerstore/bottriggers/{intent}

    N/A

    Bot Triggers-model

    PUT

    Triggering a ManagedBot

    To trigger a managed bot you will have to call the following API endpoints.

    API Methods

    HTTP Method

    API Endpoint

    Request Body

    Response

    GET

    /managedbots​/{intent}​/{userId}

    N/A

    Conversation model

    POST

    /managedbots​/{intent}​/{userId}

    Input model

    N/A

    POST

    Description API endpoint required path parameters

    Element

    Description

    {intent}​

    (String) the label/keyword used originally to point to this BotTrigger

    {userId}​

    (String) used to specify the user who triggered the conversation

    Example :

    1/Create a BotTrigger

    Request URL:

    POST http://localhost:7070//bottriggerstore/bottriggers

    Request Body

    Response Body

    no content

    Response Code

    200

    Response Headers

    2/Trigger the ManagedBot

    Request URL:

    POST http://localhost:7070/managedbots/weather_trigger/myUserId

    Request Body

    Response Body

    Response Code

    200

    Response Headers

    Codacy Badge

    Extensions

    In this article we will talk about EDDI's extensions.

    EDDI's extensions are the features that your current instance of EDDI is supporting, the latter are used in the process of configuring/developing a Chatbot.

    The list of extensions will allow you to have an overview of what is enabled in your current instance of EDDI, the list can be retrieved by calling the API endpoint below.

    Note All EDDI's resources start with eddi://, this is used to distinguish if the resource is an EDDI extension, e.g : callbacks, httpcalls, outputsets, bot packages, etc..

    Extensions REST API Endpoint

    Model

    Description of the model

    Example

    More about regular dictionaries can be found .

    Request URL

    GET http://localhost:7070/extensionstore/extensions

    Response Body

    Response Code

    200

    Response Headers

    {
      "intent": "string",
      "botDeployments": [
        {
          "environment": "environment",
          "botId": "string",
          "initialContext": {
            "additionalProp1": {
              "type": "string",
              "value": ""
            },
            "additionalProp2": {
              "type": "string",
              "value": ""
            },
            "additionalProp3": {
              "type": "string",
              "value": ""
            }
          }
        }
      ]
    }
    {
      "intent": "weather_trigger",
      "botDeployments": [
        {
          "environment": "unrestricted",
          "botId": "5bf5418c46e0fb000b7636d0",
          "initialContext": {}
        }
      ]
    }
    access-control-allow-headers: authorization, Content-Type 
    access-control-allow-methods: GET, PUT, POST, DELETE, PATCH, OPTIONS 
    access-control-allow-origin: * 
    access-control-expose-headers: location 
    connection: Keep-Alive 
    content-length: 0 
    date: Mon, 18 Mar 2019 00:31:07 GMT 
    keep-alive: timeout=5, max=100 
    server: Apache/2.4.29 (Ubuntu)
    {
      "input": "Hello managed bot!",
      "context": {}
    }
    {
      "botId": "5bf5418c46e0fb000b7636d0",
      "botVersion": 10,
      "userId": "myUserId",
      "environment": "unrestricted",
      "conversationState": "READY",
      "redoCacheSize": 0,
      "conversationOutputs": [
        {
          "input": "Hello managed bot!",
          "expressions": "unknown(Hello), unknown(managed), unknown(bot!)",
          "intents": [
            "unknown",
            "unknown",
            "unknown"
          ]
        }
      ],
      "conversationProperties": {},
      "conversationSteps": [
        {
          "conversationStep": [
            {
              "key": "input:initial",
              "value": "Hello managed bot!"
            }
          ],
          "timestamp": 1552869578596
        }
      ]
    }
    access-control-allow-headers: authorization, Content-Type 
    access-control-allow-methods: GET, PUT, POST, DELETE, PATCH, OPTIONS 
    access-control-allow-origin: * 
    access-control-expose-headers: location 
    connection: Keep-Alive 
    content-length: 0 
    date: Mon, 18 Mar 2019 00:31:07 GMT 
    keep-alive: timeout=5, max=100 
    server: Apache/2.4.29 (Ubuntu)

    /bottriggerstore/bottriggers/{intent}

    Bot Triggers-model

    N/A

    POST

    /bottriggerstore/bottriggers

    Bot Triggers-model

    N/A

    /managedbots​/{intent}​/{userId}​/endConversation

    Input model

    N/A

    Element

    Value

    HTTP Method

    GET

    API Endpoint

    /extensionstore/extensions

    Element

    Value

    type

    (String) The type of the extension

    displayName

    (String) A given name to the extension

    configs

    (Object) Configuration of the extension

    extensions

    (Object) Extensions of the extension

    here
    [
      {
        "type": "string",
        "displayName": "string",
        "configs": {},
        "extensions": {}
      }
    ]
    [ {
      "type" : "ai.labs.parser",
      "displayName" : "Input Parser",
      "configs" : {
        "includeUnknown" : {
          "displayName" : "Include Unknown Expressions",
          "fieldType" : "BOOLEAN",
          "defaultValue" : true,
          "optional" : true
        },
        "includeUnused" : {
          "displayName" : "Include Unused Expressions",
          "fieldType" : "BOOLEAN",
          "defaultValue" : true,
          "optional" : true
        },
        "appendExpressions" : {
          "displayName" : "Append Expressions",
          "fieldType" : "BOOLEAN",
          "defaultValue" : true,
          "optional" : true
        }
      },
      "extensions" : {
        "corrections" : [ {
          "type" : "ai.labs.parser.corrections.levenshtein",
          "displayName" : "Damerau Levenshtein Correction",
          "configs" : {
            "distance" : {
              "displayName" : "Distance",
              "fieldType" : "INT",
              "defaultValue" : 2,
              "optional" : true
            }
          },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.corrections.stemming",
          "displayName" : "Grammar Stemming Correction",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.corrections.phonetic",
          "displayName" : "Phonetic Matching Correction",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.corrections.mergedTerms",
          "displayName" : "Merged Terms Correction",
          "configs" : { },
          "extensions" : { }
        } ],
        "normalizer" : [ {
          "type" : "ai.labs.parser.normalizers.punctuation",
          "displayName" : "Punctuation Normalizer",
          "configs" : {
            "removePunctuation" : {
              "displayName" : "Remove Punctuation",
              "fieldType" : "BOOLEAN",
              "defaultValue" : false,
              "optional" : true
            },
            "punctuationRegexPattern" : {
              "displayName" : "Punctuation RegEx Pattern",
              "fieldType" : "STRING",
              "defaultValue" : "!?:.,;",
              "optional" : true
            }
          },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.normalizers.specialCharacter",
          "displayName" : "Convert Special Character Normalizer",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.normalizers.contractedWords",
          "displayName" : "Contracted Word Normalizer",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.normalizers.allowedCharacter",
          "displayName" : "Remove Undefined Character Normalizer",
          "configs" : { },
          "extensions" : { }
        } ],
        "dictionaries" : [ {
          "type" : "ai.labs.parser.dictionaries.integer",
          "displayName" : "Integer Dictionary",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.dictionaries.decimal",
          "displayName" : "Decimal Dictionary",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.dictionaries.ordinalNumber",
          "displayName" : "Ordinal Numbers Dictionary",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.dictionaries.punctuation",
          "displayName" : "Punctuation Dictionary",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.dictionaries.time",
          "displayName" : "Time Expression Dictionary",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.dictionaries.email",
          "displayName" : "Email Dictionary",
          "configs" : { },
          "extensions" : { }
        }, {
          "type" : "ai.labs.parser.dictionaries.regular",
          "displayName" : "Regular Dictionary",
          "configs" : {
            "uri" : {
              "displayName" : "Resource URI",
              "fieldType" : "URI",
              "optional" : false
            }
          },
          "extensions" : { }
        } ]
      }
    }, {
      "type" : "ai.labs.behavior",
      "displayName" : "Behavior Rules",
      "configs" : {
        "appendActions" : {
          "displayName" : "Append Actions",
          "fieldType" : "BOOLEAN",
          "defaultValue" : true,
          "optional" : false
        },
        "uri" : {
          "displayName" : "Resource URI",
          "fieldType" : "URI",
          "optional" : false
        }
      },
      "extensions" : { }
    }, {
      "type" : "ai.labs.output",
      "displayName" : "Output Generation",
      "configs" : {
        "uri" : {
          "displayName" : "Resource URI",
          "fieldType" : "URI",
          "optional" : false
        }
      },
      "extensions" : { }
    }, {
      "type" : "ai.labs.templating",
      "displayName" : "Templating",
      "configs" : { },
      "extensions" : { }
    }, {
      "type" : "ai.labs.property",
      "displayName" : "Property Extraction",
      "configs" : { },
      "extensions" : { }
    }, {
      "type" : "ai.labs.callback",
      "displayName" : "External Callback",
      "configs" : {
        "callbackUri" : {
          "displayName" : "Callback URI",
          "fieldType" : "URI",
          "optional" : false
        },
        "callOnActions" : {
          "displayName" : "Call on Actions",
          "fieldType" : "STRING",
          "defaultValue" : "",
          "optional" : true
        },
        "timeoutInMillis" : {
          "displayName" : "Timeout in Milliseconds",
          "fieldType" : "URI",
          "defaultValue" : 10000,
          "optional" : true
        }
      },
      "extensions" : { }
    }, {
      "type" : "ai.labs.httpcalls",
      "displayName" : "Http Calls",
      "configs" : {
        "uri" : {
          "displayName" : "Resource URI",
          "fieldType" : "URI",
          "optional" : false
        }
      },
      "extensions" : { }
    } ]
    {
      "access-control-allow-origin": "*",
      "date": "Sat, 19 May 2018 22:00:11 GMT",
      "content-type": "application/json",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "6208",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location"
    }
    Docker Repository on Quay

    Conversations

    Conversations

    In this section we will talk about how to send/receive messages from a Chatbot, the first step is the creation of the conversation, once you have the conversation Id you will be able to send a message to the Chatbot through a POST and to receive the message through A GET, while having the capacity to send context information through the body of the POST request as well.

    Important: EDDI has a great feature for conversations with chatbots, it's the possibility to go back in time by using the two API endpoints : /undo and /redo !

    Creating/initiating a conversation :

    Create a Conversation with a Chatbot REST API Endpoint

    Response Model

    Description of the Conversation response model

    Note conversationProperties can also be used in output templating e.g: [[${properties.city}]].

    Sample Response

    The conversationId will be provided through the location HTTP Header of the response, you will use that later to submit messages to the Chabot to maintain a conversation.

    Example :

    Request URL:

    http://localhost:7070/bots/unrestricted/5ad2ab182de29719b44a792a

    Response Body

    no content

    Response Code

    201

    Response Headers

    Send/receive messages

    Send a message

    Send message in a conversation with a Chatbot REST API Endpoint

    Example :

    Request URL

    http://localhost:7070/bots/restricted/5aaf90e29f7dd421ac3c7dd4/5add1fe8a081a228a0588d1c?returnDetailed=false&returnCurrentStepOnly=true

    Request Body

    Response Code

    200

    Response Body

    Response Headers

    Receive a message

    Receive message in a conversation with a Chatbot REST API Endpoint

    Example

    Request URL:

    http://localhost:7070/bots/unrestricted/5aaf90e29f7dd421ac3c7dd4/5add1fe8a081a228a0588d1c?returnDetailed=false

    Response Body

    Response Code

    200

    Response Headers

    Undo and redo :

    The undo and redo methods basically allow you to return a step back in a conversation, this is done by sending a POST along with bot and conversation ids to /bots/{environment}/{botId}/redo/{conversationId} endpoint, the GET call of the same endpoint with the same parameters will allow you to see if the last submitted undo/redo was successful by receiving a true or false in the response body.

    Undo and redo in a conversation REST API Endpoint

    Example (undo)

    Request URL:

    http://localhost:7070/bots/restricted/5aaf98e19f7dd421ac3c7de9/undo/5ade58dda081a23418503d6f

    Response Body

    no content

    Response Code

    200

    Response Headers

    Sample bot:

    Behavior Rules

    Behavior Rules

    Behavior Rules are very flexible in structure to cover most use cases that you will come across. Behavior Rules are clustered in Groups. Behavior Rules are executed sequential within each Group. As soon as one Behavior Rule succeeds, all remaining

    (integer) if undo has been performed, this number indicates how many times redo can be done (=times undo has been triggered)

    conversationOutputs

    (Array: <conversationOutput>) Array of conversationOutput

    conversationOutput.input

    (String) The user's input.

    conversationOutput.expressions

    (Array: <String>) an array of the expressions involved in the creation of this reply (output).

    conversationOutput.intents

    (Array: <String>) an array of the intents involved in the creation of this reply (output).

    conversationOutput.actions

    (Array: <String>) an array of the actions involved in the creation of this reply (output).

    conversationOutput.httpCalls

    (Array: <JsonObject>) an array of the httpCalls objects involved in the creation of this reply (output).

    conversationOutput.properties

    (Array: <JsonObject>) the list of available properties in the current conversation.

    conversationOutput.output

    (String) The final bot's output

    conversationProperties

    (Array: <>) Array of conversationProperty, <nameOfProperty> is a dynamic value that represents the name of the property

    <nameOfProperty>.name

    (String) name of the property.

    <nameOfProperty>.value

    (String|JsonObject) value of the property.

    <nameOfProperty>.scope

    (String) scope can be

    step (=valid one interaction [user input to user output]),

    conversation (=valid for the entire conversation),

    longTerm (=valid across conversations [based on given userId])

    conversationSteps

    (Array: <conversationStep>) Array of conversationStep.

    conversationStep.key

    (String) the element key in the conversationStep e.g key : input:initial, actions

    conversationStep.value

    (String) the element value of the conversationStep e.g in case of actionq as key it could be an array string [ "current_weather_in_city" ].

    timestamp.timestamp

    (dateTime) the timestamp in (ISO 8601) format

    (Query parameter):Boolean - Default : false

    returnCurrentStepOnly

    (Query parameter):Boolean - Default : true

    Request Body

    JSON Object , example : { "input": "the message", "context": {} }

    The context here is where you pass context variables that can be evaluated by EDDI, we will be explaining this in more details in Passing Context Information

    (Query parameter):Boolean - Default : false

    Element

    Tags

    HTTP Method

    POST

    API endpoint

    /bots/{environment}/{botId}

    {environment}

    (Path parameter):String Deployment environment (e.g: restricted,unrestricted,test)

    {botId}

    (Path parameter):String Id of the bot that you wish to start conversation with.

    Element

    Tags

    botId

    (String) The id of the bot that sent the reply.

    botVersion

    (integer) The version of the bot that sent the reply.

    userId

    (String) The id of the user who interacted with the bot.

    environment

    (String) the name of the environment where the bot is deployed

    conversationState

    (String) The state of the current conversation, could be:

    READY,

    IN_PROGRESS,

    ENDED,

    EXECUTION_INTERRUPTED,

    ERROR

    Element

    Tags

    HTTP Method

    POST

    API endpoint

    /bots/{environment}/{botId}/{conversationId}

    {environment}

    (Path parameter):String Deployment environment (e.g: restricted,unrestricted,test)

    botId

    (Path parameter):String Id of the bot that you wish to continue a conversation with.

    conversationId

    (Path parameter): String Id of the conversation that you wish to send the message to.

    Element

    Tags

    HTTP Method

    GET

    API endpoint

    /bots/{environment}/{botId}/{conversationId}

    {environment}

    (Path parameter):String Deployment environment (e.g: restricted,unrestricted,test)

    {botId}

    (Path parameter):String Id of the bot that you wish to continue a conversation with.

    {conversationId}

    (Path parameter): String Id of the conversation that you wish to receive a the message from.

    Element

    Tags

    HTTP Method

    POST

    API endpoint

    /bots/{environment}/{botId}/[undo/redo]/{conversationId}

    {environment}

    (Path parameter):String Deployment environment (e.g: restricted,unrestricted,test)

    {botId}

    (Path parameter):String Id of the bot that you wish to continue a conversation with.

    {conversationId}

    (Path parameter): String Id of the conversation that you wish to undo/redo the last conversation step.

    5KB
    weather_bot_v2.zip
    archive
    Open
    Weather-bot-v2.zip

    redoCount

    returnDetailed

    returnDetailed

    {
      "botId": "string",
      "botVersion": Integer,
      "userId": "string",
      "environment": "string",
      "conversationState": "string",
      "redoCacheSize": 0,
      "conversationOutputs": [
                    "input"    :    "string",
                    "expressions"    :    <arrayOfString>,
                    "intents" :        <arrayOfString>,
                    "actions"    :    <arrayOfString>,
                    "httpCalls"    :    {JsonObject},
                    "properties" :    <arrayOfString>,
                    "output" : "string"
        ],
      "conversationProperties": {
            "<nameOfProperty>" : {
          "name" : "string",
          "value" : "string" | {JsonObject},
          "scope" : "string"
        }},
      "conversationSteps": [
        {
          "conversationStep": [
            {
              "key": "string",
              "value": {}
            }
          ],
          "timestamp": "dateTime"
        }
      ]
    }
    {
      "botId": "5bf5418c46e0fb000b7636d0",
      "botVersion": 10,
      "userId": "anonymous-zj1p1GDtM5",
      "environment": "unrestricted",
      "conversationState": "READY",
      "redoCacheSize": 0,
      "conversationOutputs": [
        {
          "input": "madrid",
          "expressions": "unknown(madrid)",
          "intents": [
            "unknown"
          ],
          "actions": [
            "current_weather_in_city"
          ],
          "httpCalls": {
            "currentWeather": {
              "coord": {
                "lon": -3.7,
                "lat": 40.42
              },
              "weather": [
                {
                  "id": 800,
                  "main": "Clear",
                  "description": "clear sky",
                  "icon": "01n"
                }
              ],
              "base": "stations",
              "main": {
                "temp": 10.86,
                "pressure": 1019,
                "humidity": 66,
                "temp_min": 8.33,
                "temp_max": 13.33
              },
              "visibility": 10000,
              "wind": {
                "speed": 5.7,
                "deg": 240
              },
              "clouds": {
                "all": 0
              },
              "dt": 1551735805,
              "sys": {
                "type": 1,
                "id": 6443,
                "message": 0.0049,
                "country": "ES",
                "sunrise": 1551681788,
                "sunset": 1551723011
              },
              "id": 3117735,
              "name": "Madrid",
              "cod": 200
            }
          },
          "properties": {
            "currentWeather": {
              "coord": {
                "lon": -3.7,
                "lat": 40.42
              },
              "weather": [
                {
                  "id": 800,
                  "main": "Clear",
                  "description": "clear sky",
                  "icon": "01n"
                }
              ],
              "base": "stations",
              "main": {
                "temp": 10.86,
                "pressure": 1019,
                "humidity": 66,
                "temp_min": 8.33,
                "temp_max": 13.33
              },
              "visibility": 10000,
              "wind": {
                "speed": 5.7,
                "deg": 240
              },
              "clouds": {
                "all": 0
              },
              "dt": 1551735805,
              "sys": {
                "type": 1,
                "id": 6443,
                "message": 0.0049,
                "country": "ES",
                "sunrise": 1551681788,
                "sunset": 1551723011
              },
              "id": 3117735,
              "name": "Madrid",
              "cod": 200
            },
            "city": "madrid"
          },
          "output": [
            "The current weather situation of madrid is clear sky at 10.86 °C"
          ]
        }
      ],
      "conversationProperties": {
        "city": {
          "name": "city",
          "value": "madrid",
          "scope": "conversation"
        }
      },
      "conversationSteps": [
        {
          "conversationStep": [
            {
              "key": "input:initial",
              "value": "madrid"
            },
            {
              "key": "actions",
              "value": [
                "current_weather_in_city"
              ]
            },
            {
              "key": "output:text:current_weather_in_city",
              "value": "The current weather situation of madrid is clear sky at 10.86 °C"
            }
          ],
          "timestamp": 1551736024776
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 15 Apr 2018 01:45:09 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.conversation/conversationstore/conversations/5ad2aea52de29719b44a792c",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "input": "Hi!",
      "context": {}
    }
    {
      "botId": "5aaf90e29f7dd421ac3c7dd4",
      "botVersion": 1,
      "environment": "restricted",
      "conversationState": "READY",
      "redoCacheSize": 0,
      "conversationSteps": [
        {
          "conversationStep": [
            {
              "key": "input:initial",
              "value": "Hi!"
            }
          ],
          "timestamp": 1524441253098
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 22 Apr 2018 23:54:12 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "321",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "content-type": "application/json;resteasy-server-has-produces=true"
    }
    {
      "botId": "5aaf90e29f7dd421ac3c7dd4",
      "botVersion": 1,
      "environment": "restricted",
      "conversationState": "READY",
      "redoCacheSize": 0,
      "conversationSteps": [
        {
          "conversationStep": [
            {
              "key": "actions",
              "value": [
                "global_menu"
              ]
            },
            {
              "key": "output:text:global_menu",
              "value": "What do you want to do?"
            },
            {
              "key": "quickReplies:global_menu",
              "value": [
                {
                  "value": "Show me your skillz",
                  "expressions": "confirmation(show_skills)",
                  "default": false
                },
                {
                  "value": "Tell me a joke",
                  "expressions": "trigger(tell_a_joke)",
                  "default": false
                }
              ]
            }
          ],
          "timestamp": 1524441064450
        },
        {
          "conversationStep": [
            {
              "key": "input:initial",
              "value": "Hi!"
            }
          ],
          "timestamp": 1524441253098
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Mon, 23 Apr 2018 00:07:25 GMT",
      "cache-control": "no-cache",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "891",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "content-type": "application/json"
    }
    {
      "access-control-allow-origin": "*",
      "date": "Mon, 23 Apr 2018 22:20:57 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "content-type": null
    }
    Behavior Rules
    in this
    Group
    will be skipped.

    Groups

    Type of Conditions

    Each Behavior Rule has a list of conditions, that, depending on the condition , might have a list of sub-conditions.

    If all conditions are true, then the Behavior Rule is successful and it will trigger predefined actions.

    List of available conditions:

    • Input Matcher

    • Context Matcher

    • Connector

    • Negation

    General Structure

    conditions are always children of either a Behavior Rule or another condition. It will always follows that same structure.

    Description of condition structure

    Input Matcher

    The inputmatcher is used to match user inputs. Not directly the real input of the user, but the meaning of it, represented by expressions that are resolved from by the parser.

    Description

    Element

    Value

    Description

    type

    inputmatcher

    configs

    expressions

    comma separated list of

    expressions such as:

    expression(value),expression2(value2),

    yetAnotherExpressions(anotherValue(withASubValue))

    occurrence

    currentStep - used in case if the user said it in this conversationStep

    lastStep - used in case if the user said it in the previous conversationStep

    anyStep - used in case if the user said it in any step if this whole conversation

    never - used in case if the user has never said that, including the current step

    If the user would type "hello", and the parser resolves this as expressions "greeting(hello)" [assuming it has been defined in one of the dictionaries], then a condition could look as following in order to match this user input meaning:

    This inputmatcher condition will match any expression of type greeting, may that be "greeting(hello)", "greeting(hi)" or anything else. Of course, if you would want to match greeting(hello) explicitly, you would put "greeting(hello)" as value for the "expressions" field.

    Context Matcher

    The contextmatcher is used to match context data that has been handed over to EDDI alongside the user input. This is great to check certain conditions that come from another system, such as the day time or to check the existence of user data.

    Description

    Element

    Value

    Description

    type

    contextmatcher

    configs

    contextKey

    The key for this context (defined when handing over context to EDDI)

    contextType

    expressions

    object

    string

    Examples

    Connector

    The connector is there to all logical OR conditions within rules. By default all conditions are AND conditions, but in some cases it might be suitable to connect conditions with a logical OR.

    Description

    Element

    Value

    type

    connector

    values

    operator (either AND or OR)

    Examples

    Negation

    Inverts the overall outcome of the children conditions

    In some cases it is more relevant if a condition is false than if it is true, this is where the negation condition comes into play. The logical result of all children together (AND connected), will be inverted.

    Example:

    Occurrence

    Defines the occurrence/frequency of an action in a Behavior Rule.

    Dependency

    Check if another Behavior Rule has met it's condition or not in the same conversationStep. Sometimes you need to know if a rule has succeeded , dependency will take that rule that hasn't been executed yet in a sandbox environment as a reference for an other behavior rule.

    Action Matcher

    As inputMatcher doesn't look at expressions but it looks for actions instead, imagine a Behavior Rule has been triggered and you want to check if that action has been triggered before.

    Dynamic Value Matcher

    This will allow you to compile a condition based on any http request/properties or any sort of variables available in EDDI's context.

    The Behavior Rule API Endpoints

    The API Endpoints below will allow you to manage the Behavior Rules in your EDDI instance.

    The {id} is a path parameters that indicate which behavior rule you want to alter.

    API Methods

    HTTP Method

    API Endpoint

    Request Body

    Response

    DELETE

    /behaviorstore/behaviorsets/{id}

    N/A

    N/A

    GET

    /behaviorstore/behaviorsets/{id}

    N/A

    BehaviorSet model

    PUT

    Example

    We will demonstrate here the creation of a BehaviorSet

    Request URL

    POST http://localhost:7070/behaviorstore/behaviorsets

    Request Body

    Response Body

    no content

    Response Code

    201

    Response Headers

    {
      "behaviorGroups": [
        {
          "name": "GroupName",
          "behaviorRules": [
            {
              "name": "RuleName",
              "actions": [
                "action-to-be-triggered"
              ],
              "conditions": [
                <CONDITIONS>
              ]
            },
            {
              "name": "DifferentRule",
              "actions": [
                "another-action-to-be-triggered"
              ],
              "conditions": [
                <CONDITIONS>
              ]
            },
            <MORE_RULES>
          ]
        }
      ]
    }
    (...)
      "conditions": [
        {
          "type": "inputmatcher",
          "configs": {
            "expressions": "greeting(*)",
            "occurrence": "currentStep"
          }
        }
      ]
    (...)
    (...)
      "conditions": [
        {
          "type": "contextmatcher",
          "configs": {
            "contextType": "expressions",
            "contextKey": "someContextName",
            "expressions": "contextDataExpression(*)"
          }
        }
      ]
    (...)
    
    (...)
      "conditions": [
        {
          "type": "contextmatcher",
          "configs": {
            "contextType": "object",
            "contextKey": "userInfo",
            "objectKeyPath": "profile.username",
            "objectValue": "John"
          }
        }
      ]
    (...)
    
    (...)
      "conditions": [
        {
          "type": "contextmatcher",
          "configs": {
            "contextType": "string",
            "contextKey": "daytime",
            "string": "night"
          }
        }
      ]
    (...)
    (...)
      "conditions": [
        {
          "type": "connector",
          "configs": {
            "operator": "OR"
          },
          "conditions": [
            <any other conditions>
          ]
        }
      ]
    (...)
    Child 1 - true
    Child 2 - true
    → Negation = false
    Child 1 - false
    Child 2 - true
    → Negation = true
    
    (...)
      "conditions": [
        {
          "type": "negation",
          "conditions": [
            <any other conditions>
          ]
        }
      ]
    (...)
    (...)
    {
      "type": "occurrence",
      "configs": {
        "maxTimesOccurred": "0",
        "minTimesOccurred": "0",
        "behaviorRuleName": "Welcome"
      }
    }
    (...)
    (...)
    {
      "type": "dependency",
      "configs": {
        "reference": "<name-of-another-behavior-rule>"
      }
    }
    (...)
    (...)
    {
      "type": "actionmatcher",
      "configs": {
        "actions": "show_available_products",
        "occurrence": "lastStep"
      }
    }
    (...)
    (...)
      {
      "type": "dynamicvaluematcher",
      "configs": {
        "valuePath": "memory.current.httpCalls.someObj.errors",
        "contains": "partly matching",
        "equals": "needs to be equals"
      }
    }
    (...)
    {
      "behaviorGroups": [
        {
          "name": "Smalltalk",
          "behaviorRules": [
            {
              "name": "Welcome",
              "actions": [
                "welcome"
              ],
              "conditions": [
                {
                  "type": "negation",
                  "conditions": [
                    {
                      "type": "occurrence",
                      "configs": {
                        "maxTimesOccurred": "1",
                        "behaviorRuleName": "Welcome"
                      }
                    }
                  ]
                }
              ]
            },
            {
              "name": "Greeting",
              "actions": [
                "greet"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "greeting(*)",
                    "occurrence": "currentStep"
                  }
                }
              ]
            },
            {
              "name": "Goodbye",
              "actions": [
                "say_goodbye",
                "CONVERSATION_END"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "goodbye(*)"
                  }
                }
              ]
            },
            {
              "name": "Thank",
              "actions": [
                "thank"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "thank(*)"
                  }
                }
              ]
            },
            {
              "name": "how are you",
              "actions": [
                "how_are_you"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "how_are_you"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Thu, 21 Jun 2018 01:00:02 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.behavior/behaviorstore/behaviorsets/5b2af892ee5ee72440ee1b4b?version=1",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }

    expressions (if contextType=expressions)

    A list of comma separated expressions

    objectKeyPath (if contextType=object)

    objectValue

    Allows match via Jsonpath, such as "profile.username" (see: https://github.com/rest-assured/rest-assured/wiki/Usage)

    Exp: contextKey: userInfo , contextValue: {"profile":{"username":"John"}} The value to be match with the extracted JsonPath value

    string

    string matching (equals)

    /behaviorstore/behaviorsets/{id}

    BehaviorSet model

    N/A

    GET

    /behaviorstore/behaviorsets/descriptors

    N/A

    BehaviorSet model

    POST

    /behaviorstore/behaviorsets

    BehaviorSet model

    N/A

    GET

    /behaviorstore/behaviorsets/{id}/currentversion

    N/A

    BehaviorSet model

    POST

    /behaviorstore/behaviorsets/{id}/currentversion

    BehaviorSet model

    N/A

    Occurrence
    Dependency
    Action Matcher
    Dynamic Value Matcher
    Logo

    Create a bot that reacts to user inputs

    Prerequisites: Up and Running instance of EDDI (see: Getting started)

    Let's get started

    Follow these steps to create the configuration files you will need:

    1. Creating a Regular Dictionary inside Parser

    See also

    Create regular dictionaries in order to store custom words and phrases. A dictionary is there to map user input to expressions, which are later used in Behavior Rules. A POST to /regulardictionarystore/regulardictionaries with a JSON in the body like this:

    Example using CURL:

    Dictionary parameters

    The returned URI is a reference for this specific resource. This resource will be referenced in the bot definition.

    2. Creating Behavior Rules

    See also Behavior Rules

    Next, create a behaviorRule resource to configure the decision making a. Make a POST to /behaviorstore/behaviorsets with a JSON in the body like this:

    Behavior Rules parameters

    You should again get a return code of 201 with a URI in the location header referencing the newly created Behavior Rules:

    eddi://ai.labs.behavior/behaviorstore/behaviorsets/<UNIQUE_BEHAVIOR_ID>?version=<BEHAVIOR_VERSION>

    Example:

    eddi://ai.labs.behavior/behaviorstore/behaviorsets/5a26d8fd17312628b46119fb?version=1

    3. Creating Output

    You have guessed it correctly, another POST to /outputstore/outputsets creates the bot's Output with a JSON in the body like this:

    You should again get a return code of 201 with a URI in the location header referencing the newly created output :

    eddi://ai.labs.output/outputstore/outputsets/<UNIQUE_OUTPUTSET_ID>?version=<OUTPUTSET_VERSION>

    Example :

    eddi://ai.labs.output/outputstore/outputsets/5a26d97417312628b46119fc?version=1

    4. Creating the Package

    Now we will align the just created LifecycleTasks in the Package. Make a POST to /packagestore/packages with a JSON in the body like this:

    Package parameters

    Extension Types

    New

    Now you can use the new feature of defining properties in the package definition : This can be used by introducing an extension with type eddi://ai.labs.property which has the config model as follows:

    Description of eddi://ai.labs.property model

    Example of eddi://ai.labs.property

    You should again get a return code of 201 with an URI in the location header referencing the newly created package format

    eddi://ai.labs.package/packagestore/packages/<UNIQUE_PACKAGE_ID>?version=<PACKAGE_VERSION>

    Example

    eddi://ai.labs.package/packagestore/packages/5a2ae60f17312624f8b8a445?version=1

    See also the API documentation at

    5. Creating a Bot

    Make a POST to /botstore/bots with a JSON like this:

    Bot parameters

    b. You should again get a return code of 201 with a URI in the location header referencing the newly created bot :

    eddi://ai.labs.bot/botstore/bots/<UNIQUE_BOT_ID>?version=<BOT_VERSION>

    Example:

    eddi://ai.labs.bot/botstore/bots/5a2ae68a17312624f8b8a446?version=1

    See also the API documentation at

    6. Launching the Bot

    Finally, we are ready to let the bot fly. From here on, you have the possibility to let an UI do it for you or you do it step by step.

    The UI that automates these steps can be reached here: /chat/unrestricted/<UNIQUE_BOT_ID>

    Otherwise via REST:

    1. Deploy the Bot:

      Make a POST to /administration/unrestricted/deploy/<UNIQUE_BOT_ID>?version=<BOT_VERSION>

      You will receive a 202 http code.

    NOT_FOUND, IN_PROGRESS, ERROR and READY is what you can expect to be returned in the body.

    1. As soon as the Bot is deployed and has READY status, make a POST to /bots/unrestricted/<UNIQUE_BOT_ID>

      1. You will receive a 201 with the URI for the newly created Conversation, like this:

    Option 1: is to hand over the input text as contentType text/plain. Include the User Input in the body as text/plain (e.g. Hello)

    Option 2: is to hand over the input as contentType application/json, which also allows you to handover context information that you can use with the eddi configurations 1. Include the User Input in the body as application/json (e.g. Hello)

    1. You have two query params you can use to config the returned output 1. returnDetailed - default is false - will return all sub results of the entire conversation steps, otherwise only public ones such as input, action, output & quickreplies 2. returnCurrentStepOnly - default is true - will return only the latest conversation step that has just been processed, otherwise returns all conversation steps since the beginning of this conversation

    2. The output from the bot will be returned as JSON

    3. If you are interested in fetching the

    If you made it till here, CONGRATULATIONS, you have created your first Chatbot with EDDI !

    By the way you can use the attached postman collection below to do all of the steps mentioned above by clicking send on each request in postman.

    1. Create dictionary (greetings)

    2. Create behaviourSet

    3. Create outputSet

    4. Creating package

    External Links

    Word.frequency

    int, Used for a randomizer

    Phrase.phrase

    String, Spaces allowed

    True

    Phrase.expressions

    String, "greeting(hello)": "greeting" is the category of this expression and "hello" is an entity.

    String, allowed values:

    —>"inputmatcher" (has params: "expressions" (Array of String( and "occurrence")

    —>"negation" (BehaviorExtension object, has params: "conditions" and "occurrence")

    RuleChild.values

    HashMap, allowed values:

    —>"expressions": String, mandatory. Expression e.g. "greeting(*)" or "how_are_you"

    —>"occurrence": String, optional. Allowed values "currentStep"

    Negation.conditons

    Array of NegationChild

    NegationChild.type

    String e.g. "occurrence"

    NegationChild.values

    HashMap, allowed values:

    —>"maxTimesOccurred": String, e.g. 1

    —>"minTimesOccurred": String, e.g. 1

    —>"behaviorRuleName": String

    True

    Since deployment could take a while it has been made asynchronous.
  • Make a GET to /administration/unrestricted/deploymentstatus/<UNIQUE_BOT_ID>?version=<BOT_VERSION> to find out the status of deployment.

  • e.g.

    eddi://ai.labs.conversation/conversationstore/conversations/<UNIQUE_CONVERSATION_ID>

  • Now it's time to start talking to our Bot 1. Make a POST to /bots/unrestricted/<UNIQUE_BOT_ID>/<UNIQUE_CONVERSATION_ID>

  • conversationmemory
    at any given time, make a
    GET
    to
    /bots/unrestricted/
    <UNIQUE_BOT_ID>
    /
    <UNIQUE_CONVERSATION_ID>
    ?returnDetailed=true
    (the query param is optional, default is false)

    Creating bot

  • Deploy the bot

  • Create conversation

  • Say Hello to the bot

  • Name

    Description

    Required

    words

    Array of Word

    phrases

    Array of Phrase

    Word.word

    String, single word, no spaces.

    True

    Word.expressions

    Name

    Description

    BehaviorRule.name

    String, e.g. "Smalltalk"

    BehaviourGroup.behaviorRules

    Array of BehaviorRule

    BehaviorRule.name

    String, e.g. "Greeting"

    BehaviorRule.actions

    Array of String, e.g. "greet" or "CONVERSATION_END"

    BehaviorRule.conditions

    Array of RuleChild

    Name

    Description

    Required

    packageextensions

    Array of PackageExtension

    PackageExtension.type

    possible values, see table below "Extension Types"

    PackageExtension.extensions

    Array of Object

    False

    PackageExtension.config

    Extension

    Config

    eddi://ai.labs.parser

    Dictionaries and/or corrections

    Object "extensions" can contain "dictionaries" (Array of Dictionary) and/or "corrections" (Array of Correction)

    Object "Dictionary" has params "type" and "config" (optional)

    Dictionary.type can reference Regular-Dictionaries "eddi://ai.labs.parser.dictionaries.regular" (needs param "config.uri") or be one of the EDDI out of the box types:

    —>"eddi://ai.labs.parser.dictionaries.integer"

    —>"eddi://ai.labs.parser.dictionaries.decimal"

    —>"eddi://ai.labs.parser.dictionaries.punctuation"

    —>"eddi://ai.labs.parser.dictionaries.email"

    —>"eddi://ai.labs.parser.dictionaries.time"

    —>"eddi://ai.labs.parser.dictionaries.ordinalNumber"

    Object "Correction" has params "type" and "config" (optional)

    Correction.type can reference one of the EDDI out of the box types:

    —>"eddi://ai.labs.parser.corrections.stemming": Object "config" has params "language" (String e.g. "english") and "lookupIfKnown" (Boolean)

    —>"eddi://ai.labs.parser.corrections.levenshtein": Object "config" has param "distance" (Integer, e.g. 2)

    —>"eddi://ai.labs.parser.corrections.mergedTerms"

    eddi://ai.labs.behavior

    Object Config contains param uri with Link to a behavior set, e.g. eddi://ai.labs.behavior/behaviorstore/behaviorsets/5a26d8fd17312628b46119fb?version=1

    eddi://ai.labs.output

    Object Config contains param uri with Link to output set, e.g. eddi://ai.labs.output/outputstore/outputsets/5a26d97417312628b46119fc?version=1

    Name

    Description

    setOnActions.actions

    (string) defines which for which actions (triggered by BehaviorRules) these Properties should be set

    setOnActions.setProperties

    (Array <Property>: ) must respect the Propertymodel: name, fromObjectPath and scope.

    setOnActions.setProperties.name

    (string) name of the Property.

    setOnActions.setProperties.fromObjectPath

    (string) path to the json object.

    setOnActions.setProperties.scope

    (string) Possible values step, conversation and longTerm .

    Name

    Description

    packages

    Array of String, references to Packages

    channels

    Array of Channel,

    Channel.type

    String, e.g. "eddi://ai.labs.channel.facebook"

    Channel.config

    Config Object. For "Facebook" this object has the params "appSecret" (String), "verificationToken" (String), "pageAccessToken" (String)

    Semantic Parser
    See also Output Configuration.
    http://localhost:7070/view#!/configurations/createPackage
    http://localhost:7070/view#!/configurations/createBot
    21KB
    Creating and chatting with a bot.postman_collection.json
    Open
    Example to download
    Using collections in postman

    String, "greeting(hello)": "greeting" is the category of this expression and "hello" is an entity.

    RuleChild.type

    Config object, but can be empty.

    {
      "words": [
        {
          "word": "hello",
          "expressions": "greeting(hello)",
          "frequency": 0
        },
        {
          "word": "hi",
          "expressions": "greeting(hi)",
          "frequency": 0
        },
        {
          "word": "bye",
          "expressions": "goodbye(bye)",
          "frequency": 0
        },
        {
          "word": "thanks",
          "expressions": "thanks(thanks)",
          "frequency": 0
        }
      ],
      "phrases": [
        {
          "phrase": "good afternoon",
          "expressions": "greeting(good_afternoon)"
        },
        {
          "phrase": "how are you",
          "expressions": "how_are_you"
        }
      ]
    }
    curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \
    "language" : "en", \
    "words" : [ \
    { \
    "word" : "hello", \
    "expressions" : "greeting(hello)", \
    "frequency" : 0 \
    }, \
    { \
    "word" : "hi", \
    "expressions" : "greeting(hi)", \
    "frequency" : 0 \
    }, \
    { \
    "word" : "bye", \
    "expressions" : "goodbye(bye)", \
    "frequency" : 0 \
    }, \
    { \
    "word" : "thanks", \
    "expressions" : "thanks(thanks)", \
    "frequency" : 0 \
    } \
    ], \
    "phrases" : [ \
    { \
    "phrase" : "good afternoon", \
    "expressions" : "greeting(good_afternoon)" \
    }, \
    { \
    "phrase" : "how are you", \
    "expressions" : "how_are_you" \
    } \
    ] \
    }' 'http://localhost:7070/regulardictionarystore/regulardictionaries'
    {
      "behaviorGroups": [
        {
          "name": "Smalltalk",
          "behaviorRules": [
            {
              "name": "Welcome",
              "actions": [
                "welcome"
              ],
              "conditions": [
                {
                  "type": "occurrence",
                  "configs": {
                    "maxTimesOccurred": "0",
                    "behaviorRuleName": "Welcome"
                  }
                }
              ]
            },
            {
              "name": "Greeting",
              "actions": [
                "greet"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "greeting(*)",
                    "occurrence": "currentStep"
                  }
                }
              ]
            },
            {
              "name": "Goodbye",
              "actions": [
                "say_goodbye",
                "CONVERSATION_END"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "goodbye(*)"
                  }
                }
              ]
            },
            {
              "name": "Thank",
              "actions": [
                "thank"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "thank(*)"
                  }
                }
              ]
            },
            {
              "name": "how are you",
              "actions": [
                "how_are_you"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "how_are_you"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "outputSet": [
        {
          "action": "welcome",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Welcome!"
                }
              ]
            },
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "My name is E.D.D.I"
                }
              ]
            }
          ],
          "quickReplies": [
            {
              "value": "Hi EDDI",
              "expressions": "greeting(hi)"
            },
            {
              "value": "Bye EDDI",
              "expressions": "goodbye(bye)"
            }
          ]
        },
        {
          "action": "greet",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Hi there! Nice to meet up! :-)"
                },
                {
                  "type": "text",
                  "text": "Hey you!"
                }
              ]
            }
          ]
        },
        {
          "action": "greet",
          "timesOccurred": 1,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Did we already say hi ?! Well, twice is better than not at all! ;-)"
                }
              ]
            }
          ]
        },
        {
          "action": "say_goodbye",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "See you soon!"
                }
              ]
            }
          ]
        },
        {
          "action": "thank",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Your Welcome!"
                }
              ]
            }
          ]
        },
        {
          "action": "how_are_you",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Pretty good.. having lovely conversations all day long.. :-D"
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "packageExtensions": [
        {
          "type": "eddi://ai.labs.parser",
          "extensions": {
            "dictionaries": [
              {
                "type": "eddi://ai.labs.parser.dictionaries.integer"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.decimal"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.punctuation"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.email"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.time"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.ordinalNumber"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.regular",
                "config": {
                  "uri": "eddi://ai.labs.regulardictionary/regulardictionarystore/regulardictionaries/<UNIQUE_DICTIONARY_ID>?version=<DICTIONARY_VERSION>"
                }
              }
            ],
            "corrections": [
              {
                "type": "eddi://ai.labs.parser.corrections.stemming",
                "config": {
                  "language": "english",
                  "lookupIfKnown": "false"
                }
              },
              {
                "type": "eddi://ai.labs.parser.corrections.levenshtein",
                "config": {
                  "distance": "2"
                }
              },
              {
                "type": "eddi://ai.labs.parser.corrections.mergedTerms"
              }
            ]
          },
          "config": {}
        },
        {
          "type": "eddi://ai.labs.behavior",
          "config": {
            "uri": "eddi://ai.labs.behavior/behaviorstore/behaviorsets/<UNIQUE_BEHAVIOR_ID>?version=<BEHAVIOR_VERSION>"
          }
        },
        {
          "type": "eddi://ai.labs.output",
          "config": {
            "uri": "eddi://ai.labs.output/outputstore/outputsets/<UNIQUE_OUTPUTSET_ID>?version=<OUTPUTSET_VERSION>"
          }
        }
      ]
    }
    {
      "type": "eddi://ai.labs.property",
      "config": {
        "setOnActions": [
          {
            "actions": "string",
            "setProperties": [
              {
                "name": "string",
                "fromObjectPath": "string",
                "scope": "string"
              }
            ]
          }
        ]
      }
    }
    {
      "packageExtensions": [
       ...
        {
          "type": "eddi://ai.labs.property",
          "config": {
            "setOnActions": [
              {
                "actions": "currentWeather",
                "setProperties": [
                  {
                    "name": "city",
                    "fromObjectPath": "memory.current.input",
                    "scope": "longTerm"
                  }
                ]
              }
            ]
          }
        },
       ...
        {
          "type": "eddi://ai.labs.property",
          "config": {
            "setOnActions": [
              {
                "actions": "currentWeather",
                "setProperties": [
                  {
                    "name": "currentWeather",
                    "fromObjectPath": "memory.current.httpCalls.currentWeather",
                    "scope": "conversation"
                  }
                ]
              }
            ]
          }
        },
       ...
      ]
    }
    {
    "packages": [
    "eddi://ai.labs.package/packagestore/packages/<UNIQUE_PACKAGE_ID>?version=<PACKAGE_VERSION>"
    ],
    "channels": []
    }
    {
         "input": "some user input"
    }

    HttpCalls

    HttpCalls

    In this article we will talk about EDDI's httpCalls feature (calling other JSON APIs).

    The httpCalls feature allows a Chatbot to consume 3rd party APIs and use the JSON response in another httpCall (for authentication or requesting a token for instance) or directly print the results in Chatbot's Output, this means, for example, you can call a weather API and use the JSON response in your Chatbot's output if the user asks about today's weather or the week's forecast!

    We will emphasize the httpCall model and go through an example step by step, you can also download the example in Postman collection format and run the steps.

    Model and API endpoint

    Description

    An httpCall is mainly composed from the targetServer array of httpCalls, the latter will have request where you put all details about your actual http request (method,path,headers, etc..) and postResponse where you can define what happens after the httpCall has been executed and a response has been received; such as quick replies by using qrBuildInstruction.

    You can use ${memory.current.httpCalls.<responseObjectName>} to access your JSON object, so you can use it in output templating or in another httpCall, for example an httpCall will get the oAuth token and another httpCall will use in the http headers to authenticate to an API.

    Description of the model

    HttpCall API endpoints

    httpCall Sample

    Step by step example

    We will do a step by step example from scratch (Chatbot creation to a simple conversation that uses httpCall)

    For the sake of simplicity we will use a free weather API to fetch weather of cities by their names ().

    1 - Create regularDictionnary

    More about regular dictionaries can be found .

    Request URL

    POST http://localhost:7070/regulardictionarystore/regulardictionaries

    Request Body

    Response Body

    no content

    Response Code

    201

    Response Headers

    2 - Create the behaviorSet

    More about behaviorSets can be found in

    Request URL

    POST http://localhost:7070/behaviorstore/behaviorsets

    Response Body

    no content

    Response Code

    201

    Request Body

    Response Headers

    3 - Create the httpCall

    Note that we can pass user input to the http call using [[${memory.current.input}]]

    Request URL

    POST http://localhost:7070/httpcallsstore/httpcalls

    Request Body

    Response Body

    no content

    Response Code

    201

    Response Headers

    4 - Create the outputSet

    More about outputSet can be found .

    Note When you set "saveResponse" : true in httpCall then you can use [[${memory.current.httpCalls.<responseObjectName>}]] to access the response data and use thymeleaf( th:each ) to iterate over JSON arrays if you have them in your JSON response.

    Request URL

    POST http://localhost:7070/outputstore/outputsets

    Request Body

    Response Body

    no content

    Response Code

    201

    Response Headers

    5 - Creating the package

    More about packages can be found .

    Important Package note

    • ai.labs.httpcalls & ai.labs.output must come after ai.labs.behavior in order of the package definition

    • ai.labs.templating

    Request URL

    POST http://localhost:7070/packagestore/packages

    Request Body

    Response Body

    no content

    Response Code

    201

    Response Headers

    6 - Creating the bot

    Request URL

    POST http://localhost:7070/botstore/bots

    Request Body

    Response Body

    no content

    Response Code

    201

    Response Headers

    7 - Deploy the bot

    Request URL

    POST http://localhost:7070/administration/restricted/deploy/**<bot_id>**?version=1&autoDeploy=true

    Response Body

    no content

    Response Code

    202

    Response Headers

    8 - Create the conversation

    Request URL

    POST http://localhost:7070/bots/**<env>**/**<bot_id>**

    Response Body

    no content

    Response Code

    201

    Response Headers

    9 - Say weather

    Request URL

    POST http://localhost:7070/bots/<env>/<bot_id>/<conversation_id>?returnDetailed=false&returnCurrentStepOnly=true

    Request Body

    Response Body

    Response Code

    200

    Response Headers

    10 - Say "Vienna"

    Request URL

    POST http://localhost:7070/bots/<env>/<bot_id>/<conversation_id>?returnDetailed=false&returnCurrentStepOnly=true

    Request Body

    Response Code

    200

    Response Headers

    Full example

    If you would like to run the full example through postman, you can download and import the collection below.

    (String) JSON path to the target array to be used as body of requests e.g: "memory.current.output"

    httpCall.preRequest.batchRequests.iterationObjectName

    (String) name of the variable to be used for each element of array found in pathToTargetArray

    httpCall.request.path

    (String) path in the targetServer of the httpCall (e.g /books)

    httpCall.request.headers

    (Array:<key, value> ) for each httpCall HTTP header

    httpCall.request.queryParams

    (Array: <key, value>) for each httpCall query parameter

    httpCall.request.method

    (String) HTTP Method of the httpCall (e.g GET,POST,etc...)

    httpCall.request.contentType

    (String) value of the contentType HTTP header of the httpCall

    httpCall.request.body

    (String) an escaped JSON object that goes in the HTTP Request body if needed.

    httpCall.postResponse.qrBuildInstruction.pathToTargetArray

    (String) path to the array in your JSON response data.

    httpCall.postResponse.qrBuildInstruction.iterationObjectName

    (String) a variable name that will point to the TargetArray.

    httpCall.postResponse.qrBuildInstruction.quickReplyValue

    (String) thymeleaf expression to use as a quickReply value.

    httpCall.postResponse.qrBuildInstruction.quickReplyExpressions

    (String) expression to retrieve a property from iterationObjectName.

    httpCall.postResponse.propertyInstructions.name

    (String) name of property to be used in templating

    httpCall.postResponse.propertyInstructions.value

    (String) a static value can be set here if fromObjectPath is not defined.

    httpCall.postResponse.propertyInstructions.scope

    (String) Can be either :

    step used for only for one user interaction

    conversation for entire conversation and

    longTerm for between conversations

    httpCall.postResponse.propertyInstructions.fromObjectPath

    (String) JSON path to the saved object e.g savedObjName.something.something

    httpCall.postResponse.propertyInstructions.override

    (Boolean) flag for override

    httpCall.postResponse.propertyInstructions.httpCodeValidator.runOnHttpCode

    (Array: <Integer> ) a list of http code that enables this property instruction e.g [200]

    httpCall.postResponse.propertyInstructions.httpCodeValidator.skipOnHttpCode

    (Array: <Integer>) list of http code that enables this property instruction e.g [500,501,400]

    N/A

    N/A

    GET

    /httpcallsstore/httpcalls/{id}

    N/A

    http-call-model

    PUT

    /httpcallsstore/httpcalls/{id}

    http-call-model

    N/A

    GET

    /httpcallsstore/httpcalls/{id}/currentversion

    N/A

    http-call-model

    POST

    /httpcallsstore/httpcalls/{id}/currentversion

    http-call-model

    N/A

    has to be after
    ai.labs.output

    Element

    Description

    targetServerUrl

    (String) root/context path of the httpCall (e.g http://example.com/api)

    httpCall.saveResponse

    (Boolean) whether to save the JSON response into ${memory.current.httpCalls}

    httpCall.fireAndForget

    (Boolean) whether to execute the request without waiting for a response to be returned, (useful for POST)

    httpCall.responseObjectName

    (String) name of the JSON object so it can be accessed from other httpCalls or outputsets.

    httpCall.actions

    (String) name of the output/behavior set mapped to this http call.

    HTTP Method

    API Endpoint

    Request Body

    Response

    POST

    /httpcallsstore/httpcalls

    http-call-model

    N/A

    GET

    /httpcallsstore/httpcalls/descriptors

    N/A

    list of references to http-call-model

    DELETE

    api.openweathermap.org
    here
    Behavior Rules
    Output Configuration
    here
    21KB
    EDDI - Weather bot.postman_collection.json
    Open
    EDDI - Weather bot.postman_collection.json

    httpCall.preRequest.batchRequests.pathToTargetArray

    /httpcallsstore/httpcalls/{id}

    {
      "targetServerUrl": "string",
      "httpCalls": [
        {
          "name": "string",
          "saveResponse": boolean,
          "fireAndForget": boolean,
          "responseObjectName": "string",
          "actions": [
            "string"
          ],
          "preRequest": {
            "batchRequests": {
              "pathToTargetArray": "string",
              "iterationObjectName": "string"
            }
          },
          "request": {
            "path": "string",
            "headers": {},
            "queryParams": {},
            "method": "string",
            "contentType": "string",
            "body": "string"
          },
          "postResponse": {
            "qrBuildInstruction": {
              "pathToTargetArray": "String",
              "iterationObjectName": "String",
              "quickReplyValue": "String",
              "quickReplyExpressions": "String"
            },
            "propertyInstructions": [
              {
                "name": "string",
                "value": "string",
                "scope": "string",
                "fromObjectPath": "savedObjName.something.something",
                "override": boolean,
                "httpCodeValidator": {
                  "runOnHttpCode": [
                    <array of Integers>
                  ],
                  "skipOnHttpCode": [
                    <array of Integers>
                  ]
                }
              }
            ]
          }
        }
      ]
    }
    {
      "targetServerUrl": "https://api.bot-metrics.com/v1/messages",
      "httpCalls": [
        {
          "name": "sendUserMessageToAnalytics",
          "actions": [
            "send_input_to_analytics"
          ],
          "saveResponse": false,
          "fireAndForget": true,
          "request": {
            "method": "post",
            "queryParams": {
              "token": "<token>"
            },
            "contentType": "application/json",
            "body": "{\"text\": \"[[${memory.current.input}]]\",\"message_type\": \"incoming\",\"user_id\": \"[[${memory.current.userInfo.userId}]]\",\"platform\": \"eddi\"}"
          }
        },
        {
          "name": "sendBotMessageToAnalytics",
          "actions": [
            "send_output_to_analytics"
          ],
          "saveResponse": false,
          "fireAndForget": true,
          "preRequest": {
            "batchRequests": {
              "pathToTargetArray": "memory.current.output",
              "iterationObjectName": "output"
            }
          },
          "request": {
            "method": "post",
            "queryParams": {
              "token": "<token>"
            },
            "contentType": "application/json",
            "body": "{\"text\": \"[[${output}]]\",\"message_type\": \"outgoing\",\"user_id\": \"[[${memory.current.userInfo.userId}]]\",\"platform\": \"eddi\"}"
          },
          "postResponse": {
            "propertyInstructions": [
              {
                "name": "nameOfPropertyToBeUsedInTemplating",
                "value": "StaticValueHereIfFromObjectPathIsNotDefined",
                "scope": "step",
                "fromObjectPath": "savedObjName.something.something",
                "override": true,
                "httpCodeValidator": {
                  "runOnHttpCode": [
                    200
                  ],
                  "skipOnHttpCode": [
                    0,
                    400,
                    401,
                    402,
                    403,
                    404,
                    409,
                    410,
                    500,
                    501,
                    502
                  ]
                },
                "qrBuildInstruction": {
                  "pathToTargetArray": "savedObjName.data.topics",
                  "iterationObjectName": "topic",
                  "templateFilterExpression": "${topic.subType} != 'specialSubType'",
                  "quickReplyValue": "[(${topic.name})]",
                  "quickReplyExpressions": "property(topic_id([(${topic.id})]))"
                }
              }
            ]
          }
        }
      ]
    }
    {
      "words": [
        {
          "word": "weather",
          "expressions": "trigger(current_weather)",
          "frequency": 0
        }
      ],
      "phrases": [
        {
          "phrase": "what is the weather",
          "expressions": "trigger(current_weather)"
        },
        {
          "phrase": "whats the weather",
          "expressions": "trigger(current_weather)"
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 16:40:58 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.regulardictionary/regulardictionarystore/regulardictionaries/5af86a9aba31c023bcb9ef2b?version=1",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "behaviorGroups": [
        {
          "name": "",
          "behaviorRules": [
            {
              "name": "Ask for City",
              "actions": [
                "ask_for_city"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "trigger(current_weather)"
                  }
                }
              ]
            },
            {
              "name": "Current Weather in City",
              "actions": [
                "current_weather_in_city"
              ],
              "conditions": [
                {
                  "type": "inputmatcher",
                  "configs": {
                    "expressions": "trigger(current_weather)",
                    "occurrence": "lastStep"
                  }
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 16:45:52 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.behavior/behaviorstore/behaviorsets/5af86bc0ba31c023bcb9ef2c?version=1",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "targetServerUrl": "https://api.openweathermap.org/data/2.5/weather",
      "httpCalls": [
        {
          "name": "currentWeather",
          "saveResponse": true,
          "responseObjectName": "currentWeather",
          "actions": [
            "current_weather_in_city"
          ],
          "request": {
            "path": "",
            "headers": {},
            "queryParams": {
              "APPID": "c3366d78c7c0f76d63eb4cdf1384ddbf",
              "units": "metric",
              "q": "[[${memory.current.input}]]"
            },
            "method": "get",
            "contentType": "",
            "body": ""
          }
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 19:13:52 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.httpcalls/httpcallsstore/httpcalls/5af88e70ba31c023bcb9ef2e?version=1",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "outputSet": [
        {
          "action": "ask_for_city",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "Which City would you like to know the weather of?"
                }
              ]
            }
          ]
        },
        {
          "action": "current_weather_in_city",
          "timesOccurred": 0,
          "outputs": [
            {
              "valueAlternatives": [
                {
                  "type": "text",
                  "text": "The current weather situation of [[${memory.current.input}]] is [[${memory.current.httpCalls.currentWeather.weather[0].description}]] at [[${memory.current.httpCalls.currentWeather.main.temp}]] °C"
                }
              ]
            }
          ]
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 16:48:37 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.output/outputstore/outputsets/5af86c65ba31c023bcb9ef2d?version=1",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "packageExtensions": [
        {
          "type": "eddi://ai.labs.parser",
          "extensions": {
            "dictionaries": [
              {
                "type": "eddi://ai.labs.parser.dictionaries.integer"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.decimal"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.punctuation"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.email"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.time"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.ordinalNumber"
              },
              {
                "type": "eddi://ai.labs.parser.dictionaries.regular",
                "config": {
                  "uri": "eddi://ai.labs.regulardictionary/regulardictionarystore/regulardictionaries/{{dictionary_id}}?version=1"
                }
              }
            ],
            "corrections": [
              {
                "type": "eddi://ai.labs.parser.corrections.stemming",
                "config": {
                  "language": "english",
                  "lookupIfKnown": "false"
                }
              },
              {
                "type": "eddi://ai.labs.parser.corrections.levenshtein",
                "config": {
                  "distance": "2"
                }
              },
              {
                "type": "eddi://ai.labs.parser.corrections.mergedTerms"
              }
            ]
          },
          "config": {}
        },
        {
          "type": "eddi://ai.labs.behavior",
          "config": {
            "uri": "eddi://ai.labs.behavior/behaviorstore/behaviorsets/{{behaviourset_id}}?version=1"
          }
        },
        {
          "type": "eddi://ai.labs.httpcalls",
          "config": {
            "uri": "eddi://ai.labs.httpcalls/httpcallsstore/httpcalls/{{httpcall_id}}?version=1"
          }
        },
        {
          "type": "eddi://ai.labs.output",
          "config": {
            "uri": "eddi://ai.labs.output/outputstore/outputsets/{{outputset_id}}?version=1"
          }
        },
        {
          "type": "eddi://ai.labs.templating",
          "extensions": {},
          "config": {}
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 19:26:36 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.package/packagestore/packages/5af8916cba31c023bcb9ef2f?version=1",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "packages": [
        "eddi://ai.labs.package/packagestore/packages/{{package_id}}?version=1"
      ],
      "channels": []
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 21:18:16 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.bot/botstore/bots/5af8ab98ba31c023bcb9ef32?version=1",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 21:21:54 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 21:30:45 GMT",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "0",
      "location": "eddi://ai.labs.conversation/conversationstore/conversations/5af8ae85ba31c023bcb9ef35",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location",
      "content-type": null
    }
    {
      "input": "weather"
    }
    {
      "botId": "5af8b075ba31c023bcb9ef3b",
      "botVersion": 1,
      "environment": "unrestricted",
      "conversationState": "READY",
      "redoCacheSize": 0,
      "conversationSteps": [
        {
          "conversationStep": [
            {
              "key": "input:initial",
              "value": "weather"
            },
            {
              "key": "actions",
              "value": [
                "ask_for_city"
              ]
            },
            {
              "key": "output:text:ask_for_city",
              "value": "Which City would you like to know the weather of?"
            }
          ],
          "timestamp": 1526247548410
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 21:35:15 GMT",
      "content-type": "application/json;resteasy-server-has-produces=true",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "325",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location"
    }
    {
      "botId": "5af8b075ba31c023bcb9ef3b",
      "botVersion": 1,
      "environment": "unrestricted",
      "conversationState": "READY",
      "redoCacheSize": 0,
      "conversationSteps": [
        {
          "conversationStep": [
            {
              "key": "input:initial",
              "value": "Vienna"
            },
            {
              "key": "actions",
              "value": [
                "current_weather_in_city"
              ]
            },
            {
              "key": "output:text:current_weather_in_city",
              "value": "The current weather situation of Vienna is clear sky at 17.68 °C"
            }
          ],
          "timestamp": 1526247618080
        }
      ]
    }
    {
      "access-control-allow-origin": "*",
      "date": "Sun, 13 May 2018 21:35:15 GMT",
      "content-type": "application/json;resteasy-server-has-produces=true",
      "access-control-allow-headers": "authorization, Content-Type",
      "content-length": "325",
      "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
      "access-control-expose-headers": "location"
    }