8000 [QnAMaker] GetAnswerRaw added (#316) · guidotorresmx/botbuilder-python@27c0e18 · GitHub
[go: up one dir, main page]

Skip to content

Commit 27c0e18

Browse files
gurvsingaxelsrz
authored andcommitted
[QnAMaker] GetAnswerRaw added (microsoft#316)
* [QnAMaker] GetAnswerRaw added * Making a new function with QueryResults and putting old function in obsolete mode.
1 parent 2b4707f commit 27c0e18

File tree

6 files changed

+114
-16
lines changed

6 files changed

+114
-16
lines changed

libraries/botbuilder-ai/botbuilder/ai/qna/models/query_results.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,29 @@
22
# Licensed under the MIT License.
33

44
from typing import List
5-
5+
from msrest.serialization import Model
66
from .query_result import QueryResult
77

88

9-
class QueryResults:
9+
class QueryResults(Model):
1010
""" Contains answers for a user query. """
1111

12-
def __init__(self, answers: List[QueryResult]):
12+
_attribute_map = {
13+
"answers": {"key": "answers", "type": "[QueryResult]"},
14+
"active_learning_enabled": {"key": "activeLearningEnabled", "type": "bool"},
15+
}
16+
17+
def __init__(
18+
self, answers: List[QueryResult], active_learning_enabled: bool = None, **kwargs
19+
):
1320
"""
1421
Parameters:
1522
-----------
1623
1724
answers: The answers for a user query.
25+
26+
active_learning_enabled: The active learning enable flag.
1827
"""
28+
super(QueryResults, self).__init__(**kwargs)
1929
self.answers = answers
30+
self.active_learning_enabled = active_learning_enabled

libraries/botbuilder-ai/botbuilder/ai/qna/qnamaker.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from botbuilder.schema import Activity
99
from botbuilder.core import BotTelemetryClient, NullTelemetryClient, TurnContext
1010

11-
from .models import FeedbackRecord, QueryResult
11+
from .models import FeedbackRecord, QueryResult, QueryResults
1212
from .utils import (
1313
ActiveLearningUtils,
1414
GenerateAnswerUtils,
@@ -86,6 +86,30 @@ async def get_answers(
8686
------
8787
List[QueryResult]
8888
"""
89+
result = await self.get_answers_raw(
90+
context, options, telemetry_properties, telemetry_metrics
91+
)
92+
93+
return result.answers
94+
95+
async def get_answers_raw(
96+
self,
97+
context: TurnContext,
98+
options: QnAMakerOptions = None,
99+
telemetry_properties: Dict[str, str] = None,
100+
telemetry_metrics: Dict[str, int] = None,
101+
) -> QueryResults:
102+
"""
103+
Generates raw answers from the knowledge base.
104+
105+
return:
106+
-------
107+
A list of answers for the user's query, sorted in decreasing order of ranking score.
108+
109+
rtype:
110+
------
111+
QueryResults
112+
"""
89113
if not context:
90114
raise TypeError("QnAMaker.get_answers(): context cannot be None.")
91115

@@ -94,10 +118,10 @@ async def get_answers(
94118
"QnAMaker.get_answers(): TurnContext's activity must be an Activity instance."
95119
)
96120

97-
result = await self._generate_answer_helper.get_answers(context, options)
121+
result = await self._generate_answer_helper.get_answers_raw(context, options)
98122

99123
await self.on_qna_result(
100-
result, context, telemetry_properties, telemetry_metrics
124+
result.answers, context, telemetry_properties, telemetry_metrics
101125
)
102126

103127
return result

libraries/botbuilder-ai/botbuilder/ai/qna/utils/generate_answer_utils.py

Lines changed: 29 additions 10000 & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@
1313

1414
from ..qnamaker_endpoint import QnAMakerEndpoint
1515
from ..qnamaker_options import QnAMakerOptions
16-
from ..models import GenerateAnswerRequestBody, QnAMakerTraceInfo, QueryResult
16+
from ..models import (
17+
GenerateAnswerRequestBody,
18+
QnAMakerTraceInfo,
19+
QueryResult,
20+
QueryResults,
21+
)
1722

1823
QNAMAKER_TRACE_NAME = "QnAMaker"
1924
QNAMAKER_TRACE_LABEL = "QnAMaker Trace"
@@ -58,6 +63,13 @@ def __init__(
5863
async def get_answers(
5964
self, context: TurnContext, options: QnAMakerOptions = None
6065
) -> List[QueryResult]:
66+
result: QueryResults = await self.get_answers_raw(context, options)
67+
68+
return result
69+
70+
async def get_answers_raw(
71+
self, context: TurnContext, options: QnAMakerOptions = None
72+
) -> QueryResults:
6173
if not isinstance(context, TurnContext):
6274
raise TypeError(
6375
"GenerateAnswerUtils.get_answers(): context must be an instance of TurnContext"
@@ -66,11 +78,9 @@ async def get_answers(
6678
hydrated_options = self._hydrate_options(options)
6779
self._validate_options(hydrated_options)
6880

69-
result: List[QueryResult] = await self._query_qna_service(
70-
context, hydrated_options
71-
)
81+
result: QueryResults = await self._query_qna_service(context, hydrated_options)
7282

73-
await self._emit_trace_info(context, result, hydrated_options)
83+
await self._emit_trace_info(context, result.answers, hydrated_options)
7484

7585
return result
7686

@@ -134,7 +144,7 @@ def _ 10000 hydrate_options(self, query_options: QnAMakerOptions) -> QnAMakerOptions:
134144

135145
async def _query_qna_service(
136146
self, turn_context: TurnContext, options: QnAMakerOptions
137-
) -> List[QueryResult]:
147+
) -> QueryResults:
138148
url = f"{ self._endpoint.host }/knowledgebases/{ self._endpoint.knowledge_base_id }/generateAnswer"
139149

140150
question = GenerateAnswerRequestBody(
@@ -152,7 +162,7 @@ async def _query_qna_service(
152162
url, question, self._endpoint, options.timeout
153163
)
154164

155-
result: List[QueryResult] = await self._format_qna_result(response, options)
165+
result: QueryResults = await self._format_qna_result(response, options)
156166

157167
return result
158168

@@ -182,7 +192,7 @@ async def _emit_trace_info(
182192

183193
async def _format_qna_result(
184194
self, result, options: QnAMakerOptions
185-
) -> List[QueryResult]:
195+
) -> QueryResults:
186196
json_res = result
187197
if isinstance(result, ClientResponse):
188198
json_res = await result.json()
@@ -200,4 +210,14 @@ async def _format_qna_result(
200210
map(lambda answer: QueryResult(**answer), sorted_answers)
201211
)
202212

203-
return answers_as_query_results
213+
active_learning_enabled = (
214+
json_res["activeLearningEnabled"]
215+
if "activeLearningEnabled" in json_res
216+
else True
217+
)
218+
219+
query_answer_response = QueryResults(
220+
answers_as_query_results, active_learning_enabled
221+
)
222+
223+
return query_answer_response

libraries/botbuilder-ai/setup.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@
3333
long_description=long_description,
3434
long_description_content_type="text/x-rst",
3535
license=package_info["__license__"],
36-
packages=["botbuilder.ai", "botbuilder.ai.qna", "botbuilder.ai.luis"],
36+
packages=[
37+
"botbuilder.ai",
38+
"botbuilder.ai.qna",
39+
"botbuilder.ai.luis",
40+
"botbuilder.ai.qna.models",
41+
"botbuilder.ai.qna.utils",
42+
],
3743
install_requires=REQUIRES + TESTS_REQUIRES,
3844
tests_require=TESTS_REQUIRES,
3945
include_package_data=True,

libraries/botbuilder-ai/tests/qna/test_data/ReturnsAnswer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"activeLearningEnabled": false,
23
"answers": [
34
{
45
"questions": [

libraries/botbuilder-ai/tests/qna/test_qna.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,21 @@ async def test_returns_answer(self):
146146
first_answer.answer,
147147
)
148148

149+
async def test_active_learning_enabled_status(self):
150+
# Arrange
151+
question: str = "how do I clean the stove?"
152+
response_path: str = "ReturnsAnswer.json"
153+
154+
# Act
155+
result = await QnaApplicationTest._get_service_result_raw(
156+
question, response_path
157+
)
158+
159+
# Assert
160+
self.assertIsNotNone(result)
161+
self.assertEqual(1, len(result.answers))
162+
self.assertFalse(result.active_learning_enabled)
163+
149164
async def test_returns_answer_using_options(self):
150165
# Arrange
151166
question: str = "up"
@@ -783,6 +798,27 @@ async def _get_service_result(
783798

784799
return result
785800

801+
@classmethod
802+
async def _get_service_result_raw(
803+
cls,
804+
utterance: str,
805+
response_file: str,
806+
bot_adapter: BotAdapter = TestAdapter(),
807+
options: QnAMakerOptions = None,
808+
) -> [dict]:
809+
response_json = QnaApplicationTest._get_json_for_file(response_file)
810+
811+
qna = QnAMaker(QnaApplicationTest.tests_endpoint)
812+
context = QnaApplicationTest._get_context(utterance, bot_adapter)
813+
814+
with patch(
815+
"aiohttp.ClientSession.post",
816+
return_value=aiounittest.futurized(response_json),
817+
):
818+
result = await qna.get_answers_raw(context, options)
819+
820+
return result
821+
786822
@classmethod
787823
def _get_json_for_file(cls, response_file: str) -> object:
788824
curr_dir = path.dirname(path.abspath(__file__))

0 commit comments

Comments
 (0)
0