dc6079821b
CI Github Actions / Run Tests (push) Waiting to run
Automatic PR Merger / mergepal (push) Waiting to run
Semgrep / Semgrep Workflow Security Scan (push) Waiting to run
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
644 lines
19 KiB
Python
644 lines
19 KiB
Python
import os
|
|
import textwrap
|
|
from pathlib import Path
|
|
import json
|
|
import logging
|
|
from typing import Any, Text, Dict, Callable
|
|
|
|
import pytest
|
|
|
|
import rasa.shared.utils.io
|
|
import rasa.utils.io
|
|
from rasa.core.test import (
|
|
_create_data_generator,
|
|
_collect_story_predictions,
|
|
test as evaluate_stories,
|
|
_clean_entity_results,
|
|
)
|
|
from rasa.core.constants import (
|
|
CONFUSION_MATRIX_STORIES_FILE,
|
|
REPORT_STORIES_FILE,
|
|
FAILED_STORIES_FILE,
|
|
SUCCESSFUL_STORIES_FILE,
|
|
STORIES_WITH_WARNINGS_FILE,
|
|
)
|
|
|
|
# we need this import to ignore the warning...
|
|
# noinspection PyUnresolvedReferences
|
|
from rasa.nlu.test import evaluate_entities, run_evaluation # noqa: F401
|
|
from rasa.core.agent import Agent, load_agent
|
|
from rasa.shared.constants import LATEST_TRAINING_DATA_FORMAT_VERSION
|
|
from rasa.shared.exceptions import RasaException
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
async def trained_restaurantbot(trained_async: Callable) -> Path:
|
|
zipped_model = await trained_async(
|
|
domain="data/test_restaurantbot/domain.yml",
|
|
config="data/test_restaurantbot/config.yml",
|
|
training_files=[
|
|
"data/test_restaurantbot/data/rules.yml",
|
|
"data/test_restaurantbot/data/stories.yml",
|
|
"data/test_restaurantbot/data/nlu.yml",
|
|
],
|
|
)
|
|
|
|
if not zipped_model:
|
|
raise RasaException("Model training for formbot failed.")
|
|
|
|
return Path(zipped_model)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
async def restaurantbot_agent(trained_restaurantbot: Path) -> Agent:
|
|
return await load_agent(str(trained_restaurantbot))
|
|
|
|
|
|
async def test_evaluation_file_creation(
|
|
tmpdir: Path, default_agent: Agent, stories_path: Text
|
|
):
|
|
failed_stories_path = str(tmpdir / FAILED_STORIES_FILE)
|
|
success_stories_path = str(tmpdir / SUCCESSFUL_STORIES_FILE)
|
|
stories_with_warnings_path = str(tmpdir / STORIES_WITH_WARNINGS_FILE)
|
|
report_path = str(tmpdir / REPORT_STORIES_FILE)
|
|
confusion_matrix_path = str(tmpdir / CONFUSION_MATRIX_STORIES_FILE)
|
|
|
|
await evaluate_stories(
|
|
stories=stories_path,
|
|
agent=default_agent,
|
|
out_directory=str(tmpdir),
|
|
max_stories=None,
|
|
e2e=False,
|
|
errors=True,
|
|
successes=True,
|
|
warnings=True,
|
|
)
|
|
|
|
assert os.path.isfile(failed_stories_path)
|
|
assert os.path.isfile(success_stories_path)
|
|
assert os.path.isfile(stories_with_warnings_path)
|
|
assert os.path.isfile(report_path)
|
|
assert os.path.isfile(confusion_matrix_path)
|
|
|
|
|
|
async def test_end_to_end_evaluation_script(
|
|
default_agent: Agent, end_to_end_story_path: Text
|
|
):
|
|
generator = _create_data_generator(
|
|
end_to_end_story_path, default_agent, use_conversation_test_files=True
|
|
)
|
|
completed_trackers = generator.generate_story_trackers()
|
|
|
|
story_evaluation, num_stories, _ = await _collect_story_predictions(
|
|
completed_trackers, default_agent, use_e2e=True
|
|
)
|
|
|
|
serialised_store = [
|
|
"utter_greet",
|
|
"action_listen",
|
|
"utter_greet",
|
|
"action_listen",
|
|
"utter_default",
|
|
"action_listen",
|
|
"utter_goodbye",
|
|
"action_listen",
|
|
"utter_greet",
|
|
"action_listen",
|
|
"utter_default",
|
|
"action_listen",
|
|
"greet",
|
|
"greet",
|
|
"default",
|
|
"goodbye",
|
|
"greet",
|
|
"default",
|
|
'[{"name": "Max"}]{"entity": "name", "value": "Max"}',
|
|
]
|
|
|
|
assert story_evaluation.evaluation_store.serialise()[0] == serialised_store
|
|
assert not story_evaluation.evaluation_store.check_prediction_target_mismatch()
|
|
assert len(story_evaluation.failed_stories) == 0
|
|
assert num_stories == 3
|
|
|
|
|
|
async def test_end_to_end_evaluation_script_unknown_entity(
|
|
default_agent: Agent, e2e_story_file_unknown_entity_path: Text
|
|
):
|
|
generator = _create_data_generator(
|
|
e2e_story_file_unknown_entity_path,
|
|
default_agent,
|
|
use_conversation_test_files=True,
|
|
)
|
|
completed_trackers = generator.generate_story_trackers()
|
|
|
|
story_evaluation, num_stories, _ = await _collect_story_predictions(
|
|
completed_trackers, default_agent
|
|
)
|
|
|
|
assert story_evaluation.evaluation_store.check_prediction_target_mismatch()
|
|
assert len(story_evaluation.failed_stories) == 1
|
|
assert num_stories == 1
|
|
|
|
|
|
@pytest.mark.timeout(300, func_only=True)
|
|
async def test_end_to_evaluation_with_forms(form_bot_agent: Agent):
|
|
generator = _create_data_generator(
|
|
"data/test_evaluations/test_form_end_to_end_stories.yml",
|
|
form_bot_agent,
|
|
use_conversation_test_files=True,
|
|
)
|
|
test_stories = generator.generate_story_trackers()
|
|
|
|
story_evaluation, num_stories, _ = await _collect_story_predictions(
|
|
test_stories, form_bot_agent
|
|
)
|
|
|
|
assert not story_evaluation.evaluation_store.check_prediction_target_mismatch()
|
|
|
|
|
|
async def test_source_in_failed_stories(
|
|
tmpdir: Path, default_agent: Agent, e2e_story_file_unknown_entity_path: Text
|
|
):
|
|
stories_path = str(tmpdir / FAILED_STORIES_FILE)
|
|
|
|
await evaluate_stories(
|
|
stories=e2e_story_file_unknown_entity_path,
|
|
agent=default_agent,
|
|
out_directory=str(tmpdir),
|
|
max_stories=None,
|
|
e2e=False,
|
|
)
|
|
story_file_unknown_entity = Path(e2e_story_file_unknown_entity_path).absolute()
|
|
failed_stories = rasa.shared.utils.io.read_file(stories_path)
|
|
|
|
assert (
|
|
f"story: simple_story_with_unknown_entity ({story_file_unknown_entity})"
|
|
in failed_stories
|
|
)
|
|
|
|
|
|
async def test_end_to_evaluation_trips_circuit_breaker(
|
|
e2e_story_file_trips_circuit_breaker_path: Text,
|
|
trained_async: Callable,
|
|
tmp_path: Path,
|
|
):
|
|
config = textwrap.dedent(
|
|
f"""
|
|
version: "{LATEST_TRAINING_DATA_FORMAT_VERSION}"
|
|
assistant_id: placeholder_default
|
|
policies:
|
|
- name: MemoizationPolicy
|
|
max_history: 11
|
|
|
|
pipeline: []
|
|
"""
|
|
)
|
|
config_path = tmp_path / "config.yml"
|
|
rasa.shared.utils.io.write_text_file(config, config_path)
|
|
|
|
model_path = await trained_async(
|
|
"data/test_domains/default.yml",
|
|
str(config_path),
|
|
e2e_story_file_trips_circuit_breaker_path,
|
|
)
|
|
|
|
agent = await load_agent(model_path)
|
|
generator = _create_data_generator(
|
|
e2e_story_file_trips_circuit_breaker_path,
|
|
agent,
|
|
use_conversation_test_files=True,
|
|
)
|
|
test_stories = generator.generate_story_trackers()
|
|
|
|
story_evaluation, num_stories, _ = await _collect_story_predictions(
|
|
test_stories, agent
|
|
)
|
|
|
|
circuit_trip_predicted = [
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"utter_greet",
|
|
"circuit breaker tripped",
|
|
"circuit breaker tripped",
|
|
]
|
|
|
|
assert (
|
|
story_evaluation.evaluation_store.action_predictions == circuit_trip_predicted
|
|
)
|
|
assert num_stories == 1
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"text, entity, expected_entity",
|
|
[
|
|
(
|
|
"The first one please.",
|
|
{
|
|
"extractor": "DucklingEntityExtractor",
|
|
"entity": "ordinal",
|
|
"confidence": 0.87,
|
|
"start": 4,
|
|
"end": 9,
|
|
"value": 1,
|
|
},
|
|
{
|
|
"text": "The first one please.",
|
|
"entity": "ordinal",
|
|
"start": 4,
|
|
"end": 9,
|
|
"value": "1",
|
|
},
|
|
),
|
|
(
|
|
"The first one please.",
|
|
{
|
|
"extractor": "CRFEntityExtractor",
|
|
"entity": "ordinal",
|
|
"confidence": 0.87,
|
|
"start": 4,
|
|
"end": 9,
|
|
"value": "1",
|
|
},
|
|
{
|
|
"text": "The first one please.",
|
|
"entity": "ordinal",
|
|
"start": 4,
|
|
"end": 9,
|
|
"value": "1",
|
|
},
|
|
),
|
|
(
|
|
"Italian food",
|
|
{
|
|
"extractor": "DIETClassifier",
|
|
"entity": "cuisine",
|
|
"confidence": 0.99,
|
|
"start": 0,
|
|
"end": 7,
|
|
"value": "Italian",
|
|
},
|
|
{
|
|
"text": "Italian food",
|
|
"entity": "cuisine",
|
|
"start": 0,
|
|
"end": 7,
|
|
"value": "Italian",
|
|
},
|
|
),
|
|
],
|
|
)
|
|
def test_event_has_proper_implementation(
|
|
text: Text, entity: Dict[Text, Any], expected_entity: Dict[Text, Any]
|
|
):
|
|
actual_entities = _clean_entity_results(text, [entity])
|
|
|
|
assert actual_entities[0] == expected_entity
|
|
|
|
|
|
@pytest.mark.timeout(600, func_only=True)
|
|
@pytest.mark.parametrize(
|
|
"test_file",
|
|
[
|
|
("data/test_yaml_stories/test_full_retrieval_intent_story.yml"),
|
|
("data/test_yaml_stories/test_base_retrieval_intent_story.yml"),
|
|
],
|
|
)
|
|
async def test_retrieval_intent(response_selector_agent: Agent, test_file: Text):
|
|
generator = _create_data_generator(
|
|
test_file, response_selector_agent, use_conversation_test_files=True
|
|
)
|
|
test_stories = generator.generate_story_trackers()
|
|
|
|
story_evaluation, num_stories, _ = await _collect_story_predictions(
|
|
test_stories, response_selector_agent
|
|
)
|
|
# check that test story can either specify base intent or full retrieval intent
|
|
assert not story_evaluation.evaluation_store.check_prediction_target_mismatch()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"test_file",
|
|
[
|
|
("data/test_yaml_stories/test_full_retrieval_intent_wrong_prediction.yml"),
|
|
("data/test_yaml_stories/test_base_retrieval_intent_wrong_prediction.yml"),
|
|
],
|
|
)
|
|
async def test_retrieval_intent_wrong_prediction(
|
|
tmpdir: Path, response_selector_agent: Agent, test_file: Text
|
|
):
|
|
stories_path = str(tmpdir / FAILED_STORIES_FILE)
|
|
|
|
await evaluate_stories(
|
|
stories=test_file,
|
|
agent=response_selector_agent,
|
|
out_directory=str(tmpdir),
|
|
max_stories=None,
|
|
e2e=True,
|
|
)
|
|
|
|
failed_stories = rasa.shared.utils.io.read_file(stories_path)
|
|
|
|
# check if the predicted entry contains full retrieval intent
|
|
assert "# predicted: chitchat/ask_name" in failed_stories
|
|
|
|
|
|
# FIXME: these tests take too long to run in the CI, disabling them for now
|
|
@pytest.mark.skip_on_ci
|
|
@pytest.mark.timeout(240, func_only=True)
|
|
async def test_e2e_with_entity_evaluation(e2e_bot_agent: Agent, tmp_path: Path):
|
|
test_file = "data/test_e2ebot/tests/test_stories.yml"
|
|
|
|
await evaluate_stories(
|
|
stories=test_file,
|
|
agent=e2e_bot_agent,
|
|
out_directory=str(tmp_path),
|
|
max_stories=None,
|
|
e2e=True,
|
|
)
|
|
|
|
report = rasa.shared.utils.io.read_json_file(tmp_path / "TEDPolicy_report.json")
|
|
assert report["name"] == {
|
|
"precision": 1.0,
|
|
"recall": 1.0,
|
|
"f1-score": 1.0,
|
|
"support": 1,
|
|
"confused_with": {},
|
|
}
|
|
assert report["mood"] == {
|
|
"precision": 1.0,
|
|
"recall": 0.5,
|
|
"f1-score": 0.6666666666666666,
|
|
"support": 2,
|
|
"confused_with": {},
|
|
}
|
|
errors = rasa.shared.utils.io.read_json_file(tmp_path / "TEDPolicy_errors.json")
|
|
assert len(errors) == 1
|
|
assert errors[0]["text"] == "today I was very cranky"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"stories_yaml,expected_results",
|
|
[
|
|
[
|
|
"""
|
|
stories:
|
|
- story: story1
|
|
steps:
|
|
- intent: greet
|
|
- action: utter_greet
|
|
- story: story2
|
|
steps:
|
|
- intent: goodbye
|
|
- action: utter_goodbye
|
|
- story: story3
|
|
steps:
|
|
- intent: greet
|
|
- action: utter_greet
|
|
- intent: goodbye
|
|
- action: utter_default
|
|
""",
|
|
{
|
|
"utter_goodbye": {
|
|
"precision": 1.0,
|
|
"recall": 1.0,
|
|
"f1-score": 1.0,
|
|
"support": 1,
|
|
},
|
|
"action_listen": {
|
|
"precision": 1.0,
|
|
"recall": 0.75,
|
|
"f1-score": 0.8571428571428571,
|
|
"support": 4,
|
|
},
|
|
"utter_greet": {
|
|
"precision": 1.0,
|
|
"recall": 1.0,
|
|
"f1-score": 1.0,
|
|
"support": 2,
|
|
},
|
|
"utter_default": {
|
|
"precision": 0.0,
|
|
"recall": 0.0,
|
|
"f1-score": 0.0,
|
|
"support": 1,
|
|
},
|
|
"accuracy": 0.75,
|
|
"micro avg": {
|
|
"precision": 1.0,
|
|
"recall": 0.75,
|
|
"f1-score": 0.8571428571428571,
|
|
"support": 8,
|
|
},
|
|
"macro avg": {
|
|
"precision": 0.75,
|
|
"recall": 0.6875,
|
|
"f1-score": 0.7142857142857143,
|
|
"support": 8,
|
|
},
|
|
"weighted avg": {
|
|
"precision": 0.875,
|
|
"recall": 0.75,
|
|
"f1-score": 0.8035714285714286,
|
|
"support": 8,
|
|
},
|
|
"conversation_accuracy": {
|
|
"accuracy": 2.0 / 3.0,
|
|
"total": 3,
|
|
"correct": 2,
|
|
"with_warnings": 0,
|
|
},
|
|
},
|
|
]
|
|
],
|
|
)
|
|
async def test_story_report(
|
|
tmpdir: Path,
|
|
core_agent: Agent,
|
|
stories_yaml: Text,
|
|
expected_results: Dict[Text, Dict[Text, Any]],
|
|
) -> None:
|
|
"""Check story_report.json file contains correct result keys/values."""
|
|
|
|
stories_path = tmpdir / "stories.yml"
|
|
stories_path.write_text(stories_yaml, "utf8")
|
|
out_directory = tmpdir / "results"
|
|
out_directory.mkdir()
|
|
|
|
await evaluate_stories(stories_path, core_agent, out_directory=out_directory)
|
|
story_report_path = out_directory / "story_report.json"
|
|
assert story_report_path.exists()
|
|
|
|
actual_results = json.loads(story_report_path.read_text("utf8"))
|
|
assert actual_results == expected_results
|
|
|
|
|
|
async def test_story_report_with_empty_stories(tmpdir: Path, core_agent: Agent) -> None:
|
|
stories_path = tmpdir / "stories.yml"
|
|
stories_path.write_text("", "utf8")
|
|
out_directory = tmpdir / "results"
|
|
out_directory.mkdir()
|
|
|
|
await evaluate_stories(stories_path, core_agent, out_directory=out_directory)
|
|
story_report_path = out_directory / "story_report.json"
|
|
assert story_report_path.exists()
|
|
|
|
actual_results = json.loads(story_report_path.read_text("utf8"))
|
|
assert actual_results == {}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"skip_field,skip_value",
|
|
[
|
|
[None, None],
|
|
["precision", None],
|
|
["f1", None],
|
|
["in_training_data_fraction", None],
|
|
["report", None],
|
|
["include_report", False],
|
|
],
|
|
)
|
|
async def test_log_evaluation_table(caplog, skip_field, skip_value):
|
|
"""Check that _log_evaluation_table correctly omits/includes optional args."""
|
|
arr = [1, 1, 1, 0]
|
|
acc = 0.75
|
|
kwargs = {
|
|
"precision": 0.5,
|
|
"f1": 0.6,
|
|
"in_training_data_fraction": 0.1,
|
|
"report": {"macro f1": 0.7},
|
|
}
|
|
if skip_field:
|
|
kwargs[skip_field] = skip_value
|
|
caplog.set_level(logging.INFO)
|
|
rasa.core.test._log_evaluation_table(arr, "CONVERSATION", acc, **kwargs)
|
|
|
|
assert f"Correct: {int(len(arr) * acc)} / {len(arr)}" in caplog.text
|
|
assert f"Accuracy: {acc:.3f}" in caplog.text
|
|
|
|
if skip_field != "f1":
|
|
assert f"F1-Score: {kwargs['f1']:5.3f}" in caplog.text
|
|
else:
|
|
assert "F1-Score:" not in caplog.text
|
|
|
|
if skip_field != "precision":
|
|
assert f"Precision: {kwargs['precision']:5.3f}" in caplog.text
|
|
else:
|
|
assert "Precision:" not in caplog.text
|
|
|
|
if skip_field != "in_training_data_fraction":
|
|
assert (
|
|
f"In-data fraction: {kwargs['in_training_data_fraction']:.3g}"
|
|
in caplog.text
|
|
)
|
|
else:
|
|
assert "In-data fraction:" not in caplog.text
|
|
|
|
if skip_field != "report" and skip_field != "include_report":
|
|
assert f"Classification report: \n{kwargs['report']}" in caplog.text
|
|
else:
|
|
assert "Classification report:" not in caplog.text
|
|
|
|
|
|
@pytest.mark.skip_on_windows
|
|
@pytest.mark.parametrize(
|
|
"test_file, correct_intent, correct_entity",
|
|
[
|
|
[
|
|
"data/test_yaml_stories/"
|
|
"test_prediction_with_correct_intent_wrong_entity.yml",
|
|
True,
|
|
False,
|
|
],
|
|
[
|
|
"data/test_yaml_stories/"
|
|
"test_prediction_with_wrong_intent_correct_entity.yml",
|
|
False,
|
|
True,
|
|
],
|
|
[
|
|
"data/test_yaml_stories/"
|
|
"test_prediction_with_wrong_intent_wrong_entity.yml",
|
|
False,
|
|
False,
|
|
],
|
|
],
|
|
)
|
|
async def test_wrong_predictions_with_intent_and_entities(
|
|
tmpdir: Path,
|
|
restaurantbot_agent: Agent,
|
|
test_file: Text,
|
|
correct_intent: bool,
|
|
correct_entity: bool,
|
|
):
|
|
stories_path = str(tmpdir / FAILED_STORIES_FILE)
|
|
|
|
await evaluate_stories(
|
|
stories=test_file,
|
|
agent=restaurantbot_agent,
|
|
out_directory=str(tmpdir),
|
|
max_stories=None,
|
|
e2e=True,
|
|
)
|
|
|
|
failed_stories = rasa.shared.utils.io.read_file(stories_path)
|
|
|
|
if correct_intent and not correct_entity:
|
|
# check if there is no comment on the intent line
|
|
assert "- intent: request_restaurant # predicted:" not in failed_stories
|
|
# check if there is a comment with the predicted entity on the entity line
|
|
assert "# predicted: cuisine: greek" in failed_stories
|
|
# check that the correctly predicted entity is printed as well
|
|
assert "- seating: outside\n" in failed_stories
|
|
# check that it does not double print entities
|
|
assert failed_stories.count("\n") == 8
|
|
|
|
elif not correct_intent and correct_entity:
|
|
# check if there is a comment with the predicted intent on the intent line
|
|
assert "- intent: greet # predicted: request_restaurant" in failed_stories
|
|
# check if there is no comment on the entity line
|
|
assert "# predicted: cuisine: greek" not in failed_stories
|
|
# check that the correctly predicted entity is printed as well
|
|
assert "- seating: outside\n" in failed_stories
|
|
# check that it does not double print entities
|
|
assert failed_stories.count("\n") == 9
|
|
|
|
elif not correct_intent and not correct_entity:
|
|
# check if there is a comment with the predicted intent on the intent line
|
|
assert "- intent: greet # predicted: request_restaurant" in failed_stories
|
|
# check if there is a comment with the predicted entity on the entity line
|
|
assert "# predicted: cuisine: greek" in failed_stories
|
|
# check that the correctly predicted entity is printed as well
|
|
assert "- seating: outside\n" in failed_stories
|
|
# check that it does not double print entities
|
|
assert failed_stories.count("\n") == 9
|
|
|
|
|
|
@pytest.mark.skip_on_windows
|
|
async def test_failed_entity_extraction_comment(
|
|
tmpdir: Path, restaurantbot_agent: Agent
|
|
):
|
|
test_file = "data/test_yaml_stories/test_failed_entity_extraction_comment.yml"
|
|
stories_path = str(tmpdir / FAILED_STORIES_FILE)
|
|
|
|
await evaluate_stories(
|
|
stories=test_file,
|
|
agent=restaurantbot_agent,
|
|
out_directory=str(tmpdir),
|
|
max_stories=None,
|
|
e2e=True,
|
|
)
|
|
|
|
failed_stories = rasa.shared.utils.io.read_file(stories_path)
|
|
assert (
|
|
"- intent: request_restaurant"
|
|
" # predicted: request_restaurant: i am looking for [greek](cuisine) food"
|
|
in failed_stories
|
|
)
|