How to extract entity with one name for 2 different slots?

Hello! What the correct way to handle this case?

User says: “show me schedule from Berlin to Paris”

My NLU.md configured like this:

nlu.md
## intent:schedule
- show me schedule from [Berlin](city) to [Paris](city)

My action.py configured like this:

actions.py
    def slot_mappings(self):
        return {'city_from': [self.from_entity(entity='city', intent=['inform', 'schedule']),
                           self.from_text(not_intent='deny')],
                'city_to': [self.from_entity(entity='city', intent=['inform', 'schedule']),
                           self.from_text(not_intent='deny')]}

The problem: When I try to parse this text (localhost:5005/model/parse), Rasa can only recognize last entity “city” from input text:

Rasa reply
    {
  "intent": {
    "name": "schedule",
    "confidence": 0.9627386927604675
  },
  "entities": [
    {
      "start": **,
      "end": **,
      "value": "berlin",
      "entity": "city",
      "confidence": 0.9954288875630625,
      "extractor": "CRFEntityExtractor",
    }
  ]
...
}

Same problem with FormAction, even recognized entity ‘city’ did not filled slot ‘city_from’:

log from Core
2019-09-05 14:32:48 DEBUG    rasa.core.processor  - Received user message 'show me schedule from Berlin to Paris' with intent '{'name': 'schedule', 'confidence': 0.9627386927604675}' and entities '[{'start': **, 'end': **, 'value': 'Paris', 'entity': 'city',
 'confidence': 0.9954288875630625, 'extractor': 'CRFEntityExtractor'}]'
log from Action
2019-09-05 14:32:38 DEBUG    rasa_sdk.forms  - Trying to extract requested slot 'city_from' ...
2019-09-05 14:32:38 DEBUG    rasa_sdk.forms  - Got mapping '{'type': 'from_entity', 'entity': 'city', 'intent': ['inform', 'schedule'], 'not_intent': []}'
2019-09-05 14:32:38 DEBUG    rasa_sdk.forms  - Got mapping '{'type': 'from_text', 'intent': [], 'not_intent': ['deny']}'
2019-09-05 14:32:38 DEBUG    rasa_sdk.forms  - Failed to extract requested slot 'city_from'
2019-09-05 14:32:38 ERROR    rasa_sdk.endpoint  - Failed to extract slot city_from with action schedule_form

What the correct way of extracting same entity for two slots?

If the EntityExtractors recognizes both cities as entities, they will end up as a list in the validate_{slot_name} method. From there you may return any number of SlotSet-events.

@selphe: as you are extracting cities with the CRFEntityExtractor, you must provide enough example intents that have more than one city in the training data. How many examples do you have in ## intent:schedule (or in other intents that use the city entity)?

Then, to assign them to the ‘city_from’ and ‘city_to’, I agree with @IgNoRaNt23. What is the question that you are asking in your form? You could customize validate_city_from and validate_city_to so that you can return both city_from and city_to if both are provided.

See: Forms

Just following up @IgNoRaNt23 and @nbeuchat on the best way to model this problem as I have the same issue.

Most of the similar threads have recommended writing some logic in a form action. By this, I assume I would poke around and look for predicates like “from”, “to”, “between” and also look at existing slots and previous bot utterance, etc. It would probably work ok.

Another possibility would just be to define two entities: from_city and to_city and define the same lookup data for them twice. Then training examples might be:

That way the I can rely on training for patterns instead of writing a bunch of code for that. I guess the problem is that the user could just enter: “NYC” And in this case, there would have to be some form action code to determine if current context is from or to.

Is there a better way to think about this?

@mmm3bbb I think it’s a great approach!

I’m not even sure if you need to create the lookup twice. It might be enough to do it once as the lookup will create a bunch of regexes that would match both city_from and city_to in the training data. Therefore, I believe it would help both the extraction of city_from and city_to. Don’t take my word from it though and test :wink: That’s just how I understood lookups to work

How would I avoid creating the lookup twice? I was thinking I can dump the names into a file and just refer to same file:

lookup:from_city

data/lookup_tables/cities.txt

lookup:to_city

data/lookup_tables/cities.txt

In the case where the user just enters the city name with no extra text that would make it obvious to extract as to_city or from_city, then it just assign to one of those and I’d need to look at the most recent bot utterance to determine what slot to put it into.

Does that sound right?

What you wrote will work.

Don’t quote me on this but I belive that you can also have a single lookup:

## lookup:city
data/lookup_tables/cities.txt

This lookup will create a regex that will match both the from_cityand to_city entities that you have in your training data. Therefore, both will use this lookup in the end.

If someone from Rasa could confirm that’d be nice :slight_smile:

Yeah, I don’t understand how rasa would know to associate the ‘city’ regex with ‘from_city’ and ‘to_city’? That seems like it would require magic.