8000 Merge pull request #148 from Microsoft/work-in-progress · rsliang/botbuilder-python@274663d · GitHub
[go: up one dir, main page]

Skip to content

Commit 274663d

Browse files
authored
Merge pull request microsoft#148 from Microsoft/work-in-progress
Feature parity with C# and JS
2 parents 101cec3 + e76ada4 commit 274663d

File tree

166 files changed

+11901
-346
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

166 files changed

+11901
-346
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
from .about import __title__, __version__
5+
6+
__all__ = ["__title__", "__version__"]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
import os
5+
6+
__title__ = 'botbuilder-ai'
7+
__version__ = os.environ["packageVersion"] if "packageVersion" in os.environ else "4.0.0.a6"
8+
__uri__ = 'https://www.github.com/Microsoft/botbuilder-python'
9+
__author__ = 'Microsoft'
10+
__description__ = 'Microsoft Bot Framework Bot Builder'
11+
__summary__ = 'Microsoft Bot Framework Bot Builder SDK for Python.'
12+
__license__ = 'MIT'
Lines changed: 19 additions & 0 deletions
< 10000 td data-grid-cell-id="diff-c8ae55b10ae85b7ba9b4e91e4a9babce5c814e0fdd73a21d1fe1a5210b189b54-empty-19-0" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionNum-bgColor, var(--diffBlob-addition-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
from .intent_score import IntentScore
5+
from .luis_application import LuisApplication
6+
from .luis_prediction_options import LuisPredictionOptions
7+
from .luis_telemetry_constants import LuisTelemetryConstants
8+
from .recognizer_result import RecognizerResult, TopIntent
9+
from .luis_recognizer import LuisRecognizer
10+
11+
__all__ = [
12+
"IntentScore",
13+
"LuisApplication",
14+
"LuisPredictionOptions",
15+
"LuisRecognizer",
16+
"LuisTelemetryConstants",
17+
"RecognizerResult",
18+
"TopIntent",
19+
]
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
from datetime import datetime
5+
6+
from botbuilder.schema import (
7+
Activity,
8+
ActivityTypes,
9+
ChannelAccount,
10+
ConversationAccount,
11+
)
12+
13+
14+
class ActivityUtil(object):
15+
@staticmethod
16+
def create_trace(
17+
turn_activity: Activity,
18+
name: str,
19+
value: object = None,
20+
value_type: str = None,
21+
label: str = None,
22+
) -> Activity:
23+
"""Creates a trace activity based on this activity.
24+
25+
:param turn_activity:
26+
:type turn_activity: Activity
27+
:param name: The value to assign to the trace activity's <see cref="Activity.name"/> property.
28+
:type name: str
29+
:param value: The value to assign to the trace activity's <see cref="Activity.value"/> property., defaults to None
30+
:param value: object, optional
31+
:param value_type: The value to assign to the trace activity's <see cref="Activity.value_type"/> property, defaults to None
32+
:param value_type: str, optional
33+
:param label: The value to assign to the trace activity's <see cref="Activity.label"/> property, defaults to None
34+
:param label: str, optional
35+
:return: The created trace activity.
36+
:rtype: Activity
37+
"""
38+
39+
from_property = (
40+
ChannelAccount(
41+
id=turn_activity.recipient.id, name=turn_activity.recipient.name
42+
)
43+
if turn_activity.recipient is not None
44+
else ChannelAccount()
45+
)
46+
if value_type is None and value is not None:
47+
value_type = type(value).__name__
48+
49+
reply = Activity(
50+
type=ActivityTypes.trace,
51+
timestamp=datetime.utcnow(),
52+
from_property=from_property,
53+
recipient=ChannelAccount(
54+
id=turn_activity.from_property.id, name=turn_activity.from_property.name
55+
),
56+
reply_to_id=turn_activity.id,
57+
service_url=turn_activity.service_url,
58+
channel_id=turn_activity.channel_id,
59+
conversation=ConversationAccount(
60+
is_group=turn_activity.conversation.is_group,
61+
id=turn_activity.conversation.id,
62+
name=turn_activity.conversation.name,
63+
),
64+
name=name,
65+
label=label,
66+
value_type=value_type,
67+
value=value,
68+
)
69+
return reply
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
from typing import Dict
5+
6+
7+
class IntentScore(object):
8+
"""
9+
Score plus any extra information about an intent.
10+
"""
11+
12+
def __init__(self, score: float = None, properties: Dict[str, object] = {}):
13+
self._score: float = score
14+
self._properties: Dict[str, object] = properties
15+
16+
@property
17+
def score(self) -> float:
18+
"""Gets confidence in an intent.
19+
20+
:return: Confidence in an intent.
21+
:rtype: float
22+
"""
23+
24+
return self._score
25+
26+
@score.setter
27+
def score(self, value: float) -> None:
28+
"""Sets confidence in an intent.
29+
30+
:param value: Confidence in an intent.
31+
:type value: float
32+
:return:
33+
:rtype: None
34+
"""
35+
36+
self._score = value
37+
38+
@property
39+
def properties(self) -> Dict[str, object]:
40+
"""Gets any extra properties to include in the results.
41+
42+
:return: Any extra properties to include in the results.
43+
:rtype: Dict[str, object]
44+
"""
45+
46+
return self._properties
47+
48+
@properties.setter
49+
def properties(self, value: Dict[str, object]) -> None:
50+
"""Sets any extra properties to include in the results.
51+
52+
:param value: Any extra properties to include in the results.
53+
:type value: Dict[str, object]
54+
:return:
55+
:rtype: None
56+
"""
57+
58+
self._properties = value
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
# Licensed under the MIT license.
3+
4+
from pathlib import PurePosixPath
5+
from typing import Tuple
6+
from urllib.parse import ParseResult, parse_qs, unquote, urlparse, urlunparse
7+
from uuid import UUID, uuid4
8+
9+
10+
class LuisApplication(object):
11+
"""
12+
Data describing a LUIS application.
13+
"""
14+
15+
def __init__(self, application_id: str, endpoint_key: str, endpoint: str):
16+
"""Initializes a new instance of the <see cref="LuisApplication"/> class.
17+
18+
:param application_id: LUIS application ID.
19+
:type application_id: str
20+
:param endpoint_key: LUIS subscription or endpoint key.
21+
:type endpoint_key: str
22+
:param endpoint: LUIS endpoint to use like https://westus.api.cognitive.microsoft.com.
23+
:type endpoint: str
24+
:raises ValueError:
25+
:raises ValueError:
26+
:raises ValueError:
27+
"""
28+
29+
_, valid = LuisApplication._try_parse_uuid4(application_id)
30+
if not valid:
31+
raise ValueError(f'"{application_id}" is not a valid LUIS application id.')
32+
33+
_, valid = LuisApplication._try_parse_uuid4(endpoint_key)
34+
if not valid:
35+
raise ValueError(f'"{endpoint_key}" is not a valid LUIS subscription key.')
36+
37+
if not endpoint or endpoint.isspace():
38+
10000 endpoint = "https://westus.api.cognitive.microsoft.com"
39+
40+
_, valid = LuisApplication._try_parse_url(endpoint)
41+
if not valid:
42+
raise ValueError(f'"{endpoint}" is not a valid LUIS endpoint.')
43+
44+
self._application_id = application_id
45+
self._endpoint_key = endpoint_key
46+
self._endpoint = endpoint
47+
48+
@classmethod
49+
def from_application_endpoint(cls, application_endpoint: str):
50+
"""Initializes a new instance of the <see cref="LuisApplication"/> class.
51+
52+
:param application_endpoint: LUIS application endpoint.
53+
:type application_endpoint: str
54+
:return:
55+
:rtype: LuisApplication
56+
"""
57+
(application_id, endpoint_key, endpoint) = LuisApplication._parse(
58+
application_endpoint
59+
)
60+
return cls(application_id, endpoint_key, endpoint)
61+
62+
@property
63+
def application_id(self) -> str:
64+
"""Gets LUIS application ID.
65+
66+
:return: LUIS application ID.
67+
:rtype: str
68+
"""
69+
70+
return self._application_id
71+
72+
@application_id.setter
73+
def application_id(self, value: str) -> None:
74+
"""Sets LUIS application ID.
75+
76+
:param value: LUIS application ID.
77+
:type value: str
78+
:return:
79+
:rtype: None
80+
"""
81+
82+
self._application_id = value
83+
84+
@property
85+
def endpoint_key(self) -> str:
86+
"""Gets LUIS subscription or endpoint key.
87+
88+
:return: LUIS subscription or endpoint key.
89+
:rtype: str
90+
"""
91+
92+
return self._endpoint_key
93+
94+
@endpoint_key.setter
95+
def endpoint_key(self, value: str) -> None:
96+
"""Sets LUIS subscription or endpoint key.
97+
98+
:param value: LUIS subscription or endpoint key.
99+
:type value: str
100+
:return:
101+
:rtype: None
102+
"""
103+
104+
self._endpoint_key = value
105+
106+
@property
107+
def endpoint(self) -> str:
108+
"""Gets LUIS endpoint like https://westus.api.cognitive.microsoft.com.
109+
110+
:return: LUIS endpoint where application is hosted.
111+
:rtype: str
112+
"""
113+
114+
return self._endpoint
115+
116+
@endpoint.setter
117+
def endpoint(self, value: str) -> None:
118+
"""Sets LUIS endpoint like https://westus.api.cognitive.microsoft.com.
119+
120+
:param value: LUIS endpoint where application is hosted.
121+
:type value: str
122+
:return:
123+
:rtype: None
124+
"""
125+
126+
self._endpoint = value
127+
128+
@staticmethod
129+
def _parse(application_endpoint: str) -> Tuple[str, str, str]:
130+
url, valid = LuisApplication._try_parse_url(application_endpoint)
131+
if not valid:
132+
raise ValueError(
133+
f"{application_endpoint} is not a valid LUIS application endpoint."
134+
)
135+
136+
segments = PurePosixPath(unquote(url.path)).parts
137+
application_id = segments[-1] if segments else None
138+
qs_parsed_result = parse_qs(url.query)
139+
endpoint_key = qs_parsed_result.get("subscription-key", [None])[0]
140+
141+
parts_for_base_url = url.scheme, url.netloc, "", None, None, None
142+
endpoint = urlunparse(parts_for_base_url)
143+
return (application_id, endpoint_key, endpoint)
144+
145+
@staticmethod
146+
def _try_parse_uuid4(uuid_string: str) -> Tuple[uuid4, bool]:
147+
try:
148+
uuid = UUID(uuid_string, version=4)
149+
except (TypeError, ValueError):
150+
return None, False
151+
152+
return uuid, True
153+
154+
@staticmethod
155+
def _try_parse_url(url: str) -> Tuple[ParseResult, bool]:
156+
try:
157+
result = urlparse(url)
158+
return result, True
159+
except ValueError:
160+
return None, False

0 commit comments

Comments
 (0)
0