Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
# Release History

## 1.0.0b3 (Unreleased)
## 1.0.0 (Unreleased)

### Features Added
* We are now targeting service version `2021-10-01`

### Breaking Changes

* Method `QuestionAnsweringClient.query_knowledge_base` has been renamed to `get_answers`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow this changelog is a work of art

* Method `QuestionAnsweringClient.query_text` has been renamed to `get_answers_from_text`
* Model `QueryKnowledgeBaseOptions` has been renamed to `AnswersOptions`
* Method kwarg and model property `QueryKnowledgeBaseOptions.confidence_score_threshold` has been renamed to `AnswersOptions.confidence_threshold`
* Method kwarg and model property `QueryKnowledgeBaseOptions.answer_span_request` has been renamed to `AnswersOptions.short_answer_options`
* Method kwarg and model property `QueryKnowledgeBaseOptions.ranker_type` has been renamed to `AnswersOptions.ranker_kind`
* Method kwarg and model property `QueryKnowledgeBaseOptions.context` has been renamed to `AnswersOptions.answer_context`
* Model `QueryTextOptions` has been renamed to `AnswersFromTextOptions`
* Method kwarg and model property `QueryTextOptions.records` has been renamed to `AnswersFromTextOptions.text_documents`
* Model `AnswerSpanRequest` has been renamed to `ShortAnswerOptions`
* Model property `AnswerSpanRequest.confidence_score_threshold` has been renamed to `ShortAnswerOptions.confidence_threshold`
* Model property `AnswerSpanRequest.top_answers_with_span` has been renamed to `ShortAnswerOptions.top`
* Model `KnowledgeBaseAnswerRequestContext` has been renamed to `KnowledgeBaseAnswerContext`
* Model property `KnowledgeBaseAnswerRequestContext.previous_user_query` has been renamed to `KnowledgeBaseAnswerContext.previous_question`
* Model `TextRecord` has been renamed to `TextDocument`
* Model `KnowledgeBaseAnswers` has been renamed to `AnswersResult`
* Model `TextAnswers` has been renamed to `AnswersFromTextResult`
* Model property `KnowledgeBaseAnswer.answer_span` has been renamed to `KnowledgeBaseAnswer.short_answer`
* Model property `KnowledgeBaseAnswer.id` has been renamed to `KnowledgeBaseAnswer.qna_id`
* Model property `KnowledgeBaseAnswer.confidence_score` has been renamed to `KnowledgeBaseAnswer.confidence`
* Model property `AnswerSpan.confidence_score` has been renamed to `AnswerSpan.confidence`
* Model property `TextAnswer.confidence_score` has been renamed to `TextAnswer.confidence`
* Model property `TextAnswer.answer_span` has been renamed to `TextAnswer.short_answer`
* Enums `LogicalOperationKind` and `RankerType` have been removed.

### Bugs Fixed

### Other Changes
* Fixed formating of `MetadataFilter.metadata`

## 1.0.0b2 (2021-10-06)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,42 +78,36 @@ The following examples show common scenarios using the `client` [created above](
The only input required to ask a question using a knowledge base is just the question itself:

```python
from azure.ai.language.questionanswering import models as qna

params = qna.QueryKnowledgeBaseOptions(
question="How long should my Surface battery last?"
)

output = client.query_knowledge_base(
params,
output = client.get_answers(
question="How long should my Surface battery last?",
project_name="FAQ",
deployment_name="test"
)
for candidate in output.answers:
print("({}) {}".format(candidate.confidence_score, candidate.answer))
print("({}) {}".format(candidate.confidence, candidate.answer))
print("Source: {}".format(candidate.source))

```

You can set additional properties on `QueryKnowledgeBaseOptions` to limit the number of answers, specify a minimum confidence score, and more.
You can set additional keyword options to limit the number of answers, specify a minimum confidence score, and more.

### Ask a follow-up question

If your knowledge base is configured for [chit-chat][questionanswering_docs_chat], the answers from the knowledge base may include suggested [prompts for follow-up questions][questionanswering_refdocs_prompts] to initiate a conversation. You can ask a follow-up question by providing the ID of your chosen answer as the context for the continued conversation:

```python
params = qna.models.QueryKnowledgeBaseOptions(
question="How long should charging take?"
context=qna.models.KnowledgeBaseAnswerRequestContext(
previous_qna_id=previous_answer.id
)
)
from azure.ai.language.questionanswering import models

output = client.query_knowledge_base(
params,
project_name="FAQ"
output = client.get_answers(
question="How long should charging take?",
answer_context=models.KnowledgeBaseAnswerContext(
previous_qna_id=previous_answer.qna_id
),
project_name="FAQ",
deployment_name="live"
)
for candidate in output.answers:
print("({}) {}".format(candidate.confidence_score, candidate.answer))
print("({}) {}".format(candidate.confidence, candidate.answer))
print("Source: {}".format(candidate.source))

```
Expand All @@ -125,17 +119,13 @@ The above examples can also be run asynchronously using the client in the `aio`
```python
from azure.core.credentials import AzureKeyCredential
from azure.ai.language.questionanswering.aio import QuestionAnsweringClient
from azure.ai.language.questionanswering import models as qna

client = QuestionAnsweringClient(endpoint, credential)

params = qna.QueryKnowledgeBaseOptions(
question="How long should my Surface battery last?"
)

output = await client.query_knowledge_base(
params,
project_name="FAQ"
output = await client.get_answers(
question="How long should my Surface battery last?",
project_name="FAQ",
deployment_name="production"
)
```

Expand All @@ -156,9 +146,10 @@ For example, if you submit a question to a non-existant knowledge base, a `400`
from azure.core.exceptions import HttpResponseError

try:
client.query_knowledge_base(
params,
project_name="invalid-knowledge-base"
client.get_answers(
question="Why?",
project_name="invalid-knowledge-base",
deployment_name="test"
)
except HttpResponseError as error:
print("Query failed: {}".format(error.message))
Expand Down Expand Up @@ -208,15 +199,15 @@ This project has adopted the [Microsoft Open Source Code of Conduct][code_of_con
[azure_core_ref_docs]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-core/latest/azure.core.html
[azure_core_readme]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/core/azure-core/README.md
[pip_link]: https://pypi.org/project/pip/
[questionanswering_client_class]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-ai-language-questionanswering/1.0.0b1/azure.ai.language.questionanswering.html#azure.ai.language.questionanswering.QuestionAnsweringClient
[questionanswering_refdocs_prompts]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-ai-language-questionanswering/1.0.0b1/azure.ai.language.questionanswering.models.html#azure.ai.language.questionanswering.models.KnowledgeBaseAnswerDialog
[questionanswering_client_class]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-ai-language-questionanswering/latest/azure.ai.language.questionanswering.html#azure.ai.language.questionanswering.QuestionAnsweringClient
[questionanswering_refdocs_prompts]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-ai-language-questionanswering/latest/azure.ai.language.questionanswering.models.html#azure.ai.language.questionanswering.models.KnowledgeBaseAnswerDialog
[questionanswering_client_src]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/cognitivelanguage/azure-ai-language-questionanswering/
[questionanswering_docs]: https://azure.microsoft.com/services/cognitive-services/qna-maker/
[questionanswering_docs_chat]: https://docs.microsoft.com/azure/cognitive-services/qnamaker/how-to/chit-chat-knowledge-base
[questionanswering_docs_demos]: https://azure.microsoft.com/services/cognitive-services/qna-maker/#demo
[questionanswering_docs_features]: https://azure.microsoft.com/services/cognitive-services/qna-maker/#features
[questionanswering_pypi_package]: https://pypi.org/project/azure-ai-language-questionanswering/
[questionanswering_refdocs]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-ai-language-questionanswering/1.0.0b1/azure.ai.language.questionanswering.html
[questionanswering_refdocs]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-ai-language-questionanswering/latest/azure.ai.language.questionanswering.html
[questionanswering_rest_docs]: https://docs.microsoft.com/rest/api/cognitiveservices-qnamaker/
[questionanswering_samples]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/cognitivelanguage/azure-ai-language-questionanswering/samples/README.md

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(

self.endpoint = endpoint
self.credential = credential
self.api_version = "2021-07-15-preview"
self.api_version = "2021-10-01"
kwargs.setdefault("sdk_moniker", "ai-language-questionanswering/{}".format(VERSION))
self._configure(**kwargs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,22 @@

import six
import copy
from .models import TextRecord
from .models import TextDocument


def _validate_text_records(records):
if not records:
raise ValueError("Input records can not be empty or None")
raise ValueError("Input documents can not be empty or None")

if isinstance(records, six.string_types):
raise TypeError("Input records cannot be a string.")
raise TypeError("Input documents cannot be a string.")

if isinstance(records, dict):
raise TypeError("Input records cannot be a dict")
raise TypeError("Input documents cannot be a dict")

if not all(isinstance(x, six.string_types) for x in records):
if not all(
isinstance(x, (dict, TextRecord))
for x in records
):
raise TypeError(
"Mixing string and dictionary/object record input unsupported."
)
if not all(isinstance(x, (dict, TextDocument)) for x in records):
raise TypeError("Mixing string and dictionary/object document input unsupported.")

request_batch = []
for idx, doc in enumerate(records):
Expand All @@ -37,6 +32,7 @@ def _validate_text_records(records):
request_batch.append(doc)
return request_batch


def _get_positional_body(*args, **kwargs):
"""Verify args and kwargs are valid, and then return the positional body, if users passed it in."""
if len(args) > 1:
Expand All @@ -48,6 +44,7 @@ def _get_positional_body(*args, **kwargs):
)
return args[0] if args else None


def _verify_qna_id_and_question(query_knowledgebase_options):
"""For query_knowledge_base we require either `question` or `qna_id`."""
try:
Expand All @@ -57,21 +54,16 @@ def _verify_qna_id_and_question(query_knowledgebase_options):
qna_id = query_knowledgebase_options.get("qna_id") or query_knowledgebase_options.get("qnaId")
question = query_knowledgebase_options.get("question")
if not (qna_id or question):
raise TypeError(
"You need to pass in either `qna_id` or `question`."
)
raise TypeError("You need to pass in either `qna_id` or `question`.")
if qna_id and question:
raise TypeError("You can not specify both `qna_id` and `question`.")


def _handle_metadata_filter_conversion(options_input):
options = copy.deepcopy(options_input)
filters = options.filters if hasattr(options, "filters") else options.get("filters", {})
try:
if (
filters and
filters.metadata_filter and
filters.metadata_filter.metadata
):
if filters and filters.metadata_filter and filters.metadata_filter.metadata:
metadata_input = filters.metadata_filter.metadata
else:
metadata_input = None
Expand All @@ -87,13 +79,9 @@ def _handle_metadata_filter_conversion(options_input):
except TypeError:
raise ValueError("'metadata' must be a sequence of key-value tuples.")

metadata_modified = [
{"key": m[0], "value": m[1]}
for m in metadata_input
]
metadata_modified = [{"key": m[0], "value": m[1]} for m in metadata_input]
if in_class:
filters.metadata_filter.metadata = metadata_modified
else:
filters["metadataFilter"]["metadata"] = metadata_modified
return options

Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@


class QuestionAnsweringClient(QuestionAnsweringClientOperationsMixin):
"""The language service API is a suite of natural language processing (NLP) skills built with best-in-class Microsoft machine learning algorithms. The API can be used to analyze unstructured text for tasks such as sentiment analysis, key phrase extraction, language detection and question answering. Further documentation can be found in https://docs.microsoft.com/en-us/azure/cognitive-services/text-analytics/overview.
"""The language service API is a suite of natural language processing (NLP) skills built with best-in-class Microsoft machine learning algorithms. The API can be used to analyze unstructured text for tasks such as sentiment analysis, key phrase extraction, language detection and question answering. Further documentation can be found in https://docs.microsoft.com/azure/cognitive-services/text-analytics/overview

:param endpoint: Supported Cognitive Services endpoint (e.g.,
:code:`https://<resource-name>.api.cognitiveservices.azure.com`).
https://<resource-name>.api.cognitiveservices.azure.com).
:type endpoint: str
:param credential: Credential needed for the client to connect to Azure.
:type credential: ~azure.core.credentials.AzureKeyCredential
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

VERSION = "1.0.0b3"
VERSION = "1.0.0"
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, endpoint: str, credential: AzureKeyCredential, **kwargs: Any)

self.endpoint = endpoint
self.credential = credential
self.api_version = "2021-07-15-preview"
self.api_version = "2021-10-01"
kwargs.setdefault("sdk_moniker", "ai-language-questionanswering/{}".format(VERSION))
self._configure(**kwargs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@


class QuestionAnsweringClient(QuestionAnsweringClientOperationsMixin):
"""The language service API is a suite of natural language processing (NLP) skills built with best-in-class Microsoft machine learning algorithms. The API can be used to analyze unstructured text for tasks such as sentiment analysis, key phrase extraction, language detection and question answering. Further documentation can be found in https://docs.microsoft.com/en-us/azure/cognitive-services/text-analytics/overview.
"""The language service API is a suite of natural language processing (NLP) skills built with best-in-class Microsoft machine learning algorithms. The API can be used to analyze unstructured text for tasks such as sentiment analysis, key phrase extraction, language detection and question answering. Further documentation can be found in https://docs.microsoft.com/azure/cognitive-services/text-analytics/overview

:param endpoint: Supported Cognitive Services endpoint (e.g.,
:code:`https://<resource-name>.api.cognitiveservices.azure.com`).
https://<resource-name>.api.cognitiveservices.azure.com).
:type endpoint: str
:param credential: Credential needed for the client to connect to Azure.
:type credential: ~azure.core.credentials.AzureKeyCredential
Expand Down
Loading