dc6079821b
Docs Tests / Check for file changes (push) Has been cancelled
Docs Tests / Test Documentation (push) Has been cancelled
Docs Tests / Documentation Linting Checks (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.9) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.9) (push) Has been cancelled
Continuous Integration / Check for file changes (push) Has been cancelled
Continuous Integration / Wait for docs tests (push) Has been cancelled
Continuous Integration / Code Quality (push) Has been cancelled
Continuous Integration / Check for changelog (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Upload coverage reports to codeclimate (push) Has been cancelled
Continuous Integration / Run Non-Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Run Broker Integration Tests (push) Has been cancelled
Continuous Integration / Run Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Build Docker base images and setup environment (push) Has been cancelled
Continuous Integration / Build Docker (default) (push) Has been cancelled
Continuous Integration / Build Docker (full) (push) Has been cancelled
Continuous Integration / Build Docker (mitie-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-de) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-it) (push) Has been cancelled
Continuous Integration / Deploy to PyPI (push) Has been cancelled
Continuous Integration / Notify Slack & Publish Release Notes (push) Has been cancelled
Publish Documentation / Evaluate release tag (push) Has been cancelled
Publish Documentation / Prebuild Docs (push) Has been cancelled
Publish Documentation / Preview Docs (push) Has been cancelled
Publish Documentation / Check for file changes (push) Has been cancelled
Publish Documentation / Publish Docs (push) Has been cancelled
Automatic PR Merger / mergepal (push) Has been cancelled
CI Github Actions / Run Tests (push) Has been cancelled
Semgrep / Semgrep Workflow Security Scan (push) Has been cancelled
370 lines
11 KiB
Python
370 lines
11 KiB
Python
from __future__ import annotations
|
|
from typing import Any, Dict, Optional, Text
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
|
|
import rasa.shared
|
|
import rasa.shared.utils
|
|
import rasa.shared.utils.io
|
|
from rasa.engine.exceptions import GraphComponentException
|
|
from rasa.engine.graph import ExecutionContext, GraphComponent, GraphNode, GraphSchema
|
|
from rasa.engine.storage.storage import ModelStorage
|
|
from rasa.engine.storage.resource import Resource
|
|
from tests.engine.graph_components_test_classes import (
|
|
AddInputs,
|
|
ExecutionContextAware,
|
|
ProvideX,
|
|
SubtractByX,
|
|
PersistableTestComponent,
|
|
)
|
|
|
|
|
|
def test_calling_component(default_model_storage: ModelStorage):
|
|
node = GraphNode(
|
|
node_name="add_node",
|
|
component_class=AddInputs,
|
|
constructor_name="create",
|
|
component_config={},
|
|
fn_name="add",
|
|
inputs={"i1": "input_node1", "i2": "input_node2"},
|
|
eager=False,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "1"),
|
|
)
|
|
|
|
result = node(("input_node1", 3), ("input_node2", 4))
|
|
|
|
assert result == ("add_node", 7)
|
|
|
|
|
|
@pytest.mark.parametrize("x, output", [(None, 5), (0, 5), (1, 4), (2, 3)])
|
|
def test_component_config(
|
|
x: Optional[int], output: int, default_model_storage: ModelStorage
|
|
):
|
|
node = GraphNode(
|
|
node_name="subtract",
|
|
component_class=SubtractByX,
|
|
constructor_name="create",
|
|
component_config={"x": x} if x else {},
|
|
fn_name="subtract_x",
|
|
inputs={"i": "input_node"},
|
|
eager=False,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "1"),
|
|
)
|
|
|
|
result = node(("input_node", 5))
|
|
|
|
assert result == ("subtract", output)
|
|
|
|
|
|
def test_can_use_alternate_constructor(default_model_storage: ModelStorage):
|
|
node = GraphNode(
|
|
node_name="provide",
|
|
component_class=ProvideX,
|
|
constructor_name="create_with_2",
|
|
component_config={},
|
|
fn_name="provide",
|
|
inputs={},
|
|
eager=False,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "1"),
|
|
)
|
|
|
|
result = node()
|
|
assert result == ("provide", 2)
|
|
|
|
|
|
@pytest.mark.parametrize("eager", [True, False])
|
|
def test_eager_and_not_eager(eager: bool, default_model_storage: ModelStorage):
|
|
run_mock = Mock()
|
|
create_mock = Mock()
|
|
|
|
class SpyComponent(GraphComponent):
|
|
@classmethod
|
|
def create(
|
|
cls,
|
|
config: Dict,
|
|
model_storage: ModelStorage,
|
|
resource: Resource,
|
|
execution_context: ExecutionContext,
|
|
) -> SpyComponent:
|
|
create_mock()
|
|
return cls()
|
|
|
|
def run(self):
|
|
return run_mock()
|
|
|
|
node = GraphNode(
|
|
node_name="spy_node",
|
|
component_class=SpyComponent,
|
|
constructor_name="create",
|
|
component_config={},
|
|
fn_name="run",
|
|
inputs={},
|
|
eager=eager,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "1"),
|
|
)
|
|
|
|
if eager:
|
|
assert create_mock.called
|
|
else:
|
|
assert not create_mock.called
|
|
|
|
assert not run_mock.called
|
|
|
|
node()
|
|
|
|
assert create_mock.call_count == 1
|
|
assert run_mock.called
|
|
|
|
|
|
def test_non_eager_can_use_inputs_for_constructor(default_model_storage: ModelStorage):
|
|
node = GraphNode(
|
|
node_name="provide",
|
|
component_class=ProvideX,
|
|
constructor_name="create",
|
|
component_config={},
|
|
fn_name="provide",
|
|
inputs={"x": "input_node"},
|
|
eager=False,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "1"),
|
|
)
|
|
|
|
result = node(("input_node", 5))
|
|
|
|
assert result == ("provide", 5)
|
|
|
|
|
|
def test_execution_context(default_model_storage: ModelStorage):
|
|
context = ExecutionContext(GraphSchema({}), "some_id")
|
|
node = GraphNode(
|
|
node_name="execution_context_aware",
|
|
component_class=ExecutionContextAware,
|
|
constructor_name="create",
|
|
component_config={},
|
|
fn_name="get_execution_context",
|
|
inputs={},
|
|
eager=False,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=context,
|
|
)
|
|
|
|
context.model_id = "a_new_id"
|
|
|
|
result = node()[1]
|
|
assert result.model_id == "some_id"
|
|
assert result.node_name == "execution_context_aware"
|
|
|
|
|
|
def test_constructor_exception(default_model_storage: ModelStorage):
|
|
class BadConstructor(GraphComponent):
|
|
@classmethod
|
|
def create(
|
|
cls,
|
|
config: Dict[Text, Any],
|
|
model_storage: ModelStorage,
|
|
resource: Resource,
|
|
execution_context: ExecutionContext,
|
|
) -> BadConstructor:
|
|
raise ValueError("oh no!")
|
|
|
|
def run(self) -> None:
|
|
...
|
|
|
|
with pytest.raises(GraphComponentException):
|
|
GraphNode(
|
|
node_name="bad_constructor",
|
|
component_class=BadConstructor,
|
|
constructor_name="create",
|
|
component_config={},
|
|
fn_name="run",
|
|
inputs={},
|
|
eager=True,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "some_id"),
|
|
)
|
|
|
|
|
|
def test_fn_exception(default_model_storage: ModelStorage):
|
|
class BadFn(GraphComponent):
|
|
@classmethod
|
|
def create(
|
|
cls,
|
|
config: Dict[Text, Any],
|
|
model_storage: ModelStorage,
|
|
resource: Resource,
|
|
execution_context: ExecutionContext,
|
|
) -> BadFn:
|
|
return cls()
|
|
|
|
def run(self) -> None:
|
|
raise ValueError("Oh no!")
|
|
|
|
node = GraphNode(
|
|
node_name="bad_fn",
|
|
component_class=BadFn,
|
|
constructor_name="create",
|
|
component_config={},
|
|
fn_name="run",
|
|
inputs={},
|
|
eager=True,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "some_id"),
|
|
)
|
|
|
|
with pytest.raises(GraphComponentException):
|
|
node()
|
|
|
|
|
|
def test_writing_to_resource_during_training(default_model_storage: ModelStorage):
|
|
node_name = "some_name"
|
|
|
|
test_value_for_sub_directory = {"test": "test value sub dir"}
|
|
test_value = {"test dir": "test value dir"}
|
|
|
|
node = GraphNode(
|
|
node_name=node_name,
|
|
component_class=PersistableTestComponent,
|
|
constructor_name="create",
|
|
component_config={
|
|
"test_value": test_value,
|
|
"test_value_for_sub_directory": test_value_for_sub_directory,
|
|
},
|
|
fn_name="train",
|
|
inputs={},
|
|
eager=False,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "123"),
|
|
)
|
|
|
|
_, resource = node()
|
|
|
|
assert resource == Resource(node_name)
|
|
|
|
with default_model_storage.read_from(resource) as directory:
|
|
assert (
|
|
rasa.shared.utils.io.read_json_file(directory / "test.json") == test_value
|
|
)
|
|
assert (
|
|
rasa.shared.utils.io.read_json_file(directory / "sub_dir" / "test.json")
|
|
== test_value_for_sub_directory
|
|
)
|
|
|
|
|
|
def test_loading_from_resource_not_eager(default_model_storage: ModelStorage):
|
|
previous_resource = Resource("previous resource")
|
|
parent_node_name = "parent"
|
|
test_value = {"test": "test value"}
|
|
|
|
# Pretend resource persisted itself before
|
|
with default_model_storage.write_to(previous_resource) as directory:
|
|
rasa.shared.utils.io.dump_obj_as_json_to_file(
|
|
directory / "test.json", test_value
|
|
)
|
|
|
|
node_name = "some_name"
|
|
node = GraphNode(
|
|
node_name=node_name,
|
|
component_class=PersistableTestComponent,
|
|
constructor_name="load",
|
|
component_config={},
|
|
fn_name="run_train_process",
|
|
inputs={"resource": parent_node_name},
|
|
eager=False,
|
|
model_storage=default_model_storage,
|
|
# The `GraphComponent` should load from this resource
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "123"),
|
|
)
|
|
|
|
_, value = node((parent_node_name, previous_resource))
|
|
|
|
assert value == test_value
|
|
|
|
|
|
def test_loading_from_resource_eager(default_model_storage: ModelStorage):
|
|
previous_resource = Resource("previous resource")
|
|
test_value = {"test": "test value"}
|
|
|
|
# Pretend resource persisted itself before
|
|
with default_model_storage.write_to(previous_resource) as directory:
|
|
rasa.shared.utils.io.dump_obj_as_json_to_file(
|
|
directory / "test.json", test_value
|
|
)
|
|
|
|
node_name = "some_name"
|
|
node = GraphNode(
|
|
node_name=node_name,
|
|
component_class=PersistableTestComponent,
|
|
constructor_name="load",
|
|
component_config={},
|
|
fn_name="run_inference",
|
|
inputs={},
|
|
eager=True,
|
|
model_storage=default_model_storage,
|
|
# The `GraphComponent` should load from this resource
|
|
resource=previous_resource,
|
|
execution_context=ExecutionContext(GraphSchema({}), "123"),
|
|
)
|
|
|
|
actual_node_name, value = node()
|
|
|
|
assert actual_node_name == node_name
|
|
assert value == test_value
|
|
|
|
|
|
def test_config_with_nested_dict_override(default_model_storage: ModelStorage):
|
|
class ComponentWithNestedDictConfig(GraphComponent):
|
|
@staticmethod
|
|
def get_default_config() -> Dict[Text, Any]:
|
|
return {"nested-dict": {"key1": "value1", "key2": "value2"}}
|
|
|
|
@classmethod
|
|
def create(
|
|
cls,
|
|
config: Dict,
|
|
model_storage: ModelStorage,
|
|
resource: Resource,
|
|
execution_context: ExecutionContext,
|
|
**kwargs: Any,
|
|
) -> ComponentWithNestedDictConfig:
|
|
return cls()
|
|
|
|
def run(self) -> None:
|
|
return None
|
|
|
|
node = GraphNode(
|
|
node_name="nested_dict_config",
|
|
component_class=ComponentWithNestedDictConfig,
|
|
constructor_name="create",
|
|
component_config={"nested-dict": {"key2": "override-value2"}},
|
|
fn_name="run",
|
|
inputs={},
|
|
eager=True,
|
|
model_storage=default_model_storage,
|
|
resource=None,
|
|
execution_context=ExecutionContext(GraphSchema({}), "123"),
|
|
)
|
|
|
|
expected_config = {"nested-dict": {"key1": "value1", "key2": "override-value2"}}
|
|
|
|
for key, value in expected_config.items():
|
|
assert key in node._component_config
|
|
if isinstance(value, dict):
|
|
for nested_key, nested_value in expected_config[key].items():
|
|
assert nested_key in node._component_config[key]
|
|
assert node._component_config[key][nested_key] == nested_value
|