Repository: microsoft/botbuilder-python
Pull request #310 (2019-09-03 12:58:18)

[QnA Maker] Multi-turn SDK support for QnAId 
## Description
Addition of a new optional parameter (qnaId) in GenerateAnswer body.

## Specific Changes
<!-- Please list the changes in a concise manner. -->

  - Support for QnA Id added 

## Testing
Test case added


Patch:
diff --git a/libraries/botbuilder-ai/botbuilder/ai/qna/models/generate_answer_request_body.py b/libraries/botbuilder-ai/botbuilder/ai/qna/models/generate_answer_request_body.py
index 285900ae..34afb4d2 100644
--- a/libraries/botbuilder-ai/botbuilder/ai/qna/models/generate_answer_request_body.py
+++ b/libraries/botbuilder-ai/botbuilder/ai/qna/models/generate_answer_request_body.py
@@ -18,6 +18,7 @@ class GenerateAnswerRequestBody(Model):
         "score_threshold": {"key": "scoreThreshold", "type": "float"},
         "strict_filters": {"key": "strictFilters", "type": "[Metadata]"},
         "context": {"key": "context", "type": "QnARequestContext"},
+        "qna_id": {"key": "qnaId", "type": "int"},
     }
 
     def __init__(
@@ -27,6 +28,7 @@ class GenerateAnswerRequestBody(Model):
         score_threshold: float,
         strict_filters: List[Metadata],
         context: QnARequestContext = None,
+        qna_id: int = None,
         **kwargs
     ):
         """
@@ -43,6 +45,8 @@ class GenerateAnswerRequestBody(Model):
 
         context: The context from which the QnA was extracted.
 
+        qna_id: Id of the current question asked.
+
         """
 
         super().__init__(**kwargs)
@@ -52,3 +56,4 @@ class GenerateAnswerRequestBody(Model):
         self.score_threshold = score_threshold
         self.strict_filters = strict_filters
         self.context = context
+        self.qna_id = qna_id
diff --git a/libraries/botbuilder-ai/botbuilder/ai/qna/models/qnamaker_trace_info.py b/libraries/botbuilder-ai/botbuilder/ai/qna/models/qnamaker_trace_info.py
index 1a503f07..987ea967 100644
--- a/libraries/botbuilder-ai/botbuilder/ai/qna/models/qnamaker_trace_info.py
+++ b/libraries/botbuilder-ai/botbuilder/ai/qna/models/qnamaker_trace_info.py
@@ -21,6 +21,7 @@ class QnAMakerTraceInfo:
         top: int,
         strict_filters: List[Metadata],
         context: QnARequestContext = None,
+        qna_id: int = None,
     ):
         """
         Parameters:
@@ -39,6 +40,8 @@ class QnAMakerTraceInfo:
         strict_filters: Filters used on query.
 
         context: (Optional) The context from which the QnA was extracted.
+
+        qna_id: (Optional) Id of the current question asked.
         """
         self.message = message
         self.query_results = query_results
@@ -47,3 +50,4 @@ class QnAMakerTraceInfo:
         self.top = top
         self.strict_filters = strict_filters
         self.context = context
+        self.qna_id = qna_id
diff --git a/libraries/botbuilder-ai/botbuilder/ai/qna/qnamaker_options.py b/libraries/botbuilder-ai/botbuilder/ai/qna/qnamaker_options.py
index 127b0aa3..a32f49fe 100644
--- a/libraries/botbuilder-ai/botbuilder/ai/qna/qnamaker_options.py
+++ b/libraries/botbuilder-ai/botbuilder/ai/qna/qnamaker_options.py
@@ -12,9 +12,11 @@ class QnAMakerOptions:
         top: int = 0,
         strict_filters: [Metadata] = None,
         context: [QnARequestContext] = None,
+        qna_id: int = None,
     ):
         self.score_threshold = score_threshold
         self.timeout = timeout
         self.top = top
         self.strict_filters = strict_filters or []
         self.context = context
+        self.qna_id = qna_id
diff --git a/libraries/botbuilder-ai/botbuilder/ai/qna/utils/generate_answer_utils.py b/libraries/botbuilder-ai/botbuilder/ai/qna/utils/generate_answer_utils.py
index 5831875c..3a6e28fc 100644
--- a/libraries/botbuilder-ai/botbuilder/ai/qna/utils/generate_answer_utils.py
+++ b/libraries/botbuilder-ai/botbuilder/ai/qna/utils/generate_answer_utils.py
@@ -127,8 +127,8 @@ class GenerateAnswerUtils:
             ):
                 hydrated_options.timeout = query_options.timeout
 
-            if query_options.context:
-                hydrated_options.context = query_options.context
+            hydrated_options.context = query_options.context
+            hydrated_options.qna_id = query_options.qna_id
 
         return hydrated_options
 
@@ -143,6 +143,7 @@ class GenerateAnswerUtils:
             score_threshold=options.score_threshold,
             strict_filters=options.strict_filters,
             context=options.context,
+            qna_id=options.qna_id,
         )
 
         http_request_helper = HttpRequestUtils(self._http_client)
@@ -166,6 +167,7 @@ class GenerateAnswerUtils:
             top=options.top,
             strict_filters=options.strict_filters,
             context=options.context,
+            qna_id=options.qna_id,
         )
 
         trace_activity = Activity(


Test patch:
diff --git a/libraries/botbuilder-ai/tests/qna/test_qna.py b/libraries/botbuilder-ai/tests/qna/test_qna.py
index 24134fc9..eb7f5a9e 100644
--- a/libraries/botbuilder-ai/tests/qna/test_qna.py
+++ b/libraries/botbuilder-ai/tests/qna/test_qna.py
@@ -710,7 +710,25 @@ class QnaApplicationTest(aiounittest.AsyncTestCase):
         context = QnARequestContext(
             previous_qna_id=5, prvious_user_query="how do I clean the stove?"
         )
-        options = QnAMakerOptions(top=2, context=context)
+        options = QnAMakerOptions(top=2, qna_id=55, context=context)
+        turn_context = QnaApplicationTest._get_context(question, TestAdapter())
+        response_json = QnaApplicationTest._get_json_for_file(
+            "AnswerWithHighScoreProvidedContext.json"
+        )
+
+        with patch(
+            "aiohttp.ClientSession.post",
+            return_value=aiounittest.futurized(response_json),
+        ):
+            results = await qna.get_answers(turn_context, options)
+            self.assertEqual(1, len(results), "Should have received 1 answers.")
+            self.assertEqual(1, results[0].score, "Score should be high.")
+
+    async def test_should_answer_with_high_score_provided_qna_id(self):
+        qna = QnAMaker(QnaApplicationTest.tests_endpoint)
+        question: str = "where can I buy?"
+
+        options = QnAMakerOptions(top=2, qna_id=55)
         turn_context = QnaApplicationTest._get_context(question, TestAdapter())
         response_json = QnaApplicationTest._get_json_for_file(
             "AnswerWithHighScoreProvidedContext.json"