Spaces:
Build error
Build error
Validify-testbot-1
/
botbuilder-python
/libraries
/botbuilder-dialogs
/botbuilder
/dialogs
/choices
/choice_recognizers.py
| # Copyright (c) Microsoft Corporation. All rights reserved. | |
| # Licensed under the MIT License. | |
| from typing import List, Union | |
| from recognizers_number import NumberModel, NumberRecognizer, OrdinalModel | |
| from recognizers_text import Culture | |
| from .choice import Choice | |
| from .find import Find | |
| from .find_choices_options import FindChoicesOptions | |
| from .found_choice import FoundChoice | |
| from .model_result import ModelResult | |
| class ChoiceRecognizers: | |
| """Contains methods for matching user input against a list of choices.""" | |
| def recognize_choices( | |
| utterance: str, | |
| choices: List[Union[str, Choice]], | |
| options: FindChoicesOptions = None, | |
| ) -> List[ModelResult]: | |
| """ | |
| Matches user input against a list of choices. | |
| This is layered above the `Find.find_choices()` function, and adds logic to let the user specify | |
| their choice by index (they can say "one" to pick `choice[0]`) or ordinal position | |
| (they can say "the second one" to pick `choice[1]`.) | |
| The user's utterance is recognized in the following order: | |
| - By name using `find_choices()` | |
| - By 1's based ordinal position. | |
| - By 1's based index position. | |
| Parameters: | |
| ----------- | |
| utterance: The input. | |
| choices: The list of choices. | |
| options: (Optional) Options to control the recognition strategy. | |
| Returns: | |
| -------- | |
| A list of found choices, sorted by most relevant first. | |
| """ | |
| if utterance is None: | |
| utterance = "" | |
| # Normalize list of choices | |
| choices_list = [ | |
| Choice(value=choice) if isinstance(choice, str) else choice | |
| for choice in choices | |
| ] | |
| # Try finding choices by text search first | |
| # - We only want to use a single strategy for returning results to avoid issues where utterances | |
| # like the "the third one" or "the red one" or "the first division book" would miss-recognize as | |
| # a numerical index or ordinal as well. | |
| locale = options.locale if (options and options.locale) else Culture.English | |
| matched = Find.find_choices(utterance, choices_list, options) | |
| if not matched: | |
| matches = [] | |
| if not options or options.recognize_ordinals: | |
| # Next try finding by ordinal | |
| matches = ChoiceRecognizers._recognize_ordinal(utterance, locale) | |
| for match in matches: | |
| ChoiceRecognizers._match_choice_by_index( | |
| choices_list, matched, match | |
| ) | |
| if not matches and (not options or options.recognize_numbers): | |
| # Then try by numerical index | |
| matches = ChoiceRecognizers._recognize_number(utterance, locale) | |
| for match in matches: | |
| ChoiceRecognizers._match_choice_by_index( | |
| choices_list, matched, match | |
| ) | |
| # Sort any found matches by their position within the utterance. | |
| # - The results from find_choices() are already properly sorted so we just need this | |
| # for ordinal & numerical lookups. | |
| matched = sorted(matched, key=lambda model_result: model_result.start) | |
| return matched | |
| def _recognize_ordinal(utterance: str, culture: str) -> List[ModelResult]: | |
| model: OrdinalModel = NumberRecognizer(culture).get_ordinal_model(culture) | |
| return list( | |
| map(ChoiceRecognizers._found_choice_constructor, model.parse(utterance)) | |
| ) | |
| def _match_choice_by_index( | |
| choices: List[Choice], matched: List[ModelResult], match: ModelResult | |
| ): | |
| try: | |
| index: int = int(match.resolution.value) - 1 | |
| if 0 <= index < len(choices): | |
| choice = choices[index] | |
| matched.append( | |
| ModelResult( | |
| start=match.start, | |
| end=match.end, | |
| type_name="choice", | |
| text=match.text, | |
| resolution=FoundChoice( | |
| value=choice.value, index=index, score=1.0 | |
| ), | |
| ) | |
| ) | |
| except: | |
| # noop here, as in dotnet/node repos | |
| pass | |
| def _recognize_number(utterance: str, culture: str) -> List[ModelResult]: | |
| model: NumberModel = NumberRecognizer(culture).get_number_model(culture) | |
| return list( | |
| map(ChoiceRecognizers._found_choice_constructor, model.parse(utterance)) | |
| ) | |
| def _found_choice_constructor(value_model: ModelResult) -> ModelResult: | |
| return ModelResult( | |
| start=value_model.start, | |
| end=value_model.end, | |
| type_name="choice", | |
| text=value_model.text, | |
| resolution=FoundChoice( | |
| value=value_model.resolution["value"], index=0, score=1.0 | |
| ), | |
| ) | |