コード例 #1
0
def test_intent_parser() -> None:
    """
    Creating an instance.
    """
    intent = Intent(name="intent_name", score=0.5)
    intent.add_parser(MockPlugin())

    assert intent.parsers == ["MockPlugin"]
コード例 #2
0
    def vote_signal(self, intents: List[Intent], trials: int) -> List[Intent]:
        """
        Reduce a list of intents.

        This is a naive voting algorithm. We filter intents with high confidence.
        Count the frequency of the remaining intents. If the proportion of votes
        goes beyond the expected constituency, then the intent is elected else
        a fallback intent is emitted.

        :param intents: A list of predictions over ASR output. (size ~ 1-10)
        :type intents: List[Intent]
        :param trials: Number of observations over which the set of intents is obtained.
        :type trials: int
        :return: Voted signal or fallback in case of no consensus.
        :rtype: Intent
        """
        fallback = [Intent(name=self.fallback_intent, score=1)]
        if not intents:
            return fallback

        intent_signals = [(intent.name, intent.score, 1.0) for intent in intents]
        intent_signals = adjust_signal_strength(
            intent_signals, trials, aggregate_fn=self.aggregate_fn
        )
        main_intent: Signal = intent_signals[0]
        conflict_intent: Signal = (
            intent_signals[1] if len(intent_signals) > 1 else ("_", 0, 0)
        )

        logger.debug("Intents with adjusted signal strength: ")
        logger.debug(intent_signals)

        representative_signal = self.representation <= (main_intent[const.SIGNAL.REPRESENTATION] - conflict_intent[const.SIGNAL.REPRESENTATION])  # type: ignore
        logger.debug(f"representative signal: {representative_signal}")

        consensus_achieved = (
            main_intent[const.SIGNAL.STRENGTH] - conflict_intent[const.SIGNAL.STRENGTH]  # type: ignore
            > self.consensus
        )
        logger.debug(
            f"consensus achieved: {consensus_achieved=} | ({main_intent[const.SIGNAL.STRENGTH]=} - {conflict_intent[const.SIGNAL.STRENGTH]=}) > {self.consensus=}"
        )

        strong_signal = main_intent[const.SIGNAL.STRENGTH] > self.threshold  # type: ignore
        logger.debug(f"strong signal: {strong_signal}")

        if (consensus_achieved or representative_signal) and strong_signal:
            return [
                Intent(
                    name=main_intent[const.SIGNAL.NAME],  # type: ignore
                    score=main_intent[const.SIGNAL.STRENGTH],  # type: ignore
                )
            ]
        return [Intent(name=self.fallback_intent, score=1)]
コード例 #3
0
ファイル: intent.py プロジェクト: us241098/dialogy
    def vote_signal(self, intents: List[Intent], trials: int) -> Intent:
        """
        Reduce a list of intents.

        This is a naive voting algorithm. We filter intents with high confidence.
        Count the frequency of the remaining intents. If the proportion of votes
        goes beyond the expected constituency, then the intent is elected else
        a fallback intent is emitted.

        Args:
            intents (List[Intent]): A list of predictions over ASR output. (size ~ 1-10)
            constituency (float, optional): Threshold for proportion of votes,
                proportion over this qualifies an intent for victory. Defaults to 0.5.

        Returns:
            Intent: Voted signal or fallback in case of no consensus.
        """
        fallback = Intent(name=self.fallback_intent, score=1)
        if not intents:
            return fallback

        intent_signals = [(intent.name, intent.score, 1.0)
                          for intent in intents]
        intent_signals = adjust_signal_strength(intent_signals,
                                                trials,
                                                aggregate_fn=self.aggregate_fn)
        main_intent: Signal = intent_signals[0]
        conflict_intent: Signal = (intent_signals[1]
                                   if len(intent_signals) > 1 else ("_", 0, 0))

        if self.debug:
            change_log_level("DEBUG")
            log.debug("Intents with adjusted signal strength: ")
            log.debug(intent_signals)
            change_log_level("INFO")

        if self.representation > main_intent[
                const.SIGNAL.REPRESENTATION]:  # type: ignore
            return Intent(name=self.fallback_intent, score=1)

        consensus_achieved = (
            main_intent[const.SIGNAL.STRENGTH] -
            conflict_intent[const.SIGNAL.STRENGTH]  # type: ignore
            > self.consensus)

        strong_signal = main_intent[
            const.SIGNAL.STRENGTH] > self.threshold  # type: ignore
        if consensus_achieved and strong_signal:
            return Intent(
                name=main_intent[const.SIGNAL.NAME],  # type: ignore
                score=main_intent[const.SIGNAL.STRENGTH],  # type: ignore
            )
        return Intent(name=self.fallback_intent, score=1)
コード例 #4
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_="")
コード例 #5
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_"
コード例 #6
0
def test_rule_with_multiple_types() -> None:
    ordinal_entity = BaseEntity(
        range={
            "from": 0,
            "to": 15
        },
        body="12th december",
        dim="default",
        entity_type="ordinal",
        values=[{
            "key": "12th"
        }],
        slot_names=["basic_slot"],
    )
    number_entity = BaseEntity(
        range={
            "from": 0,
            "to": 15
        },
        body="12 december",
        dim="default",
        entity_type="number",
        values=[{
            "key": "12"
        }],
        slot_names=["basic_slot"],
    )
    rules = {"intent": {"basic_slot": ["ordinal", "number"]}}
    intent = Intent(name="intent", score=0.8)
    intent.apply(rules)
    intent.fill_slot(number_entity, fill_multiple=True)
    intent.fill_slot(ordinal_entity, fill_multiple=True)

    assert intent.slots["basic_slot"].values[0] == number_entity
    assert intent.slots["basic_slot"].values[1] == ordinal_entity
コード例 #7
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_"
コード例 #8
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_"
コード例 #9
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_"
コード例 #10
0
def test_slot_invalid_intent() -> 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`.
    """
    intent_name = "intent_1"
    # ... a mock `Intent`
    intent = Intent(name=intent_name, score=0.8)

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

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

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

    # The RuleBasedSlotFillerPlugin specifies that it expects `Tuple[Intent, List[Entity])` on `access(workflow)`.
    workflow.set("output.intents", [1]).set("output.entities", [entity])

    with pytest.raises(AttributeError):
        workflow.run(Input(utterances=body))
コード例 #11
0
def test_missing_rule() -> None:
    """
    In case there is no rule for an intent?
    """
    rules = {
        "intent": {
            "date_slot": "date",
            "number_slot": "number",
        }
    }

    intent = Intent(name="some-other-intent", score=0.8)
    intent.apply(rules)

    assert "date_slot" not in intent.slots, "date_slot should be present."
    assert "number_slot" not in intent.slots, "number_slot should be present."
コード例 #12
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("")
コード例 #13
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("")
コード例 #14
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`.
    """
    intent_name = "intent_2"

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

    # Create a mock `workflow`
    workflow = Workflow([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",
        entity_type="entity_1",
        values=[{
            "key": "value"
        }],
    )

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

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

    # `workflow.output[0]` is the `Intent` we created.
    # The `entity_1_slot` and `entity_2_slot` are filled.
    assert output[const.INTENTS][0]["slots"]["entity_1_slot"]["values"] == [
        entity_1.json()
    ]
    assert output[const.INTENTS][0]["slots"]["entity_2_slot"]["values"] == [
        entity_2.json()
    ]
コード例 #15
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]
コード例 #16
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_"
コード例 #17
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_"
コード例 #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=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"
コード例 #19
0
def test_slot_filling_prop_removal() -> None:
    """
    This test shows rule application, and filling an entity within a slot.
    """
    body = "12th december"
    entity = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        entity_type="basic",
        values=[{
            "key": "value"
        }],
        slot_names=["basic_slot"],
    )
    rules = {"intent": {"basic_slot": "basic"}}
    intent = Intent(name="intent", score=0.8)
    intent.apply(rules)
    intent.fill_slot(entity)

    intent_json = intent.json()
    assert "dim" not in intent_json["slots"]["basic_slot"]["values"][0]
コード例 #20
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"
コード例 #21
0
def test_slot_competition_fill_multiple() -> None:
    """
    What happens when we have two entities of the same type but different value?
    """
    intent_name = "intent_1"

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

    # Create a mock `workflow`
    workflow = Workflow([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",
        entity_type="entity_1",
        values=[{
            "key": "value_1"
        }],
    )

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

    workflow.set("output.intents", [intent]).set("output.entities",
                                                 [entity_1, entity_2])
    _, output = workflow.run(Input(utterances=body))

    # `workflow.output[0]` is the `Intent` we created.
    # The `entity_1_slot` and `entity_2_slot` are filled.

    assert output[const.INTENTS][0]["slots"]["entity_1_slot"]["values"] == [
        entity_1.json(),
        entity_2.json(),
    ]
コード例 #22
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
コード例 #23
0
ファイル: test_intents.py プロジェクト: us241098/dialogy
def test_slot_filling() -> None:
    """
    This test shows rule application, and filling an entity within a slot.
    """
    body = "12th december"
    entity = BaseEntity(
        range={
            "from": 0,
            "to": len(body)
        },
        body=body,
        dim="default",
        type="basic",
        values=[{
            "key": "value"
        }],
        slot_names=["basic_slot"],
    )
    rules = {"intent": {"basic_slot": "basic"}}
    intent = Intent(name="intent", score=0.8)
    intent.apply(rules)

    intent.fill_slot(entity)

    assert intent.slots["basic_slot"].values[0] == entity
コード例 #24
0
def test_rule_application() -> None:
    """
    A rule application case.

    This is helpful if you wish to understand how slots are filled within an intent.
    An initial setup is rule application, once that's done, you can expect
    the slots to be ready for containing entities.
    """

    rules = {
        "intent": {
            "date_slot": "date",
            "number_slot": "number",
        }
    }

    intent = Intent(name="intent", score=0.8)
    intent.apply(rules)

    assert "date_slot" in intent.slots, "date_slot should be present."
    assert "number_slot" in intent.slots, "number_slot should be present."

    assert intent.slots["date_slot"].types == ["date"]
    assert intent.slots["number_slot"].types == ["number"]
コード例 #25
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
コード例 #26
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
コード例 #27
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`.
    """
    intent_name = "intent_1"

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

    # Create a mock `workflow`
    workflow = Workflow([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",
        entity_type="entity_2",
        values=[{
            "key": "value"
        }],
    )

    # The RuleBasedSlotFillerPlugin specifies that it expects `Tuple[Intent, List[Entity])` on `access(workflow)`.
    workflow.set("output.intents", [intent]).set("output.entities", [entity])

    _, output = workflow.run(Input(utterances=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 output[const.INTENTS][0]["slots"]
コード例 #28
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.
    """
    intent_name = "intent_1"

    slot_filler = RuleBasedSlotFillerPlugin(rules=rules, dest="output.intents")

    # Create a mock `workflow`
    workflow = Workflow([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",
        entity_type="entity_1",
        values=[{
            "key": "value"
        }],
    )

    # The RuleBasedSlotFillerPlugin specifies that it expects `Tuple[Intent, List[Entity])` on `access(workflow)`.
    workflow.set("output.intents", [intent]).set("output.entities", [entity])

    _, output = workflow.run(Input(utterances=body))
    intent, *_ = output[const.INTENTS]

    # `workflow.output[0]` is the `Intent` we created.
    # so we are checking if the `entity_1_slot` is filled by our mock entity.
    assert intent["slots"]["entity_1_slot"]["values"][0] == entity.json()
コード例 #29
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"
コード例 #30
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"