Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:24:47 +08:00

332 lines
11 KiB
Python

import uuid
from typing import Text, Any
import jsonschema
import pytest
from sanic import Sanic, response
from rasa.core.nlg.callback import CallbackNaturalLanguageGenerator
from rasa.core.nlg.response import TemplatedNaturalLanguageGenerator
from rasa.utils.endpoints import EndpointConfig, read_endpoint_config
from rasa.core.agent import Agent
def nlg_app(base_url="/"):
app = Sanic("test_nlg")
@app.route(base_url, methods=["POST"])
async def generate(request):
"""Simple HTTP NLG generator, checks that the incoming request
is format according to the spec."""
nlg_request_format_spec = {
"type": "object",
"properties": {
"response": {"type": "string"},
"id": {"type": ["string", "null"]},
"arguments": {"type": "object"},
"tracker": {
"type": "object",
"properties": {
"sender_id": {"type": "string"},
"slots": {"type": "object"},
"latest_message": {"type": "object"},
"latest_event_time": {"type": "number"},
"paused": {"type": "boolean"},
"events": {"type": "array"},
},
},
"channel": {
"type": "object",
"properties": {"name": {"type": "string"}},
},
},
}
nlg_call = request.json
jsonschema.validate(nlg_call, nlg_request_format_spec)
if nlg_call.get("response") == "utter_greet":
response_dict = {"text": "Hey there!"}
else:
response_dict = {"text": "Sorry, didn't get that."}
return response.json(response_dict)
return app
# noinspection PyShadowingNames
@pytest.fixture()
def http_nlg(loop, sanic_client):
return loop.run_until_complete(sanic_client(nlg_app()))
async def test_nlg(http_nlg, trained_rasa_model: Text):
sender = str(uuid.uuid1())
nlg_endpoint = EndpointConfig.from_dict({"url": http_nlg.make_url("/")})
agent = Agent.load(trained_rasa_model, generator=nlg_endpoint)
response = await agent.handle_text("/greet", sender_id=sender)
assert len(response) == 1
assert response[0] == {"text": "Hey there!", "recipient_id": sender}
def test_nlg_endpoint_config_loading(endpoints_path: Text):
cfg = read_endpoint_config(endpoints_path, "nlg")
assert cfg == EndpointConfig.from_dict({"url": "http://localhost:5055/nlg"})
def test_nlg_schema_validation():
content = {"text": "Hey there!"}
assert CallbackNaturalLanguageGenerator.validate_response(content)
def test_nlg_schema_validation_empty_buttons():
content = {"text": "Hey there!", "buttons": []}
assert CallbackNaturalLanguageGenerator.validate_response(content)
def test_nlg_schema_validation_empty_image():
content = {"text": "Hey there!", "image": None}
assert CallbackNaturalLanguageGenerator.validate_response(content)
def test_nlg_schema_validation_empty_custom_dict():
content = {"custom": {}}
assert CallbackNaturalLanguageGenerator.validate_response(content)
@pytest.mark.parametrize(
"slot_name, slot_value",
[
("tag_w_underscore", "a"),
("tag with space", "bacon"),
("tag.with.dot", "chocolate"),
("tag-w-dash", "apple pie"),
("tag-w-$", "banana"),
("tag-w-@", "one"),
("tagCamelCase", "two"),
("tag-w-*", "three"),
("tag_w_underscore", "a"),
("tag.with.float.val", 1.3),
("tag-w-$", "banana"),
("tagCamelCase", "two"),
("empty_string", ""),
("null", None),
],
)
def test_nlg_fill_response_text(slot_name: Text, slot_value: Any):
response = {"text": f"{{{slot_name}}}"}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(response=response, filled_slots={slot_name: slot_value})
assert result == {"text": str(slot_value)}
@pytest.mark.parametrize(
"img_slot_name, img_slot_value",
[("url", "https://www.exampleimg.com"), ("img1", "https://www.appleimg.com")],
)
def test_nlg_fill_response_image(img_slot_name: Text, img_slot_value: Text):
response = {"image": f"{{{img_slot_name}}}"}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response=response, filled_slots={img_slot_name: img_slot_value}
)
assert result == {"image": str(img_slot_value)}
@pytest.mark.parametrize(
"slot_name, slot_value",
[
("tag_w_underscore", "a"),
("tag with space", "bacon"),
("tag.with.dot", "chocolate"),
("tag-w-dash", "apple pie"),
("tag-w-$", "banana"),
("tag-w-@", "one"),
("tagCamelCase", "two"),
("tag-w-*", "three"),
("tag_w_underscore", "a"),
("tag.with.float.val", 1.3),
("tag-w-$", "banana"),
("tagCamelCase", "two"),
("empty_string", ""),
("null", None),
],
)
def test_nlg_fill_response_custom(slot_name: Text, slot_value: Any):
response = {
"custom": {
"field": f"{{{slot_name}}}",
"properties": {"field_prefixed": f"prefix_{{{slot_name}}}"},
"bool_field": True,
"int_field:": 42,
"empty_field": None,
}
}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(response=response, filled_slots={slot_name: slot_value})
assert result == {
"custom": {
"field": str(slot_value),
"properties": {"field_prefixed": f"prefix_{slot_value}"},
"bool_field": True,
"int_field:": 42,
"empty_field": None,
}
}
def test_nlg_fill_response_custom_with_list():
response = {
"custom": {
"blocks": [{"fields": [{"text": "*Departure date:*\n{test}"}]}],
"other": ["{test}"],
}
}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(response=response, filled_slots={"test": 5})
assert result == {
"custom": {
"blocks": [{"fields": [{"text": "*Departure date:*\n5"}]}],
"other": ["5"],
}
}
@pytest.mark.parametrize(
"response_text, expected",
[
('{{"variable":"{slot_1}"}}', '{"variable":"foo"}'),
("{slot_1} and {slot_2}", "foo and bar"),
("{{{slot_1}, {slot_2}!}}", "{foo, bar!}"),
("{{{slot_1}}}", "{foo}"),
("{{slot_1}}", "{slot_1}"),
],
)
def test_nlg_fill_response_text_with_json(response_text, expected):
response = {"text": response_text}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response=response, filled_slots={"slot_1": "foo", "slot_2": "bar"}
)
assert result == {"text": expected}
@pytest.mark.parametrize("slot_name, slot_value", [("tag_w_\n", "a")])
def test_nlg_fill_response_with_bad_slot_name(slot_name, slot_value):
response_text = f"{{{slot_name}}}"
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response={"text": response_text}, filled_slots={slot_name: slot_value}
)
assert result["text"] == response_text
@pytest.mark.parametrize(
"text_slot_name, text_slot_value, img_slot_name, img_slot_value",
[
("tag_w_underscore", "a", "url", "https://www.exampleimg.com"),
("tag with space", "bacon", "img1", "https://www.appleimg.com"),
],
)
def test_nlg_fill_response_image_and_text(
text_slot_name, text_slot_value, img_slot_name, img_slot_value
):
response = {"text": f"{{{text_slot_name}}}", "image": f"{{{img_slot_name}}}"}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response=response,
filled_slots={text_slot_name: text_slot_value, img_slot_name: img_slot_value},
)
assert result == {"text": str(text_slot_value), "image": str(img_slot_value)}
@pytest.mark.parametrize(
"text_slot_name, text_slot_value, cust_slot_name, cust_slot_value",
[
("tag_w_underscore", "a", "tag.with.dot", "chocolate"),
("tag with space", "bacon", "tag-w-dash", "apple pie"),
],
)
def test_nlg_fill_response_text_and_custom(
text_slot_name, text_slot_value, cust_slot_name, cust_slot_value
):
response = {
"text": f"{{{text_slot_name}}}",
"custom": {
"field": f"{{{cust_slot_name}}}",
"properties": {"field_prefixed": f"prefix_{{{cust_slot_name}}}"},
},
}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response=response,
filled_slots={text_slot_name: text_slot_value, cust_slot_name: cust_slot_value},
)
assert result == {
"text": str(text_slot_value),
"custom": {
"field": str(cust_slot_value),
"properties": {"field_prefixed": f"prefix_{str(cust_slot_value)}"},
},
}
@pytest.mark.parametrize(
"attach_slot_name, attach_slot_value", [("attach_file", "https://attach.pdf")]
)
def test_nlg_fill_response_attachment(attach_slot_name, attach_slot_value):
response = {"attachment": "{" + attach_slot_name + "}"}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response=response, filled_slots={attach_slot_name: attach_slot_value}
)
assert result == {"attachment": str(attach_slot_value)}
@pytest.mark.parametrize(
"button_slot_name, button_slot_value", [("button_1", "button_1")]
)
def test_nlg_fill_response_button(button_slot_name, button_slot_value):
response = {
"buttons": [
{
"payload": f'/choose{{{{"some_slot": "{{{button_slot_name}}}"}}}}',
"title": f"{{{button_slot_name}}}",
}
]
}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response=response, filled_slots={button_slot_name: button_slot_value}
)
assert result == {
"buttons": [
{
"payload": f'/choose{{"some_slot": "{button_slot_value}"}}',
"title": f"{button_slot_value}",
}
]
}
@pytest.mark.parametrize(
"quick_replies_slot_name, quick_replies_slot_value", [("qreply", "reply 1")]
)
def test_nlg_fill_response_quick_replies(
quick_replies_slot_name, quick_replies_slot_value
):
response = {"quick_replies": f"{{{quick_replies_slot_name}}}"}
t = TemplatedNaturalLanguageGenerator(responses=dict())
result = t._fill_response(
response=response,
filled_slots={quick_replies_slot_name: quick_replies_slot_value},
)
assert result == {"quick_replies": str(quick_replies_slot_value)}