Skip to content

Commit 8ea8c7a

Browse files
authored
Release v0.9 (#393)
2 parents d428908 + 8aedf8c commit 8ea8c7a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2545
-3485
lines changed
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
# flake8: noqa: F401
22

3-
from chatsky.core.service.types import ExtraHandlerRuntimeInfo, StartConditionCheckerFunction, ComponentExecutionState
3+
from chatsky.core.service.types import ExtraHandlerRuntimeInfo, ComponentExecutionState
44
from chatsky.core import Context, Script
55
from chatsky.core.script import Node
66
from chatsky.core.pipeline import Pipeline
77
from chatsky.slots.slots import SlotManager
8-
from chatsky.core.context import FrameworkData
8+
from chatsky.core.context import FrameworkData, ServiceState
9+
from chatsky.core.service import PipelineComponent
910

11+
PipelineComponent.model_rebuild()
1012
Pipeline.model_rebuild()
1113
Script.model_rebuild()
1214
Context.model_rebuild()
1315
ExtraHandlerRuntimeInfo.model_rebuild()
1416
FrameworkData.model_rebuild()
17+
ServiceState.model_rebuild()

chatsky/conditions/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
HasCallbackQuery,
1111
)
1212
from chatsky.conditions.slots import SlotsExtracted
13+
from chatsky.conditions.service import ServiceFinished

chatsky/conditions/service.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
Service Conditions
3+
------------------
4+
Provides service-related conditions
5+
"""
6+
7+
from __future__ import annotations
8+
9+
from chatsky.core.context import Context
10+
from chatsky.core.script_function import BaseCondition
11+
12+
from chatsky.core.service.types import (
13+
ComponentExecutionState,
14+
)
15+
16+
17+
class ServiceFinished(BaseCondition):
18+
"""
19+
Check if a :py:class:`~chatsky.core.service.service.Service` was executed successfully.
20+
"""
21+
22+
path: str
23+
"""The path of the condition pipeline component."""
24+
wait: bool = False
25+
"""
26+
Whether to wait for the service to be finished.
27+
28+
This eliminates possible service states ``NOT_RUN`` and ``RUNNING``.
29+
"""
30+
31+
def __init__(self, path: str, *, wait: bool = False):
32+
super().__init__(path=path, wait=wait)
33+
34+
async def call(self, ctx: Context) -> bool:
35+
if self.wait:
36+
await ctx.framework_data.service_states[self.path].finished_event.wait()
37+
38+
state = ctx.framework_data.service_states[self.path].execution_status
39+
40+
return ComponentExecutionState[state] == ComponentExecutionState.FINISHED

chatsky/conditions/standard.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class HasText(BaseCondition):
6969
Text to search for in the last request.
7070
"""
7171

72-
def __init__(self, text):
72+
def __init__(self, text: str):
7373
super().__init__(text=text)
7474

7575
async def call(self, ctx: Context) -> bool:
@@ -94,7 +94,7 @@ class Regexp(BaseCondition):
9494
Flags to pass to ``re.compile``.
9595
"""
9696

97-
def __init__(self, pattern, *, flags=0):
97+
def __init__(self, pattern: Union[str, Pattern], *, flags: Union[int, re.RegexFlag] = 0):
9898
super().__init__(pattern=pattern, flags=flags)
9999

100100
@computed_field
@@ -120,7 +120,7 @@ class Any(BaseCondition):
120120
List of conditions.
121121
"""
122122

123-
def __init__(self, *conditions):
123+
def __init__(self, *conditions: BaseCondition):
124124
super().__init__(conditions=list(conditions))
125125

126126
async def call(self, ctx: Context) -> bool:
@@ -137,7 +137,7 @@ class All(BaseCondition):
137137
List of conditions.
138138
"""
139139

140-
def __init__(self, *conditions):
140+
def __init__(self, *conditions: BaseCondition):
141141
super().__init__(conditions=list(conditions))
142142

143143
async def call(self, ctx: Context) -> bool:
@@ -154,7 +154,7 @@ class Negation(BaseCondition):
154154
Condition to negate.
155155
"""
156156

157-
def __init__(self, condition):
157+
def __init__(self, condition: BaseCondition):
158158
super().__init__(condition=condition)
159159

160160
async def call(self, ctx: Context) -> bool:
@@ -189,7 +189,11 @@ class CheckLastLabels(BaseCondition):
189189
"""
190190

191191
def __init__(
192-
self, *, flow_labels=None, labels: Optional[List[AbsoluteNodeLabelInitTypes]] = None, last_n_indices=1
192+
self,
193+
*,
194+
flow_labels: Optional[List[str]] = None,
195+
labels: Optional[List[AbsoluteNodeLabelInitTypes]] = None,
196+
last_n_indices: int = 1
193197
):
194198
if flow_labels is None:
195199
flow_labels = []
@@ -216,7 +220,7 @@ class HasCallbackQuery(BaseCondition):
216220
Query string to find in last request's attachments.
217221
"""
218222

219-
def __init__(self, query_string):
223+
def __init__(self, query_string: str):
220224
super().__init__(query_string=query_string)
221225

222226
async def call(self, ctx: Context) -> bool:

chatsky/core/context.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from __future__ import annotations
2020
import logging
21+
import asyncio
2122
from uuid import UUID, uuid4
2223
from typing import Any, Optional, Union, Dict, TYPE_CHECKING
2324

@@ -28,9 +29,9 @@
2829
from chatsky.core.node_label import AbsoluteNodeLabel, AbsoluteNodeLabelInitTypes
2930

3031
if TYPE_CHECKING:
32+
from chatsky.core.service import ComponentExecutionState
3133
from chatsky.core.script import Node
3234
from chatsky.core.pipeline import Pipeline
33-
from chatsky.core.service.types import ComponentExecutionState
3435

3536
logger = logging.getLogger(__name__)
3637

@@ -53,13 +54,29 @@ class ContextError(Exception):
5354
"""Raised when context methods are not used correctly."""
5455

5556

56-
class FrameworkData(BaseModel):
57+
class ServiceState(BaseModel, arbitrary_types_allowed=True):
58+
execution_status: ComponentExecutionState = Field(default="NOT_RUN")
59+
"""
60+
:py:class:`.ComponentExecutionState` of this pipeline service.
61+
Cleared at the end of every turn.
62+
"""
63+
finished_event: asyncio.Event = Field(default_factory=asyncio.Event)
64+
"""
65+
Asyncio `Event` which can be awaited until this service finishes.
66+
Cleared at the end of every turn.
67+
"""
68+
69+
70+
class FrameworkData(BaseModel, arbitrary_types_allowed=True):
5771
"""
5872
Framework uses this to store data related to any of its modules.
5973
"""
6074

61-
service_states: Dict[str, ComponentExecutionState] = Field(default_factory=dict, exclude=True)
62-
"Statuses of all the pipeline services. Cleared at the end of every turn."
75+
service_states: Dict[str, ServiceState] = Field(default_factory=dict, exclude=True)
76+
"""
77+
Dictionary containing :py:class:`.ServiceState` of all the pipeline components.
78+
Cleared at the end of every turn.
79+
"""
6380
current_node: Optional[Node] = Field(default=None, exclude=True)
6481
"""
6582
A copy of the current node provided by :py:meth:`~chatsky.core.script.Script.get_inherited_node`.

chatsky/core/pipeline.py

Lines changed: 5 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,8 @@
2424
from chatsky.slots.slots import GroupSlot
2525
from chatsky.core.service.group import ServiceGroup, ServiceGroupInitTypes
2626
from chatsky.core.service.extra import ComponentExtraHandlerInitTypes, BeforeHandler, AfterHandler
27-
from chatsky.core.service.types import (
28-
GlobalExtraHandlerType,
29-
ExtraHandlerFunction,
30-
)
3127
from .service import Service
32-
from .utils import finalize_service_group
28+
from .utils import finalize_service_group, initialize_service_states
3329
from chatsky.core.service.actor import Actor
3430
from chatsky.core.node_label import AbsoluteNodeLabel, AbsoluteNodeLabelInitTypes
3531
from chatsky.core.script_parsing import JSONImporter, Path
@@ -104,15 +100,6 @@ class Pipeline(BaseModel, extra="forbid", arbitrary_types_allowed=True):
104100
timeout: Optional[float] = None
105101
"""
106102
Timeout to add to pipeline root service group.
107-
"""
108-
optimization_warnings: bool = False
109-
"""
110-
Asynchronous pipeline optimization check request flag;
111-
warnings will be sent to logs. Additionally, it has some calculated fields:
112-
113-
- `services_pipeline` is a pipeline root :py:class:`~.ServiceGroup` object,
114-
- `actor` is a pipeline actor, found among services.
115-
116103
"""
117104
parallelize_processing: bool = False
118105
"""
@@ -136,7 +123,6 @@ def __init__(
136123
before_handler: ComponentExtraHandlerInitTypes = None,
137124
after_handler: ComponentExtraHandlerInitTypes = None,
138125
timeout: float = None,
139-
optimization_warnings: bool = None,
140126
parallelize_processing: bool = None,
141127
):
142128
if fallback_label is None:
@@ -154,7 +140,6 @@ def __init__(
154140
"before_handler": before_handler,
155141
"after_handler": after_handler,
156142
"timeout": timeout,
157-
"optimization_warnings": optimization_warnings,
158143
"parallelize_processing": parallelize_processing,
159144
}
160145
empty_fields = set()
@@ -216,14 +201,11 @@ def services_pipeline(self) -> PipelineServiceGroup:
216201
after_handler=self.after_handler,
217202
timeout=self.timeout,
218203
)
219-
services_pipeline.name = "pipeline"
220-
services_pipeline.path = ".pipeline"
204+
services_pipeline.name = ""
205+
services_pipeline.path = ""
221206

222207
finalize_service_group(services_pipeline, path=services_pipeline.path)
223208

224-
if self.optimization_warnings:
225-
services_pipeline.log_optimization_warnings()
226-
227209
return services_pipeline
228210

229211
@model_validator(mode="after")
@@ -240,60 +222,6 @@ def validate_fallback_label(self):
240222
raise ValueError(f"Unknown fallback_label={self.fallback_label}")
241223
return self
242224

243-
def add_global_handler(
244-
self,
245-
global_handler_type: GlobalExtraHandlerType,
246-
extra_handler: ExtraHandlerFunction,
247-
whitelist: Optional[List[str]] = None,
248-
blacklist: Optional[List[str]] = None,
249-
):
250-
"""
251-
Method for adding global wrappers to pipeline.
252-
Different types of global wrappers are called before/after pipeline execution
253-
or before/after each pipeline component.
254-
They can be used for pipeline statistics collection or other functionality extensions.
255-
NB! Global wrappers are still wrappers,
256-
they shouldn't be used for much time-consuming tasks (see :py:mod:`chatsky.core.service.extra`).
257-
258-
:param global_handler_type: (required) indication where the wrapper
259-
function should be executed.
260-
:param extra_handler: (required) wrapper function itself.
261-
:type extra_handler: ExtraHandlerFunction
262-
:param whitelist: a list of services to only add this wrapper to.
263-
:param blacklist: a list of services to not add this wrapper to.
264-
:return: `None`
265-
"""
266-
267-
def condition(name: str) -> bool:
268-
return (whitelist is None or name in whitelist) and (blacklist is None or name not in blacklist)
269-
270-
if (
271-
global_handler_type is GlobalExtraHandlerType.BEFORE_ALL
272-
or global_handler_type is GlobalExtraHandlerType.AFTER_ALL
273-
):
274-
whitelist = ["pipeline"]
275-
global_handler_type = (
276-
GlobalExtraHandlerType.BEFORE
277-
if global_handler_type is GlobalExtraHandlerType.BEFORE_ALL
278-
else GlobalExtraHandlerType.AFTER
279-
)
280-
281-
self.services_pipeline.add_extra_handler(global_handler_type, extra_handler, condition)
282-
283-
@property
284-
def info_dict(self) -> dict:
285-
"""
286-
Property for retrieving info dictionary about this pipeline.
287-
Returns info dict, containing most important component public fields as well as its type.
288-
All complex or unserializable fields here are replaced with 'Instance of [type]'.
289-
"""
290-
return {
291-
"type": type(self).__name__,
292-
"messenger_interface": f"Instance of {type(self.messenger_interface).__name__}",
293-
"context_storage": f"Instance of {type(self.context_storage).__name__}",
294-
"services": [self.services_pipeline.info_dict],
295-
}
296-
297225
async def _run_pipeline(
298226
self, request: Message, ctx_id: Optional[Hashable] = None, update_ctx_misc: Optional[dict] = None
299227
) -> Context:
@@ -329,12 +257,10 @@ async def _run_pipeline(
329257
ctx.framework_data.slot_manager.set_root_slot(self.slots)
330258

331259
ctx.framework_data.pipeline = self
260+
initialize_service_states(ctx, self.services_pipeline)
332261

333262
ctx.add_request(request)
334-
result = await self.services_pipeline(ctx, self)
335-
336-
if asyncio.iscoroutine(result):
337-
await result
263+
await self.services_pipeline(ctx)
338264

339265
ctx.framework_data.service_states.clear()
340266
ctx.framework_data.pipeline = None

chatsky/core/script_function.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ async def wrapped_call(self, ctx: Context, *, info: str = ""):
5151
logger.debug(f"Function {self.__class__.__name__} returned {result!r}. {info}")
5252
return result
5353
except Exception as exc:
54-
logger.warning(f"An exception occurred in {self.__class__.__name__}. {info}", exc_info=exc)
54+
logger.error(f"An exception occurred in {self.__class__.__name__}. {info}", exc_info=exc)
5555
return exc
5656

5757
async def __call__(self, ctx: Context):

chatsky/core/service/__init__.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,14 @@
55
"""
66

77
from .component import PipelineComponent
8-
from .conditions import (
9-
always_start_condition,
10-
service_successful_condition,
11-
not_condition,
12-
all_condition,
13-
any_condition,
14-
)
158
from .extra import BeforeHandler, AfterHandler
169
from .group import ServiceGroup
1710
from .service import Service, to_service
1811
from .types import (
19-
ServiceRuntimeInfo,
2012
ExtraHandlerRuntimeInfo,
21-
GlobalExtraHandlerType,
2213
ExtraHandlerType,
2314
PipelineRunnerFunction,
2415
ComponentExecutionState,
25-
StartConditionCheckerFunction,
2616
ExtraHandlerConditionFunction,
2717
ExtraHandlerFunction,
28-
ServiceFunction,
2918
)

0 commit comments

Comments
 (0)