Giter VIP home page Giter VIP logo

resm's Introduction

RESM

RESM which stands for RESponse Manager is an SDK for handling response generation in a dialogue system. It can for example be used to build NLG servers for Rasa to separate the response generation from the dialogue control.

It is a personal project in early development that has been motivated by my previous nlg-server implementation in Java to replicate it in Go to deepen my understanding of Go and potentially to add more features to RESM compared to the Java version. The Java version I maintain can be found here NLG-Server

Use Case

When you have a dialogue system in which you want to separate the actual response generation from the dialogue control you can achieve this with RESM.

E.g. when you are using Rasa and you do not want to deploy a new model for just simple changes to the response text.

RESM is written in Go and is therefore lightweight and fast.

Get RESM

go get github.com/Kai-Karren/resm

Run

go run .

Tests

To run the test cases recursively to run the tests in the submodules run

go test -v ./...

As a reminder, test files have to end with _test in Go.

Simple API

RESM's most simple API that provided basic features.

API Request

{
    "response": "utter_example",
    "slots": {
        "name": "John Doe",
        "turns": "4"
    }
}
curl http://localhost:8080/nlg -X POST -d '{
    "response": "utter_example",
    "slots": {
        "name": "John Doe",
        "turns": "4"
    }
}'

API Response

{
    "response": "utter_example",
    "text": "This is an example response from RESM"
}

Rasa Compatible API

The Rasa API implementation can act as NLG server following Rasa NLG Has been last tested with Rasa 3.2.1

Rasa API Request

The request for the Rasa API has to look as follows: For more details please see Rasa NLG

{
"response":"utter_example",
  "arguments":{
    
  },
  "tracker":{
    "sender_id":"user_0",
    "slots":{
      "number": "42"
    },
    "latest_message":{
      "intent":{
        "id":3014457480322877053,
        "name":"greet",
        "confidence":0.9999994039535522
      },
      "entities":[
        
      ],
      "text":"Hello",
      "message_id":"94838d6f49ff4366b254b6f6d23a90cf",
      "metadata":{
        
      },
      "intent_ranking":[
        {
          "id":3014457480322877053,
          "name":"greet",
          "confidence":0.9999994039535522
        }
      ]
    },
    "latest_event_time":1599476297.694504,
    "followup_action":null,
    "paused":false,
    "events":[
      {
        "event":"action",
        "timestamp":1599476297.68784,
        "name":"action_session_start",
        "policy":null,
        "confidence":null
      },
      {
        "event":"session_started",
        "timestamp":1599476297.6878452
      }
    ],
    "latest_input_channel":"rest",
    "active_loop":{
      
    },
    "latest_action_name":"action_listen"
  },
  "channel":{
    "name":"collector"
  }
}

Rasa API Response

{
    "text": "This is an example response from RESM."
}

Examples

Examples and experiments with RESM can be found in this repo

Response Generators

The Rasa-compatible API provides different so-called Response Generators that handle the response generation of RESM.

Static Response Generator

The StaticResponseGenerator is the primary used Response Generator that allows you to specify a mapping between a response name and one response text or a set of response variations. Slot values can be injected in the text responses with $slotName or with {slotName}.

Static Response Generator with Memory (Experimental)

Implementation of a Response Generator that focuses on the better handling of response variations by ensuring that all variations of a response are returned to a user before a variation is returned twice. RESM only includes an inmemory implementation of the ResponseMemory as of now.

Custom Response Generator

If you want to handle responses by executing custom Go code, you can use the CustomResponseGenerator which allows you to pass a mapping between response name and a function that should be run to generate the response. This allows dyamic response generation at runtime with almost unlimited possibilities.

generator := NewCustomResponseGenerator()

exampleHandler := func(request NlgRequest) (NlgResponse, error) {
  return NewNlgResponse("This is a custom response."), nil
}

generator.AddHandler("test", exampleHandler)

Distributed Response Generator

If you want to combine e.g. the Static and the Custom Response Generators in one API, you can do this with the DistributedResponseGenerator. It handles the routing of the requests to the corresponding generator. If you are using your own Response Generator implementation please make sure to correctly implement the HandlesResponse method. Currently, the DistributedResponseGenerator queries the generators in the order that have been added each time a request is handled. This may change in the future with alternative routing strategies or other alternative implementations.

Your Response Generator

Of course, it is also possible to create your own Response Generator by implementing the Response Generator interface!

resm's People

Contributors

kai-karren avatar

Watchers

 avatar

resm's Issues

Request Authentification

The REST APIs over GIN are currently not secured, I should look into how this could be done and with which options. This will likely not be included in this repo though.

Implement Slot filing into the responses

RESM does not support filling to slot values into responses yet.

This should work in the same way as I implemented it in Kai-Karren/nlg-server#3

"I understood that you said $number"  with slot number = 42 => "I understood that you said 42"
"I understood that you are {name}" with slot name = "Kai Karren" => "I understood that you are Kai Karren"

Support for Response variations

Currently, it is only possible to have a 1-to-1 mapping between a response name and the text for this response. To support CUI design best practices 1 to n mappings should also be supported.

Support for multiple projects in one instance?

Should one RESM instance be used per project or should it be possible to manage different projects with one RESM instance?

For now, I do not see the need to manage the responses of different CUIs in something like a project structure. It would also add potential other ideas like role-based access which would add unnecessary complexity at the moment.

Also, RESM could already be used by different bots by adding the needed responses.

Read all response JSON files in a given directory

Currently, there is only a utility method to read a certain JSON file and load its content. To have a way to specify a directory and to get all response JSON files loaded recursively would be a welcome addition I think.

Should there be more logging?

Currently, RESM does not log much information. The logging also uses the built-in way using fmt. So the improvement potential could be checked and if zap should be used.

Restructuring with a Generator Package and an own rasa package?

Should a new package be created for the Response Generators?

Should Rasa get its own package rasa instead of being part of the API?

I think it could also make sense to use the RasaNlgRequest as the request for all response Generators because the simplified API does not include enough information that could be used for custom response generation aside from the slots.

At a later point, the RasaNlgRequest could be extended with optional parameters if needed.

Combine static and custom response generation

It would be nice if you could combine static responses and the generation of responses with one or multiple custom response generators.

For this to work, there would have to be some decision making which response should be handled by which response generator.
This could be done by letting the generators register the responses they can handle to build a mapping for the corresponding routing.

There should also be a response generator defined for unexpected response names or an error should be thrown.

Option to limit the random response variations to unseen ones

Currently, the response variations are selected completely random without keeping track if these response variations were already returned to the conversation before, depending on the use case this is not the desired behavior. It should be optionally possible to request random unseen response variations until there are no further unseen ones and the condition resets.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.