Eliza Example¶
This tutorial is to help one to understand how visualization work together with the pipeline. We will walk you through the steps to set up an Eliza chatbot which generates responses based on Eliza rules. We will utilize stave
to visualize the dialogue page that allows you to chat with the bot interactively.
Introduction¶
Eliza chatbot (https://en.wikipedia.org/wiki/ELIZA) is a famous rule-based chatbot invented in 1964 . The rule-based and model-less nature makes it extremely suitable for demonstration purposes. This tutorial is based on ElizaProcessor
. For more details, refer to https://github.com/asyml/forte/blob/master/forte/processors/nlp/eliza_processor.py.
Quick Start¶
Install Dependencies¶
[ ]:
!pip install torch
!pip install "forte[remote]@git+https://github.com/asyml/forte.git@master"
!pip install stave==0.0.2.dev1
Start a Eliza pipeline service¶
Run the following python script to start a pipeline service to process input queries based on Eliza rules.
[ ]:
from threading import Thread
from forte.pipeline import Pipeline
from forte.data.data_pack import DataPack
from forte.data.readers import RawDataDeserializeReader
from forte.processors.nlp import ElizaProcessor
def start_eliza_service(
input_format: str = "DataPack", service_name: str = "test_name"
) -> None:
"""
Start a remote service for ElizaProcessor
"""
pipeline = Pipeline[DataPack]()
pipeline.set_reader(RawDataDeserializeReader())
pipeline.add(ElizaProcessor())
pipeline.serve(input_format=input_format, service_name=service_name)
if __name__ == "__main__":
Thread(target=start_eliza_service).start()
Visualize the chatbot in stave
¶
We will need stave
to open a chatbot window for us to test the pipeline service that we just started in the previous step. stave
is a fast, lightweight, extensible web-based text annotation and visualization tool designed to support a wide range of data types and NLP tasks. For more details, refer to https://github.com/asyml/stave.
Run the following command:
[ ]:
!stave -s start -o -l -n 8889
Now we should see a browser window popped out which directs to a login page (http://localhost:8889/login) of stave
. You can log in with default username (admin
) and password (admin
).
After successfully logging into stave
, we can navigate to the All Projects
page. Click the VIEW PROJECT
button under Eliza
project. Then click eliza.json
on the left side to enter the dialogue page where you can enter queries and get responses from Eliza chatbot.
Code Explained¶
Overview¶
The Eliza example showcases forte
’s ability to expose a pipeline to be served as a remote service that can be called from another pipeline using RemoteProcessor. This allows users to port their local pipeline to a remote endpoint that can be accessed and shared by other users to call its functionality. We will use the Eliza example to show how we can achieve this.
Start a Pipeline Service¶
In the code snippet above we build a simple pipeline and start it as a service for Eliza chatbot:
pipeline = Pipeline[DataPack]()
pipeline.set_reader(RawDataDeserializeReader())
pipeline.add(ElizaProcessor())
pipeline.serve()
Here we set RawDataDeserializeReader as a reader of the pipeline since we expect the input request will be a sequence of serialized DataPack
strings. This reader is able to deserialize these strings to DataPack
s.
ElizaProcessor is responsible for generating responses based on Eliza rules from the input queries. The responses will be appended to the text payload of input DataPack
annotated as Utterance
.
Pipeline.serve(host, port) will start a pipeline service at a specific endpoint. You may configure host
and port
to specify the endpoint.
Call a Pipeline Service¶
After setting up the service, you will be able to access it from http://{host}:{port}
. You can also call it from another forte pipeline with RemoteProcessor. In the pre-loaded Eliza
project, stave
has already set up a forte pipeline to invoke the Eliza service:
# Adapted from https://github.com/asyml/stave/blob/master/simple-backend/stave_backend/handlers/nlp.py#L49
pipeline = Pipeline[DataPack](do_init_type_check)
pipeline.set_reader(RawDataDeserializeReader())
pipeline.add(RemoteProcessor(), config)
pipeline.initialize()
RawDataDeserializeReader is set as the reader of this pipeline because stave
stores DataPack
s as serialized strings in database. Input queries entered by users are integrated into an existing chatbot DataPack
and saved to database, which will be fed into the pipeline above.
RemoteProcessor provides a wrapping of interactions with remote forte service endpoint. Each input DataPack from the upstream component will be serialized and packed into a POST request to be sent to a remote service, which should return a response that can be parsed into a DataPack to update the input. In the Eliza example, it will prepare a POST request from the deserialized DataPack
(which contains
the user inputs), and send it to the remote service we just set up, and then parse the response (which contains the generated text from ElizaProcessor
) into a new DataPack
that can be passed to the downstream components.
Create Your Own Chatbot Service¶
You might notice that the pipeline of Eliza
project in stave
actually doesn’t constrain the remote service to be a Eliza
chatbot. It should be able to support any types of chatbot service as long as the service can process input DataPack
s in a way that stave
can understand.
To render a chatbot page, stave
will retrieve the Utterance annotations stored in DataPack
and lay out the dialogues based on Utterance.speaker. If speaker
of an Utterance
is "ai"
(e.g., the initial prompt message and chatbot responses), then its message will be placed at the left side of the page. For messages that are
entered by users, stave
will append them to DataPack
as new Utterance
annotations with their speaker
field set to "user"
and place them to the right side of chatbot window.
The chatbot service must conform to the protocol described above in order to correctly display its response in stave
. This service will receive a serialized DataPack
, hence it always needs to set RawDataDeserializeReader
as the reader. The downstream processor should retrieve the Utterance
annotations from it. The processor can choose to analyze the whole chat history or generate response simply based on the latest query from user. It must append its responses to DataPack
and
annotate them as Utterance
s whose speaker
should be set to "ai"
.