コード例 #1
0
def test_incorrect_access_fn() -> None:
    """
    This test shows that the plugin needs `access` function to be a `PluginFn`,
    or else it throws a `TypeError`.
    """
    rules = {"basic": {"slot_name": "basic_slot", "entity_type": "basic"}}
    access = 5

    slot_filler = RuleBasedSlotFillerPlugin(rules=rules, access=access)()
    workflow = Workflow(preprocessors=[], postprocessors=[slot_filler])
    intent = Intent(name="intent", score=0.8)

    body = "12th december"
    entity = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="basic",
        values=[{
            "key": "value"
        }],
        slot_names=["basic_slot"],
    )

    workflow.output = (intent, [entity])

    with pytest.raises(TypeError):
        workflow.run("")
コード例 #2
0
def test_plugin_cases(payload) -> None:
    """
    Test cases where the plugin should work.
    """
    entities = payload.get("inputs", {}).get("entities", [])
    tracker = payload.get("inputs", {}).get("tracker", [])
    expected = payload.get("expected", {})
    duckling_plugin = DucklingPlugin(dimensions=["date", "time"],
                                     timezone="Asia/Kolkata",
                                     dest="output.entities")

    for i, entity in enumerate(entities):
        current_turn_entities = duckling_plugin._reshape(entity, i)

    combine_date_time_plugin = CombineDateTimeOverSlots(
        trigger_intents=["_callback_"],
        dest="output.entities",
    )

    workflow = Workflow(plugins=[combine_date_time_plugin])
    workflow.output = Output(entities=current_turn_entities)
    _, output = workflow.run(Input(utterances=[""], slot_tracker=tracker))
    entity_values = [entity["value"] for entity in output[const.ENTITIES]]

    if len(entity_values) != len(expected):
        pytest.fail("Expected {} entities but got {}".format(
            len(expected), len(entity_values)))

    for entity_value, expected_value in zip(entity_values, expected):
        try:
            expected = datetime.fromisoformat(expected_value)
            generated = datetime.fromisoformat(entity_value)
            assert generated == expected, f"Expected {expected} but got {generated}"
        except (ValueError, TypeError):
            assert entity_value == expected_value
コード例 #3
0
def test_workflow_set_output() -> None:
    """
    We can set output and input as anything.
    """
    workflow = Workflow(preprocessors=[], postprocessors=[])
    workflow.output = 10
    assert workflow.output == 10, "workflow.get_output() should == 10."
コード例 #4
0
def test_missing_access_fn() -> None:
    """
    This test shows that the plugin needs an `access` provided or else it raises a type error.
    """
    slot_filler = RuleBasedSlotFillerPlugin(rules=rules)()
    workflow = Workflow(preprocessors=[], postprocessors=[slot_filler])
    intent = Intent(name="intent", score=0.8)

    body = "12th december"
    entity = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="basic",
        values=[{
            "key": "value"
        }],
        slot_names=["basic_slot"],
    )

    workflow.output = (intent, [entity])

    with pytest.raises(TypeError):
        workflow.run("")
コード例 #5
0
def test_slot_filling_multiple() -> None:
    """
    Let's try filling both the slots this time with fill_multiple=True!
    `intent_2` supports both `entity_1` and `entity_2`.
    """
    def access(workflow: Workflow) -> Any:
        return workflow.output

    intent_name = "intent_2"

    # Setting up the slot-filler, both instantiation and plugin is created. (notice two calls).
    slot_filler = RuleBasedSlotFillerPlugin(rules=rules,
                                            access=access,
                                            fill_multiple=True)()

    # Create a mock `workflow`
    workflow = Workflow(preprocessors=[], postprocessors=[slot_filler])

    # ... a mock `Intent`
    intent = Intent(name=intent_name, score=0.8)

    # and mock `Entity`-ies.
    body = "12th december"
    entity_1 = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="entity_1",
        values=[{
            "key": "value"
        }],
        slot_names=["entity_1_slot"],
    )

    entity_2 = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="entity_2",
        values=[{
            "key": "value"
        }],
        slot_names=["entity_2_slot"],
    )

    # The RuleBasedSlotFillerPlugin specifies that it expects `Tuple[Intent, List[Entity])` on `access(workflow)`.
    workflow.output = (intent, [entity_1, entity_2])
    workflow.run(body)

    # `workflow.output[0]` is the `Intent` we created.
    # The `entity_1_slot` and `entity_2_slot` are filled.
    assert workflow.output[0].slots["entity_1_slot"].values == [entity_1]
    assert workflow.output[0].slots["entity_2_slot"].values == [entity_2]
コード例 #6
0
ファイル: test_plugins.py プロジェクト: Vernacular-ai/dialogy
def test_plugin_no_set_on_invalid_output():
    arbitrary_plugin = ArbitraryPlugin(
        dest="output.intents",
        guards=[lambda i, _: i.current_state == "COF"],
    )
    workflow = Workflow()
    workflow.input = Input(utterances="hello")
    workflow.output = None
    assert arbitrary_plugin(workflow) is None
コード例 #7
0
def test_slot_competition() -> None:
    """
    What happens when we have two entities of the same type but different value?
    """
    def access(workflow: Workflow) -> Any:
        return workflow.output

    intent_name = "intent_1"

    # Setting up the slot-filler, both instantiation and plugin is created. (notice two calls).
    slot_filler = RuleBasedSlotFillerPlugin(rules=rules, access=access)()

    # Create a mock `workflow`
    workflow = Workflow(preprocessors=[], postprocessors=[slot_filler])

    # ... a mock `Intent`
    intent = Intent(name=intent_name, score=0.8)

    # Here we have two entities which compete for the same slot but have different values.
    body = "12th december"
    entity_1 = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="entity_1",
        values=[{
            "key": "value_1"
        }],
        slot_names=["entity_1_slot"],
    )

    entity_2 = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="entity_1",
        values=[{
            "key": "value_2"
        }],
        slot_names=["entity_1_slot"],
    )

    # The RuleBasedSlotFillerPlugin specifies that it expects `Tuple[Intent, List[Entity])` on `access(workflow)`.
    workflow.output = (intent, [entity_1, entity_2])
    workflow.run(body)

    # `workflow.output[0]` is the `Intent` we created.
    # The `entity_1_slot` and `entity_2_slot` are filled.
    assert "entity_1_slot" not in workflow.output[0].slots
コード例 #8
0
def test_voting_0_intents():
    """
    The code uses division. So its always good to
    have a test to see if it takes care of division 0.
    """
    intents: List[Intent] = []
    vote_plugin = VotePlugin(access=lambda w: (w.output[0], 0), mutate=update_intent)()
    workflow = Workflow(preprocessors=[], postprocessors=[vote_plugin])
    workflow.output = intents, []
    intent, _ = workflow.run(input_="")
    assert intent.name == const.S_INTENT_OOS
コード例 #9
0
def test_voting_0_intents():
    """
    The code uses division. So its always good to
    have a test to see if it takes care of division 0.
    """
    intents: List[Intent] = []
    vote_plugin = VotePlugin(dest="output.intents")
    workflow = Workflow([vote_plugin])
    workflow.output = Output(intents=intents)
    _, output = workflow.run(Input(utterances=["some text"]))
    assert output["intents"][0]["name"] == const.S_INTENT_OOS
コード例 #10
0
def test_missing_access():
    intents = [
        Intent(name="a", score=0.3),
        Intent(name="a", score=0.2),
        Intent(name="b", score=0.1),
        Intent(name="b", score=0.1),
    ]

    vote_plugin = VotePlugin(mutate=update_intent)()
    workflow = Workflow(preprocessors=[], postprocessors=[vote_plugin])
    workflow.output = intents, []
    with pytest.raises(TypeError):
        intent, _ = workflow.run(input_="")
コード例 #11
0
def test_representation_oos():
    intents = [
        Intent(name="a", score=0.99),
        Intent(name="b", score=0.1),
        Intent(name="b", score=0.4),
        Intent(name="b", score=0.31),
        Intent(name="d", score=0.44),
    ]

    vote_plugin = VotePlugin(dest="output.intents")
    workflow = Workflow([vote_plugin])
    workflow.output = Output(intents=intents)
    _, output = workflow.run(Input(utterances=["some text"]))
    assert output["intents"][0]["name"] == "_oos_"
コード例 #12
0
def test_representation_oos():
    intents = [
        Intent(name="a", score=0.99),
        Intent(name="b", score=0.1),
        Intent(name="c", score=0.31),
        Intent(name="d", score=0.44),
    ]

    vote_plugin = VotePlugin(
        access=lambda w: (w.output[0], len(intents)), mutate=update_intent
    )()
    workflow = Workflow(preprocessors=[], postprocessors=[vote_plugin])
    workflow.output = intents, []
    intent, _ = workflow.run(input_="")
    assert intent.name == "_oos_"
コード例 #13
0
def test_voting_on_conflicts():
    """
    Testing the case with conflicts.
    """
    intents = [
        Intent(name="a", score=1),
        Intent(name="a", score=1),
        Intent(name="b", score=1),
        Intent(name="b", score=1),
    ]
    vote_plugin = VotePlugin(dest="output.intents")
    workflow = Workflow([vote_plugin])
    workflow.output = Output(intents=intents)
    _, output = workflow.run(Input(utterances=["some text"]))
    assert output["intents"][0]["name"] == "_oos_"
コード例 #14
0
def test_voting_on_weak_signals():
    """
    Testing all weak intents.
    """
    intents = [
        Intent(name="a", score=0.3),
        Intent(name="a", score=0.2),
        Intent(name="b", score=0.1),
        Intent(name="b", score=0.1),
    ]
    vote_plugin = VotePlugin(dest="output.intents")
    workflow = Workflow([vote_plugin])
    workflow.output = Output(intents=intents)
    _, output = workflow.run(Input(utterances=["some text"]))
    assert output["intents"][0]["name"] == "_oos_"
コード例 #15
0
def test_voting_on_conflicts():
    """
    Testing the case with conflicts.
    """
    intents = [
        Intent(name="a", score=1),
        Intent(name="a", score=1),
        Intent(name="b", score=1),
        Intent(name="b", score=1),
    ]
    vote_plugin = VotePlugin(
        access=lambda w: (w.output[0], len(intents)), mutate=update_intent
    )()
    workflow = Workflow(preprocessors=[], postprocessors=[vote_plugin])
    workflow.output = intents, []
    intent, _ = workflow.run(input_="")
    assert intent.name == "_oos_"
コード例 #16
0
def test_voting_n_intents():
    """
    Testing the usual case.
    """
    intents = [
        Intent(name="a", score=1),
        Intent(name="a", score=1),
        Intent(name="b", score=0.13),
        Intent(name="a", score=1),
    ]
    vote_plugin = VotePlugin(
        debug=True, access=lambda w: (w.output[0], len(intents)), mutate=update_intent
    )()
    workflow = Workflow(preprocessors=[], postprocessors=[vote_plugin])
    workflow.output = intents, []
    intent, _ = workflow.run(input_="")
    assert intent.name == "a"
コード例 #17
0
def test_voting_on_weak_signals():
    """
    Testing all weak intents.
    """
    intents = [
        Intent(name="a", score=0.3),
        Intent(name="a", score=0.2),
        Intent(name="b", score=0.1),
        Intent(name="b", score=0.1),
    ]
    vote_plugin = VotePlugin(
        access=lambda w: (w.output[0], len(intents)), mutate=update_intent
    )()
    workflow = Workflow(preprocessors=[], postprocessors=[vote_plugin])
    workflow.output = intents, []
    intent, _ = workflow.run(input_="")
    assert intent.name == "_oos_"
コード例 #18
0
def test_voting_n_intents():
    """
    Testing the usual case.
    """
    intents = [
        Intent(name="a", score=1),
        Intent(name="a", score=1),
        Intent(name="b", score=0.13),
        Intent(name="a", score=1),
    ]
    vote_plugin = VotePlugin(
        debug=False,
        dest="output.intents",
    )
    workflow = Workflow([vote_plugin])
    workflow.output = Output(intents=intents)
    _, output = workflow.run(Input(utterances=["some text"]))
    assert output["intents"][0]["name"] == "a"
コード例 #19
0
def test_slot_no_fill() -> None:
    """
    Here, we will see that an entity will not fill an intent unless the intent has a slot for it.
    `intent_1` doesn't have a slot for an entity of type `entity_2`.
    """
    def access(workflow: Workflow) -> Any:
        return workflow.output

    intent_name = "intent_1"

    # Setting up the slot-filler, both instantiation and plugin is created. (notice two calls).
    slot_filler = RuleBasedSlotFillerPlugin(rules=rules, access=access)()

    # Create a mock `workflow`
    workflow = Workflow(preprocessors=[], postprocessors=[slot_filler])

    # ... a mock `Intent`
    intent = Intent(name=intent_name, score=0.8)

    # and a mock `Entity`.
    body = "12th december"
    entity = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="entity_2",
        values=[{
            "key": "value"
        }],
        slot_names=["entity_2_slot"],
    )

    # The RuleBasedSlotFillerPlugin specifies that it expects `Tuple[Intent, List[Entity])` on `access(workflow)`.
    workflow.output = (intent, [entity])
    workflow.run(body)

    # `workflow.output[0]` is the `Intent` we created.
    # we can see that the `entity_2_slot` is not filled by our mock entity.
    assert "entity_1_slot" not in workflow.output[0].slots
コード例 #20
0
def test_slot_filling() -> None:
    """
    This test case covers a trivial usage of a slot-filler.
    We have `rules` that demonstrate association of intents with entities and their respective slot-configuration.
    """
    def access(workflow: Workflow) -> Any:
        return workflow.output

    intent_name = "intent_1"

    # Setting up the slot-filler, both instantiation and plugin is created. (notice two calls).
    slot_filler = RuleBasedSlotFillerPlugin(rules=rules, access=access)()

    # Create a mock `workflow`
    workflow = Workflow(preprocessors=[], postprocessors=[slot_filler])

    # ... a mock `Intent`
    intent = Intent(name=intent_name, score=0.8)

    # and a mock `Entity`.
    body = "12th december"
    entity = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="entity_1",
        values=[{
            "key": "value"
        }],
        slot_names=["entity_1_slot"],
    )

    # The RuleBasedSlotFillerPlugin specifies that it expects `Tuple[Intent, List[Entity])` on `access(workflow)`.
    workflow.output = (intent, [entity])
    workflow.run(body)

    # `workflow.output[0]` is the `Intent` we created.
    # so we are checking if the `entity_1_slot` is filled by our mock entity.
    assert workflow.output[0].slots["entity_1_slot"].values[0] == entity
コード例 #21
0
def test_aggregate_fn_incorrect():
    intents = [
        Intent(name="a", score=0.99),
        Intent(name="a", score=0.99),
        Intent(name="a", score=0.91),
        Intent(name="b", score=0.1),
        Intent(name="c", score=0.31),
        Intent(name="d", score=0.44),
    ]

    vote_plugin = VotePlugin(
        dest="output.intents",
        aggregate_fn=5,
    )
    workflow = Workflow([vote_plugin])
    workflow.output = Output(intents=intents)

    with pytest.raises(TypeError):
        _, output = workflow.run(Input(utterances=[""]))
        assert output["intents"][0]["name"] == "a"
コード例 #22
0
def test_aggregate_fn_incorrect():
    intents = [
        Intent(name="a", score=0.99),
        Intent(name="a", score=0.99),
        Intent(name="a", score=0.91),
        Intent(name="b", score=0.1),
        Intent(name="c", score=0.31),
        Intent(name="d", score=0.44),
    ]

    vote_plugin = VotePlugin(
        access=lambda w: (w.output[0], len(intents)),
        mutate=update_intent,
        aggregate_fn=5,
    )()
    workflow = Workflow(preprocessors=[], postprocessors=[vote_plugin])
    workflow.output = intents, []

    with pytest.raises(TypeError):
        intent, _ = workflow.run(input_="")
        assert intent.name == "a"
コード例 #23
0
ファイル: test_plugins.py プロジェクト: us241098/dialogy
def mutate(workflow: Workflow, value: Any) -> Any:
    """
    This function would be provided by the
    workflow implementer.
    """
    workflow.output = value