Skip to content

Commit e703bb1

Browse files
authored
Merge pull request #2 from rvinothrajendran/master
#1 Added numberwithunitprompt.py & numberwithtype_prompt.py file. Addresses #3 as well.
2 parents c82e5b9 + ffd4f5e commit e703bb1

File tree

5 files changed

+440
-0
lines changed

5 files changed

+440
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from numberwithunit_prompt import (
2+
NumberWithUnitPrompt,
3+
NumberWithUnitPromptType,
4+
NumberWithUnitResult,
5+
NumberWithTypePromptType,
6+
NumberWithTypePrompt)
7+
8+
__all__ = [
9+
"NumberWithUnitPrompt",
10+
"NumberWithUnitPromptType",
11+
"NumberWithUnitResult",
12+
"NumberWithTypePromptType",
13+
"NumberWithTypePrompt"
14+
]
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from botbuilder.dialogs.prompts import Prompt, PromptOptions, PromptRecognizerResult
2+
from botbuilder.core.turn_context import TurnContext
3+
from botbuilder.schema import ActivityTypes
4+
from recognizers_number import NumberRecognizer
5+
from recognizers_text import Culture, ModelResult
6+
from typing import Callable, Dict
7+
import enum
8+
9+
class NumberWithTypePromptType(enum.Enum):
10+
Ordinal = 0,
11+
Percentage = 1
12+
13+
14+
class NumberWithTypePrompt(Prompt):
15+
def __init__(
16+
self,
17+
dialog_id,
18+
prompt_type : NumberWithTypePromptType,
19+
validator: object = None,
20+
default_locale = None
21+
):
22+
super().__init__(dialog_id, validator)
23+
24+
if default_locale is None:
25+
default_locale = Culture.English
26+
27+
self._default_locale = default_locale
28+
self._prompt_type = prompt_type
29+
30+
async def on_prompt(
31+
self,
32+
turn_context: TurnContext,
33+
state: Dict[str, object],
34+
options: PromptOptions,
35+
is_retry: bool,
36+
):
37+
if not turn_context:
38+
raise TypeError("turn_context can’t be none")
39+
if not options:
40+
raise TypeError("options can’t be none")
41+
42+
if is_retry and options.retry_prompt is not None:
43+
await turn_context.send_activity(options.retry_prompt)
44+
else:
45+
if options.prompt is not None:
46+
await turn_context.send_activity(options.prompt)
47+
48+
async def on_recognize(
49+
self,
50+
turn_context: TurnContext,
51+
state: Dict[str, object],
52+
options: PromptOptions,
53+
) -> PromptRecognizerResult:
54+
if not turn_context:
55+
raise TypeError("turn_context can’t be none")
56+
57+
if turn_context.activity.type == ActivityTypes.message:
58+
utterance = turn_context.activity.text
59+
60+
turn_context.activity.locale = self._default_locale
61+
62+
recognizer_result = PromptRecognizerResult()
63+
64+
recognizer = NumberRecognizer(turn_context.activity.locale)
65+
66+
if (self._prompt_type == NumberWithTypePromptType.Ordinal):
67+
model = recognizer.get_ordinal_model()
68+
elif (self._prompt_type == NumberWithTypePromptType.Percentage):
69+
model = recognizer.get_percentage_model()
70+
71+
model_result = model.parse(utterance)
72+
if len(model_result) > 0 and len(model_result[0].resolution) > 0:
73+
recognizer_result.succeeded = True
74+
recognizer_result.value = model_result[0].resolution["value"]
75+
76+
return recognizer_result
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
from botbuilder.dialogs.prompts import Prompt, PromptOptions, PromptRecognizerResult
2+
from botbuilder.core.turn_context import TurnContext
3+
from botbuilder.schema import ActivityTypes
4+
from recognizers_number_with_unit import NumberWithUnitRecognizer
5+
from recognizers_text import Culture, ModelResult
6+
from typing import Callable, Dict
7+
import enum
8+
9+
class NumberWithUnitPromptType(enum.Enum):
10+
Currency = 0
11+
Temperature = 1
12+
Age = 2
13+
Dimension = 3
14+
15+
class NumberWithUnitResult:
16+
def __init__(self, unit , value ):
17+
self._unit = unit
18+
self._value = value
19+
20+
@property
21+
def unit(self):
22+
return self._unit
23+
@property
24+
def value(self):
25+
return self._value
26+
27+
28+
class NumberWithUnitPrompt(Prompt):
29+
def __init__(
30+
self,
31+
dialog_id,
32+
prompt_type: NumberWithUnitPromptType,
33+
validator: object = None,
34+
default_locale = None
35+
):
36+
super().__init__(dialog_id, validator)
37+
38+
if default_locale is None:
39+
default_locale = Culture.English
40+
41+
self._default_locale = default_locale
42+
self._prompt_type = prompt_type
43+
44+
async def on_prompt(
45+
self,
46+
turn_context: TurnContext,
47+
state: Dict[str, object],
48+
options: PromptOptions,
49+
is_retry: bool,
50+
):
51+
if not turn_context:
52+
raise TypeError("turn_context can’t be none")
53+
if not options:
54+
raise TypeError("options can’t be none")
55+
56+
if is_retry and options.retry_prompt is not None:
57+
await turn_context.send_activity(options.retry_prompt)
58+
else:
59+
if options.prompt is not None:
60+
await turn_context.send_activity(options.prompt)
61+
62+
async def on_recognize(
63+
self,
64+
turn_context: TurnContext,
65+
state: Dict[str, object],
66+
options: PromptOptions,
67+
) -> PromptRecognizerResult:
68+
if not turn_context:
69+
raise TypeError("turn_context can’t be none")
70+
71+
if turn_context.activity.type == ActivityTypes.message:
72+
utterance = turn_context.activity.text
73+
74+
turn_context.activity.locale = self._default_locale
75+
76+
recognizer_result = PromptRecognizerResult()
77+
78+
recognizer = NumberWithUnitRecognizer(turn_context.activity.locale)
79+
80+
if self._prompt_type == NumberWithUnitPromptType.Age:
81+
model = recognizer.get_age_model()
82+
elif self._prompt_type == NumberWithUnitPromptType.Currency:
83+
model = recognizer.get_currency_model()
84+
elif self._prompt_type == NumberWithUnitPromptType.Dimension:
85+
model = recognizer.get_dimension_model()
86+
elif self._prompt_type == NumberWithUnitPromptType.Temperature:
87+
model = recognizer.get_temperature_model()
88+
89+
model_result = model.parse(utterance)
90+
91+
if len(model_result) > 0 and len(model_result[0].resolution) > 1:
92+
recognizer_result.succeeded = True
93+
recognizer_result.value = NumberWithUnitResult(
94+
model_result[0].resolution["unit"],
95+
model_result[0].resolution["value"]
96+
)
97+
98+
return recognizer_result
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import sys
2+
import pathlib
3+
import pytest
4+
import aiounittest
5+
import asyncio
6+
7+
current = pathlib.Path(__file__).parent.parent
8+
libpath = current.joinpath("source")
9+
sys.path.append(str(libpath))
10+
11+
from botbuilder.dialogs.prompts import (
12+
AttachmentPrompt,
13+
PromptOptions,
14+
PromptValidatorContext,
15+
)
16+
17+
from botbuilder.core import (
18+
TurnContext,
19+
ConversationState,
20+
MemoryStorage,
21+
MessageFactory,
22+
)
23+
24+
from botbuilder.schema import Activity, ActivityTypes, Attachment
25+
from botbuilder.core.adapters import TestAdapter
26+
from botbuilder.dialogs import DialogSet, DialogTurnStatus
27+
from number_with_type_prompt import NumberWithTypePrompt, NumberWithTypePromptType
28+
29+
class NumberWithTypeOrdinalPromptTests(aiounittest.AsyncTestCase):
30+
async def test_ordinal_prompt(self):
31+
async def exec_test(turn_context:TurnContext):
32+
dialog_context = await dialogs.create_context(turn_context)
33+
34+
results = await dialog_context.continue_dialog()
35+
if results.status == DialogTurnStatus.Empty:
36+
options = PromptOptions(
37+
prompt = Activity(
38+
type = ActivityTypes.message,
39+
text = "test the ordinalnumber type api"
40+
)
41+
)
42+
await dialog_context.prompt("ordinal_number_prompt", options)
43+
elif results.status == DialogTurnStatus.Complete:
44+
reply = results.result
45+
await turn_context.send_activity(reply)
46+
47+
await conv_state.save_changes(turn_context)
48+
49+
adapter = TestAdapter(exec_test)
50+
51+
conv_state = ConversationState(MemoryStorage())
52+
53+
dialog_state = conv_state.create_property("dialog-state")
54+
dialogs = DialogSet(dialog_state)
55+
dialogs.add(NumberWithTypePrompt("ordinal_number_prompt", NumberWithTypePromptType.Ordinal))
56+
57+
step1 = await adapter.test('Hello', 'test the ordinalnumber type api')
58+
step2 = await step1.send('tenth')
59+
await step2.assert_reply("10")
60+
61+
62+
class NumberWithPercentagePrompt(aiounittest.AsyncTestCase):
63+
async def test_percentage_prompt(self):
64+
async def exec_test(turn_context:TurnContext):
65+
dialog_context = await dialogs.create_context(turn_context)
66+
67+
results = await dialog_context.continue_dialog()
68+
69+
if results.status == DialogTurnStatus.Empty:
70+
options = PromptOptions(
71+
prompt = Activity(
72+
type = ActivityTypes.message,
73+
text = "test the percentage type api"
74+
)
75+
)
76+
await dialog_context.prompt("percentagePrompt", options)
77+
elif results.status == DialogTurnStatus.Complete:
78+
reply = results.result
79+
await turn_context.send_activity(reply)
80+
81+
await conv_state.save_changes(turn_context)
82+
83+
adapter = TestAdapter(exec_test)
84+
85+
conv_state = ConversationState(MemoryStorage())
86+
87+
dialog_state = conv_state.create_property("dialog-state")
88+
dialogs = DialogSet(dialog_state)
89+
dialogs.add(NumberWithTypePrompt("percentagePrompt", NumberWithTypePromptType.Percentage))
90+
91+
step1 = await adapter.test('percentagePrompt', 'test the percentage type api')
92+
step2 = await step1.send('two hundred percents')
93+
await step2.assert_reply("200%")

0 commit comments

Comments
 (0)