2. Pre- and postprocessors#
The following tutorial shows more advanced usage of pipeline
module as an extension to chatsky.script.core
.
Here, misc dictionary of context is used for storing additional data.
[1]:
# installing dependencies
%pip install -q chatsky
Note: you may need to restart the kernel to use updated packages.
[2]:
import logging
from chatsky.messengers.console import CLIMessengerInterface
from chatsky import Context, Message, Pipeline
from chatsky.utils.testing import (
check_happy_path,
is_interactive_mode,
HAPPY_PATH,
TOY_SCRIPT_KWARGS,
)
logger = logging.getLogger(__name__)
When Pipeline is created, additional pre- and post-services can be defined. These can be any callables, certain objects or dicts. They are being turned into special Service
or ServiceGroup
objects (see tutorial 3), that will be run before or after Actor
respectively. These services can be used to access external APIs, annotate user input, etc.
Service callable signature can be one of the following: [ctx]
, [ctx, pipeline]
or [ctx, actor, info]
(see tutorial 3), where:
ctx
- Context of the current dialog.pipeline
- The current pipeline.info
- dictionary, containing information about current service and pipeline execution state (see tutorial 4).
Here a preprocessor (“ping”) and a postprocessor (“pong”) are added to pipeline. They share data in context.misc
- a common place for sharing data between services and actor.
[3]:
def ping_processor(ctx: Context):
ctx.misc["ping"] = True
def pong_processor(ctx: Context):
ping = ctx.misc.get("ping", False)
ctx.misc["pong"] = ping
[4]:
pipeline = Pipeline(
**TOY_SCRIPT_KWARGS,
context_storage={}, # `context_storage` - a dictionary or
# a `DBContextStorage` instance,
# a place to store dialog contexts
messenger_interface=CLIMessengerInterface(),
# `messenger_interface` - a message channel adapter,
# it's not used in this tutorial
pre_services=[ping_processor],
post_services=[pong_processor],
)
if __name__ == "__main__":
check_happy_path(pipeline, HAPPY_PATH, printout=True)
if is_interactive_mode():
ctx_id = 0 # 0 will be current dialog (context) identification.
while True:
message = Message(input("Send request: "))
ctx: Context = pipeline(message, ctx_id)
print(f"Response: {ctx.last_response}")
ping_pong = ctx.misc.get("ping", False) and ctx.misc.get(
"pong", False
)
print(
f"Ping-pong exchange: {'completed' if ping_pong else 'failed'}."
)
logger.info(f"Context misc: {ctx.misc}")
USER: text='Hi'
BOT : text='Hi, how are you?'
USER: text='i'm fine, how are you?'
BOT : text='Good. What do you want to talk about?'
USER: text='Let's talk about music.'
BOT : text='Sorry, I can not talk about music now.'
USER: text='Ok, goodbye.'
BOT : text='bye'
USER: text='Hi'
BOT : text='Hi, how are you?'