From b3f3d20faed65308d2b7f0c6fd5abbfc0fa88da5 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Sep 2020 15:42:13 -0400 Subject: [PATCH 1/3] don't look at doc # bc of OM error --- .../azure/ai/textanalytics/_models.py | 13 +++++++------ .../azure/ai/textanalytics/_response_handlers.py | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py index 1e25740e30c0..818ec1eac271 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py @@ -820,7 +820,7 @@ def __init__(self, **kwargs): self.mined_opinions = kwargs.get("mined_opinions", None) @classmethod - def _from_generated(cls, sentence, results): + def _from_generated(cls, sentence, results, sentiment): offset = sentence.offset length = sentence.length if isinstance(sentence, _v3_0_models.SentenceSentiment): @@ -830,7 +830,7 @@ def _from_generated(cls, sentence, results): length = None if hasattr(sentence, "aspects"): mined_opinions = ( - [MinedOpinion._from_generated(aspect, results) for aspect in sentence.aspects] # pylint: disable=protected-access + [MinedOpinion._from_generated(aspect, results, sentiment) for aspect in sentence.aspects] # pylint: disable=protected-access if sentence.aspects else [] ) else: @@ -871,7 +871,7 @@ def __init__(self, **kwargs): self.opinions = kwargs.get("opinions", None) @staticmethod - def _get_opinions(relations, results): + def _get_opinions(relations, results, sentiment): if not relations: return [] opinion_relations = [r.ref for r in relations if r.relation_type == "opinion"] @@ -882,16 +882,17 @@ def _get_opinions(relations, results): sentence_index = nums[1] opinion_index = nums[2] opinions.append( - results[document_index].sentences[sentence_index].opinions[opinion_index] + sentiment.sentences[sentence_index].opinions[opinion_index] ) return opinions @classmethod - def _from_generated(cls, aspect, results): + def _from_generated(cls, aspect, results, sentiment): return cls( aspect=AspectSentiment._from_generated(aspect), # pylint: disable=protected-access opinions=[ - OpinionSentiment._from_generated(opinion) for opinion in cls._get_opinions(aspect.relations, results) # pylint: disable=protected-access + OpinionSentiment._from_generated(opinion) + for opinion in cls._get_opinions(aspect.relations, results, sentiment) # pylint: disable=protected-access ], ) diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py index 559fbf17cc5f..79383ba63957 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py @@ -126,7 +126,7 @@ def sentiment_result(sentiment, results): warnings=[TextAnalyticsWarning._from_generated(w) for w in sentiment.warnings], # pylint: disable=protected-access statistics=TextDocumentStatistics._from_generated(sentiment.statistics), # pylint: disable=protected-access confidence_scores=SentimentConfidenceScores._from_generated(sentiment.confidence_scores), # pylint: disable=protected-access - sentences=[SentenceSentiment._from_generated(s, results) for s in sentiment.sentences], # pylint: disable=protected-access + sentences=[SentenceSentiment._from_generated(s, results, sentiment) for s in sentiment.sentences], # pylint: disable=protected-access ) @prepare_result From 182b20682bac201c74e24de01e803d29536e35d8 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Sep 2020 15:42:24 -0400 Subject: [PATCH 2/3] add tests --- ..._opinion_mining_more_than_5_documents.yaml | 59 +++++++++++++++++++ ..._opinion_mining_more_than_5_documents.yaml | 48 +++++++++++++++ .../tests/test_analyze_sentiment.py | 35 +++++++++++ .../tests/test_analyze_sentiment_async.py | 34 +++++++++++ 4 files changed, 176 insertions(+) create mode 100644 sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment.test_opinion_mining_more_than_5_documents.yaml create mode 100644 sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment_async.test_opinion_mining_more_than_5_documents.yaml diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment.test_opinion_mining_more_than_5_documents.yaml b/sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment.test_opinion_mining_more_than_5_documents.yaml new file mode 100644 index 000000000000..694e4826e951 --- /dev/null +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment.test_opinion_mining_more_than_5_documents.yaml @@ -0,0 +1,59 @@ +interactions: +- request: + body: '{"documents": [{"id": "0", "text": "The food was unacceptable", "language": + "en"}, {"id": "1", "text": "The rooms were beautiful. The AC was good and quiet.", + "language": "en"}, {"id": "2", "text": "The breakfast was good, but the toilet + was smelly.", "language": "en"}, {"id": "3", "text": "Loved this hotel - good + breakfast - nice shuttle service - clean rooms.", "language": "en"}, {"id": + "4", "text": "I had a great unobstructed view of the Microsoft campus.", "language": + "en"}, {"id": "5", "text": "Nice rooms but bathrooms were old and the toilet + was dirty when we arrived.", "language": "en"}, {"id": "6", "text": "The toilet + smelled.", "language": "en"}]}' + headers: + Accept: + - application/json, text/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '664' + Content-Type: + - application/json + User-Agent: + - azsdk-python-ai-textanalytics/5.1.0b1 Python/3.8.5 (macOS-10.13.6-x86_64-i386-64bit) + method: POST + uri: https://westcentralus.api.cognitive.microsoft.com/text/analytics/v3.1-preview.2/sentiment?showStats=false&opinionMining=true&stringIndexType=UnicodeCodePoint + response: + body: + string: '{"documents":[{"id":"0","sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"sentences":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"offset":0,"length":25,"text":"The + food was unacceptable","aspects":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":4,"length":4,"text":"food","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/0"}]}],"opinions":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":13,"length":12,"text":"unacceptable","isNegated":false}]}],"warnings":[]},{"id":"1","sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"sentences":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":0,"length":25,"text":"The + rooms were beautiful.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":4,"length":5,"text":"rooms","relations":[{"relationType":"opinion","ref":"#/documents/1/sentences/0/opinions/0"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":15,"length":9,"text":"beautiful","isNegated":false}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":26,"length":26,"text":"The + AC was good and quiet.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":30,"length":2,"text":"AC","relations":[{"relationType":"opinion","ref":"#/documents/1/sentences/1/opinions/0"},{"relationType":"opinion","ref":"#/documents/1/sentences/1/opinions/1"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":37,"length":4,"text":"good","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":46,"length":5,"text":"quiet","isNegated":false}]}],"warnings":[]},{"id":"2","sentiment":"negative","confidenceScores":{"positive":0.01,"neutral":0.0,"negative":0.99},"sentences":[{"sentiment":"negative","confidenceScores":{"positive":0.01,"neutral":0.0,"negative":0.99},"offset":0,"length":50,"text":"The + breakfast was good, but the toilet was smelly.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":4,"length":9,"text":"breakfast","relations":[{"relationType":"opinion","ref":"#/documents/2/sentences/0/opinions/0"}]},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":32,"length":6,"text":"toilet","relations":[{"relationType":"opinion","ref":"#/documents/2/sentences/0/opinions/1"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":18,"length":4,"text":"good","isNegated":false},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":43,"length":6,"text":"smelly","isNegated":false}]}],"warnings":[]},{"id":"3","sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"sentences":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":0,"length":71,"text":"Loved + this hotel - good breakfast - nice shuttle service - clean rooms.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":11,"length":5,"text":"hotel","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/0"}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":24,"length":9,"text":"breakfast","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/1"}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":41,"length":15,"text":"shuttle + service","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/2"}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":65,"length":5,"text":"rooms","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/0"},{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/1"},{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/3"},{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/2"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":19,"length":4,"text":"good","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":36,"length":4,"text":"nice","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":0,"length":5,"text":"loved","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":59,"length":5,"text":"clean","isNegated":false}]}],"warnings":[]},{"id":"4","sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"sentences":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":0,"length":56,"text":"I + had a great unobstructed view of the Microsoft campus.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":0.97,"negative":0.03},"offset":27,"length":4,"text":"view","relations":[{"relationType":"opinion","ref":"#/documents/4/sentences/0/opinions/0"},{"relationType":"opinion","ref":"#/documents/4/sentences/0/opinions/1"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":8,"length":5,"text":"great","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":0.93,"negative":0.07},"offset":14,"length":12,"text":"unobstructed","isNegated":false}]}],"warnings":[]},{"id":"5","sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"sentences":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"offset":0,"length":75,"text":"Nice + rooms but bathrooms were old and the toilet was dirty when we arrived.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":5,"length":5,"text":"rooms","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/0"}]},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":15,"length":9,"text":"bathrooms","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/1"}]},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":42,"length":6,"text":"toilet","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/2"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":0,"length":4,"text":"nice","isNegated":false},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":30,"length":3,"text":"old","isNegated":false},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":53,"length":5,"text":"dirty","isNegated":false}]}],"warnings":[]},{"id":"6","sentiment":"neutral","confidenceScores":{"positive":0.03,"neutral":0.63,"negative":0.34},"sentences":[{"sentiment":"neutral","confidenceScores":{"positive":0.03,"neutral":0.63,"negative":0.34},"offset":0,"length":19,"text":"The + toilet smelled.","aspects":[{"sentiment":"negative","confidenceScores":{"positive":0.01,"negative":0.99},"offset":4,"length":6,"text":"toilet","relations":[{"relationType":"opinion","ref":"#/documents/1/sentences/0/opinions/0"}]}],"opinions":[{"sentiment":"negative","confidenceScores":{"positive":0.01,"negative":0.99},"offset":11,"length":7,"text":"smelled","isNegated":false}]}],"warnings":[]}],"errors":[],"modelVersion":"2020-04-01"}' + headers: + apim-request-id: + - 3114573b-7cce-415e-8fb0-4a40fbb1fdf4 + content-type: + - application/json; charset=utf-8 + csp-billing-usage: + - CognitiveServices.TextAnalytics.BatchScoring=7 + date: + - Wed, 16 Sep 2020 19:41:48 GMT + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + transfer-encoding: + - chunked + x-content-type-options: + - nosniff + x-envoy-upstream-service-time: + - '113' + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment_async.test_opinion_mining_more_than_5_documents.yaml b/sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment_async.test_opinion_mining_more_than_5_documents.yaml new file mode 100644 index 000000000000..46d25a8a0ce9 --- /dev/null +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/recordings/test_analyze_sentiment_async.test_opinion_mining_more_than_5_documents.yaml @@ -0,0 +1,48 @@ +interactions: +- request: + body: '{"documents": [{"id": "0", "text": "The food was unacceptable", "language": + "en"}, {"id": "1", "text": "The rooms were beautiful. The AC was good and quiet.", + "language": "en"}, {"id": "2", "text": "The breakfast was good, but the toilet + was smelly.", "language": "en"}, {"id": "3", "text": "Loved this hotel - good + breakfast - nice shuttle service - clean rooms.", "language": "en"}, {"id": + "4", "text": "I had a great unobstructed view of the Microsoft campus.", "language": + "en"}, {"id": "5", "text": "Nice rooms but bathrooms were old and the toilet + was dirty when we arrived.", "language": "en"}, {"id": "6", "text": "The toilet + smelled.", "language": "en"}]}' + headers: + Accept: + - application/json, text/json + Content-Length: + - '664' + Content-Type: + - application/json + User-Agent: + - azsdk-python-ai-textanalytics/5.1.0b1 Python/3.8.5 (macOS-10.13.6-x86_64-i386-64bit) + method: POST + uri: https://westcentralus.api.cognitive.microsoft.com/text/analytics/v3.1-preview.2/sentiment?showStats=false&opinionMining=true&stringIndexType=UnicodeCodePoint + response: + body: + string: '{"documents":[{"id":"0","sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"sentences":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"offset":0,"length":25,"text":"The + food was unacceptable","aspects":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":4,"length":4,"text":"food","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/0"}]}],"opinions":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":13,"length":12,"text":"unacceptable","isNegated":false}]}],"warnings":[]},{"id":"1","sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"sentences":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":0,"length":25,"text":"The + rooms were beautiful.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":4,"length":5,"text":"rooms","relations":[{"relationType":"opinion","ref":"#/documents/1/sentences/0/opinions/0"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":15,"length":9,"text":"beautiful","isNegated":false}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":26,"length":26,"text":"The + AC was good and quiet.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":30,"length":2,"text":"AC","relations":[{"relationType":"opinion","ref":"#/documents/1/sentences/1/opinions/0"},{"relationType":"opinion","ref":"#/documents/1/sentences/1/opinions/1"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":37,"length":4,"text":"good","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":46,"length":5,"text":"quiet","isNegated":false}]}],"warnings":[]},{"id":"2","sentiment":"negative","confidenceScores":{"positive":0.01,"neutral":0.0,"negative":0.99},"sentences":[{"sentiment":"negative","confidenceScores":{"positive":0.01,"neutral":0.0,"negative":0.99},"offset":0,"length":50,"text":"The + breakfast was good, but the toilet was smelly.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":4,"length":9,"text":"breakfast","relations":[{"relationType":"opinion","ref":"#/documents/2/sentences/0/opinions/0"}]},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":32,"length":6,"text":"toilet","relations":[{"relationType":"opinion","ref":"#/documents/2/sentences/0/opinions/1"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":18,"length":4,"text":"good","isNegated":false},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":43,"length":6,"text":"smelly","isNegated":false}]}],"warnings":[]},{"id":"3","sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"sentences":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":0,"length":71,"text":"Loved + this hotel - good breakfast - nice shuttle service - clean rooms.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":11,"length":5,"text":"hotel","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/0"}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":24,"length":9,"text":"breakfast","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/1"}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":41,"length":15,"text":"shuttle + service","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/2"}]},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":65,"length":5,"text":"rooms","relations":[{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/0"},{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/1"},{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/3"},{"relationType":"opinion","ref":"#/documents/3/sentences/0/opinions/2"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":19,"length":4,"text":"good","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":36,"length":4,"text":"nice","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":0,"length":5,"text":"loved","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":59,"length":5,"text":"clean","isNegated":false}]}],"warnings":[]},{"id":"4","sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"sentences":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"neutral":0.0,"negative":0.0},"offset":0,"length":56,"text":"I + had a great unobstructed view of the Microsoft campus.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":0.97,"negative":0.03},"offset":27,"length":4,"text":"view","relations":[{"relationType":"opinion","ref":"#/documents/4/sentences/0/opinions/0"},{"relationType":"opinion","ref":"#/documents/4/sentences/0/opinions/1"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":8,"length":5,"text":"great","isNegated":false},{"sentiment":"positive","confidenceScores":{"positive":0.93,"negative":0.07},"offset":14,"length":12,"text":"unobstructed","isNegated":false}]}],"warnings":[]},{"id":"5","sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"sentences":[{"sentiment":"negative","confidenceScores":{"positive":0.0,"neutral":0.0,"negative":1.0},"offset":0,"length":75,"text":"Nice + rooms but bathrooms were old and the toilet was dirty when we arrived.","aspects":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":5,"length":5,"text":"rooms","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/0"}]},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":15,"length":9,"text":"bathrooms","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/1"}]},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":42,"length":6,"text":"toilet","relations":[{"relationType":"opinion","ref":"#/documents/0/sentences/0/opinions/2"}]}],"opinions":[{"sentiment":"positive","confidenceScores":{"positive":1.0,"negative":0.0},"offset":0,"length":4,"text":"nice","isNegated":false},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":30,"length":3,"text":"old","isNegated":false},{"sentiment":"negative","confidenceScores":{"positive":0.0,"negative":1.0},"offset":53,"length":5,"text":"dirty","isNegated":false}]}],"warnings":[]},{"id":"6","sentiment":"neutral","confidenceScores":{"positive":0.03,"neutral":0.63,"negative":0.34},"sentences":[{"sentiment":"neutral","confidenceScores":{"positive":0.03,"neutral":0.63,"negative":0.34},"offset":0,"length":19,"text":"The + toilet smelled.","aspects":[{"sentiment":"negative","confidenceScores":{"positive":0.01,"negative":0.99},"offset":4,"length":6,"text":"toilet","relations":[{"relationType":"opinion","ref":"#/documents/1/sentences/0/opinions/0"}]}],"opinions":[{"sentiment":"negative","confidenceScores":{"positive":0.01,"negative":0.99},"offset":11,"length":7,"text":"smelled","isNegated":false}]}],"warnings":[]}],"errors":[],"modelVersion":"2020-04-01"}' + headers: + apim-request-id: b19f292b-d4b6-40ff-87c9-559a4d47d820 + content-type: application/json; charset=utf-8 + csp-billing-usage: CognitiveServices.TextAnalytics.BatchScoring=7 + date: Wed, 16 Sep 2020 19:41:48 GMT + strict-transport-security: max-age=31536000; includeSubDomains; preload + transfer-encoding: chunked + x-content-type-options: nosniff + x-envoy-upstream-service-time: '113' + status: + code: 200 + message: OK + url: https://westcentralus.api.cognitive.microsoft.com//text/analytics/v3.1-preview.2/sentiment?showStats=false&opinionMining=true&stringIndexType=UnicodeCodePoint +version: 1 diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment.py b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment.py index 88365d0949cf..c914a08fa1f3 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment.py +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment.py @@ -651,6 +651,41 @@ def test_opinion_mining_with_negated_opinion(self, client): self.assertEqual(4, food_opinion.length) self.assertTrue(food_opinion.is_negated) + + @GlobalTextAnalyticsAccountPreparer() + @TextAnalyticsClientPreparer() + def test_opinion_mining_more_than_5_documents(self, client): + documents = [ + "The food was unacceptable", + "The rooms were beautiful. The AC was good and quiet.", + "The breakfast was good, but the toilet was smelly.", + "Loved this hotel - good breakfast - nice shuttle service - clean rooms.", + "I had a great unobstructed view of the Microsoft campus.", + "Nice rooms but bathrooms were old and the toilet was dirty when we arrived.", + "The toilet smelled." + ] + + analyzed_documents = client.analyze_sentiment(documents, show_opinion_mining=True) + doc_5 = analyzed_documents[5] + doc_6 = analyzed_documents[6] + + doc_5_opinions = [ + opinion.text + for sentence in doc_5.sentences + for mined_opinion in sentence.mined_opinions + for opinion in mined_opinion.opinions + ] + + doc_6_opinions = [ + opinion.text + for sentence in doc_6.sentences + for mined_opinion in sentence.mined_opinions + for opinion in mined_opinion.opinions + ] + + assert doc_5_opinions == ["nice", "old", "dirty"] + assert doc_6_opinions == ["smelled"] + @GlobalTextAnalyticsAccountPreparer() @TextAnalyticsClientPreparer() def test_opinion_mining_no_mined_opinions(self, client): diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment_async.py b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment_async.py index 61204e13da35..16eedf46b21f 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment_async.py +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_sentiment_async.py @@ -667,6 +667,40 @@ async def test_opinion_mining_with_negated_opinion(self, client): self.assertEqual(4, food_opinion.length) self.assertTrue(food_opinion.is_negated) + @GlobalTextAnalyticsAccountPreparer() + @TextAnalyticsClientPreparer() + async def test_opinion_mining_more_than_5_documents(self, client): + documents = [ + "The food was unacceptable", + "The rooms were beautiful. The AC was good and quiet.", + "The breakfast was good, but the toilet was smelly.", + "Loved this hotel - good breakfast - nice shuttle service - clean rooms.", + "I had a great unobstructed view of the Microsoft campus.", + "Nice rooms but bathrooms were old and the toilet was dirty when we arrived.", + "The toilet smelled." + ] + + analyzed_documents = await client.analyze_sentiment(documents, show_opinion_mining=True) + doc_5 = analyzed_documents[5] + doc_6 = analyzed_documents[6] + + doc_5_opinions = [ + opinion.text + for sentence in doc_5.sentences + for mined_opinion in sentence.mined_opinions + for opinion in mined_opinion.opinions + ] + + doc_6_opinions = [ + opinion.text + for sentence in doc_6.sentences + for mined_opinion in sentence.mined_opinions + for opinion in mined_opinion.opinions + ] + + assert doc_5_opinions == ["nice", "old", "dirty"] + assert doc_6_opinions == ["smelled"] + @GlobalTextAnalyticsAccountPreparer() @TextAnalyticsClientPreparer() async def test_opinion_mining_no_mined_opinions(self, client): From 9e2914d46f0f6af6d59d45ca56ec167b1ef3fe83 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Sep 2020 15:57:34 -0400 Subject: [PATCH 3/3] fix pylint --- .../azure/ai/textanalytics/_models.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py index 818ec1eac271..83a8eb146568 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py @@ -871,14 +871,13 @@ def __init__(self, **kwargs): self.opinions = kwargs.get("opinions", None) @staticmethod - def _get_opinions(relations, results, sentiment): + def _get_opinions(relations, results, sentiment): # pylint: disable=unused-argument if not relations: return [] opinion_relations = [r.ref for r in relations if r.relation_type == "opinion"] opinions = [] for opinion_relation in opinion_relations: nums = _get_indices(opinion_relation) - document_index = nums[0] sentence_index = nums[1] opinion_index = nums[2] opinions.append( @@ -891,8 +890,8 @@ def _from_generated(cls, aspect, results, sentiment): return cls( aspect=AspectSentiment._from_generated(aspect), # pylint: disable=protected-access opinions=[ - OpinionSentiment._from_generated(opinion) - for opinion in cls._get_opinions(aspect.relations, results, sentiment) # pylint: disable=protected-access + OpinionSentiment._from_generated(opinion) # pylint: disable=protected-access + for opinion in cls._get_opinions(aspect.relations, results, sentiment) ], )