New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rasanlu parser does not manage the new returned response after training request #886
Comments
I started working on a fix that detect if the returned data is a json one or a zip one. Example :From Opsdroid Side:
From Rasanlu side :
Testing the new model (intent:affirm) :
Now still 2 things to address :
Do not hesitate if you have any ideas :-) |
really, do not hesitate to comment :-) |
ok no answer :-( |
Sorry! That sounds good. |
Ok Thanks :-) |
Hi All, I Finished the fix. it's working, but i have some problem with the tox test (adding tests to test_parser_rasanlu.py).
I am not a gourou of tox, so can someone assist with that please Fixed Function : async def train_rasanlu(config, skills):
"""Train a Rasa NLU model based on the loaded skills."""
_LOGGER.info(_("Starting Rasa NLU training."))
intents = await _get_all_intents(skills)
if intents is None:
_LOGGER.warning(_("No intents found, skipping training."))
return False
config["model"] = await _get_intents_fingerprint(intents)
if config["model"] in await _get_existing_models(config):
_LOGGER.info(_("This model already exists, skipping training..."))
await _init_model(config)
return True
async with aiohttp.ClientSession() as session:
_LOGGER.info(_("Now training the model. This may take a while..."))
url = await _build_training_url(config)
# https://github.com/RasaHQ/rasa_nlu/blob/master/docs/http.rst#post-train
# Note : The request should always be sent as
# application/x-yml regardless of wether you use
# json or md for the data format. Do not send json as
# application/json for example.+
headers = {"content-type": "application/x-yml"}
try:
training_start = arrow.now()
resp = await session.post(url, data=intents, headers=headers)
except aiohttp.client_exceptions.ClientConnectorError:
_LOGGER.error(_("Unable to connect to Rasa NLU, training failed."))
return False
if resp.status == 200:
if resp.content_type == "application/json":
result = await resp.json()
if "info" in result and "new model trained" in result["info"]:
time_taken = (arrow.now() - training_start).total_seconds()
_LOGGER.info(_("Rasa NLU training completed in %s seconds."),
int(time_taken))
await _init_model(config)
return True
_LOGGER.debug(result)
if resp.content_type == "application/zip" and resp.content_disposition.type == "attachment":
time_taken = (arrow.now() - training_start).total_seconds()
_LOGGER.info(_("Rasa NLU training completed in %s seconds."),
int(time_taken))
await _init_model(config)
# As inditated in the issue #886, returned zip file is ignored, this can be changed
# This can be changed in future release if needed
# Saving model.zip file example :
# try:
# output_file = open("/target/directory/model.zip","wb")
# data = await resp.read()
# output_file.write(data)
# output_file.close()
# _LOGGER.debug("Rasa taining model file saved to /target/directory/model.zip")
# except:
# _LOGGER.error("Cannot save rasa taining model file to /target/directory/model.zip")
return True
_LOGGER.error(_("Bad Rasa NLU response - %s"), await resp.text())
_LOGGER.error(_("Rasa NLU training failed."))
return False Now the test should include when returned response is a zip file and when a returned response is a json dict Thanks |
Its hard to tell without seeing the whole test. But my guess would be that you need to set the content type of |
Hi, async def test_train_rasanlu(self):
result = amock.Mock()
result.status = 404
result.text = amock.CoroutineMock()
result.json = amock.CoroutineMock()
result.json.return_value = {"info": "new model trained: abc123"}
with amock.patch(
"aiohttp.ClientSession.post"
) as patched_request, amock.patch.object(
rasanlu, "_get_all_intents"
) as mock_gai, amock.patch.object(
rasanlu, "_init_model"
) as mock_im, amock.patch.object(
rasanlu, "_build_training_url"
) as mock_btu, amock.patch.object(
rasanlu, "_get_existing_models"
) as mock_gem, amock.patch.object(
rasanlu, "_get_intents_fingerprint"
) as mock_gif:
mock_gai.return_value = None
self.assertEqual(await rasanlu.train_rasanlu({}, {}), False)
mock_gai.return_value = "Hello World"
mock_gem.return_value = ["abc123"]
mock_gif.return_value = "abc123"
self.assertEqual(await rasanlu.train_rasanlu({}, {}), True)
self.assertTrue(mock_im.called)
self.assertFalse(mock_btu.called)
mock_gem.return_value = []
mock_btu.return_value = "http://example.com"
patched_request.side_effect = aiohttp.client_exceptions.ClientConnectorError(
"key", amock.Mock()
)
self.assertEqual(await rasanlu.train_rasanlu({}, {}), False)
patched_request.side_effect = None
patched_request.return_value = asyncio.Future()
patched_request.return_value.set_result(result)
self.assertEqual(await rasanlu.train_rasanlu({}, {}), False)
result.status = 200
patched_request.return_value = asyncio.Future()
patched_request.return_value.set_result(result)
self.assertEqual(await rasanlu.train_rasanlu({}, {}), True)
result.json.return_value = {"info": "error"}
patched_request.return_value = asyncio.Future()
patched_request.return_value.set_result(result)
self.assertEqual(await rasanlu.train_rasanlu({}, {}), False) During my tests i tried to adapt it by adding result.status = 200
result.content_type == "application/zip"
result.content_disposition == "attachment"
result.json.return_value = {'Content-Type': 'application/zip', 'Content-Disposition': 'attachment'}
patched_request.return_value = asyncio.Future()
patched_request.return_value.set_result(result)
self.assertEqual(await rasanlu.train_rasanlu({}, {}), True) but the problem still the same |
Hmm strange. It might good for you to raise a PR at this point. Then we can see the tests fail in Travis and dig a little deeper. Also makes testing locally a bit easier. |
Ok thanks for your help |
Description
This issue was initially detected by @jhofeditz when testing the fix #881.
The new rasanlu trainer instead of returning a json response after a model training, it return a zip file with all files generated by the trainer.
Steps to Reproduce
1- Download docker image rasa/rasa_nlu:latest-spacy
2- Start docker image
3- Use a skill that interact with rasanlu and that need rasa to be trained using an intents.yml file
4- activate the skill in your opsdroid config file
5- Start opsdroid
Expected Functionality
Opsdroid should be capable to manage json response and zip response
Experienced Functionality
Crash of opsdroid due to parsing error
Versions
Additional Details
From Rasa side :
From Opsdroid side :
The text was updated successfully, but these errors were encountered: