Skip to content

Commit

Permalink
Update API (#253)
Browse files Browse the repository at this point in the history
* Move updates from merge/slots; ensure passing tests

* move run_response from Node object to Actor object; execute response functions asynchronously

* update documentation && change the signature of processing-related actor methods

* remove overwrite_current_node_in_processing method

* allow asynchronous condition functions

* update tutorial

* fix merge errors

* make import absolute

* Apply suggestions by @RLKRo

Apply suggestions by @RLKRo

Co-authored-by: Roman Zlobin <[email protected]>

* Update actor & group removing context assignment statements

* test responses for None; use validate_label once

* return context from the 'pipeline' service group

* update tutorial tests for script/core;

* Remove random seed; use seed value of 42

* Deprecate overwrite_current_node

* update deprecation details

* fix: try to resolve docs bug

* update docs

* Update signature typings

* revert tutorial changes

Special tests for parallel processing will be added instead.

* remove overwrite_current_node_in_processing instead of deprecating

I decided that the next release will be 1.0, so we can remove instead of deprecating.

* remove most context returns; update docs and typing

* fix actor test

* codestyle

* add parallel processing test

* make global/local/node conditions run sequentially

As I said before it doesn't make much sense that they run in parallel while conditions in them run sequentially.

* replace args, kwargs with update_ctx_misc

Also includes some doc and typing updates

* codestyle

* fix typing

* line collapse

* rename function to fit inside code blocks

* fix tutorial function signatures

---------

Co-authored-by: Roman Zlobin <[email protected]>
  • Loading branch information
ruthenian8 and RLKRo authored Dec 12, 2023
1 parent 8bfe13b commit 677ee7a
Show file tree
Hide file tree
Showing 39 changed files with 429 additions and 410 deletions.
2 changes: 1 addition & 1 deletion dff/messengers/common/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-

from .interface import MessengerInterface, PollingMessengerInterface, CallbackMessengerInterface, CLIMessengerInterface
from .types import PipelineRunnerFunction, PollingInterfaceLoopFunction
from .types import PollingInterfaceLoopFunction
51 changes: 20 additions & 31 deletions dff/messengers/common/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
The Message Interfaces module contains several basic classes that define the message interfaces.
These classes provide a way to define the structure of the messengers that are used to communicate with the DFF.
"""
from __future__ import annotations
import abc
import asyncio
import logging
import uuid
from typing import Optional, Any, List, Tuple, TextIO, Hashable
from typing import Optional, Any, List, Tuple, TextIO, Hashable, TYPE_CHECKING

from dff.script import Context, Message
from dff.messengers.common.types import PollingInterfaceLoopFunction

from .types import PipelineRunnerFunction, PollingInterfaceLoopFunction
if TYPE_CHECKING:
from dff.pipeline.types import PipelineRunnerFunction

logger = logging.getLogger(__name__)

Expand All @@ -29,9 +32,8 @@ async def connect(self, pipeline_runner: PipelineRunnerFunction):
Method invoked when message interface is instantiated and connection is established.
May be used for sending an introduction message or displaying general bot information.
:param pipeline_runner: A function that should return pipeline response to user request;
:param pipeline_runner: A function that should process user request and return context;
usually it's a :py:meth:`~dff.pipeline.pipeline.pipeline.Pipeline._run_pipeline` function.
:type pipeline_runner: PipelineRunnerFunction
"""
raise NotImplementedError

Expand Down Expand Up @@ -96,12 +98,10 @@ async def connect(
The looping behavior is determined by `loop` and `timeout`,
for most cases the loop itself shouldn't be overridden.
:param pipeline_runner: A function that should return pipeline response to user request;
:param pipeline_runner: A function that should process user request and return context;
usually it's a :py:meth:`~dff.pipeline.pipeline.pipeline.Pipeline._run_pipeline` function.
:type pipeline_runner: PipelineRunnerFunction
:param loop: a function that determines whether polling should be continued;
called in each cycle, should return `True` to continue polling or `False` to stop.
:type loop: PollingInterfaceLoopFunction
:param timeout: a time interval between polls (in seconds).
"""
while loop():
Expand All @@ -124,33 +124,23 @@ def __init__(self):
async def connect(self, pipeline_runner: PipelineRunnerFunction):
self._pipeline_runner = pipeline_runner

async def on_request_async(self, request: Any, ctx_id: Hashable) -> Context:
async def on_request_async(
self, request: Message, ctx_id: Optional[Hashable] = None, update_ctx_misc: Optional[dict] = None
) -> Context:
"""
Method invoked on user input. This method works just like
:py:meth:`~dff.pipeline.pipeline.pipeline.Pipeline._run_pipeline`,
however callback message interface may contain additional functionality (e.g. for external API accessing).
Return context that represents dialog with the user;
`last_response`, `id` and some dialog info can be extracted from there.
:param request: User input.
:param ctx_id: Any unique id that will be associated with dialog between this user and pipeline.
:return: Context that represents dialog with the user.
Method that should be invoked on user input.
This method has the same signature as :py:class:`~dff.pipeline.types.PipelineRunnerFunction`.
"""
return await self._pipeline_runner(request, ctx_id)
return await self._pipeline_runner(request, ctx_id, update_ctx_misc)

def on_request(self, request: Any, ctx_id: Hashable) -> Context:
def on_request(
self, request: Any, ctx_id: Optional[Hashable] = None, update_ctx_misc: Optional[dict] = None
) -> Context:
"""
Method invoked on user input. This method works just like
:py:meth:`~dff.pipeline.pipeline.pipeline.Pipeline._run_pipeline`,
however callback message interface may contain additional functionality (e.g. for external API accessing).
Return context that represents dialog with the user;
`last_response`, `id` and some dialog info can be extracted from there.
:param request: User input.
:param ctx_id: Any unique id that will be associated with dialog between this user and pipeline.
:return: Context that represents dialog with the user.
Method that should be invoked on user input.
This method has the same signature as :py:class:`~dff.pipeline.types.PipelineRunnerFunction`.
"""
return asyncio.run(self.on_request_async(request, ctx_id))
return asyncio.run(self.on_request_async(request, ctx_id, update_ctx_misc))


class CLIMessengerInterface(PollingMessengerInterface):
Expand Down Expand Up @@ -183,9 +173,8 @@ async def connect(self, pipeline_runner: PipelineRunnerFunction, **kwargs):
"""
The CLIProvider generates new dialog id used to user identification on each `connect` call.
:param pipeline_runner: A function that should return pipeline response to user request;
:param pipeline_runner: A function that should process user request and return context;
usually it's a :py:meth:`~dff.pipeline.pipeline.pipeline.Pipeline._run_pipeline` function.
:type pipeline_runner: PipelineRunnerFunction
:param \\**kwargs: argument, added for compatibility with super class, it shouldn't be used normally.
"""
self._ctx_id = uuid.uuid4()
Expand Down
15 changes: 2 additions & 13 deletions dff/messengers/common/types.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
"""
Types
-----
The Types module contains two special types that are used throughout the `DFF Messengers`.
The first type is used for the messenger interface to client interaction and the second one
to control the polling loop.
The Types module contains special types that are used throughout the `DFF Messengers`.
"""
from typing import Callable, Any, Hashable, Awaitable
from typing import Callable
from typing_extensions import TypeAlias

from dff.script import Context


PipelineRunnerFunction: TypeAlias = Callable[[Any, Hashable], Awaitable[Context]]
"""
A function type for messenger_interface-to-client interaction.
Accepts anything (user input) and hashable value (current context id), returns string (answer from pipeline).
"""


PollingInterfaceLoopFunction: TypeAlias = Callable[[], bool]
"""
Expand Down
3 changes: 2 additions & 1 deletion dff/messengers/telegram/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

from telebot import types, apihelper

from dff.messengers.common import MessengerInterface, PipelineRunnerFunction, CallbackMessengerInterface
from dff.messengers.common import MessengerInterface, CallbackMessengerInterface
from dff.pipeline.types import PipelineRunnerFunction
from .messenger import TelegramMessenger
from .message import TelegramMessage

Expand Down
Loading

0 comments on commit 677ee7a

Please sign in to comment.