Skip to content

Commit 17d36b3

Browse files
authored
[TA] Healthcare entity relations and assertion (Azure#19552)
1 parent 602404b commit 17d36b3

File tree

33 files changed

+1236
-345
lines changed

33 files changed

+1236
-345
lines changed

sdk/textanalytics/azure-ai-textanalytics/CHANGELOG.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
# Release History
22
## 5.1.0-beta.5 (Unreleased)
3+
### New features
4+
- Added `normalizedText` property to `HealthcareEntity`.
5+
- `AnalyzeHealthcareEntitiesResult` now exposes the property `entityRelations`, which is a list of `HealthcareEntityRelation`.
6+
- Added `HealthcareEntityRelation` class which will determine all the different relations between the entities as `Roles`.
7+
- Added `HealthcareEntityRelationRole`, which exposes `name` and `entity` of type `String` and `HealthcareEntity` respectively.
8+
39
### Breaking changes
10+
- Replace `isNegated` by `HealthcareEntityAssertion` to `HealthcareEntity` which further exposes `EntityAssociation`, `EntityCertainity` and `EntityConditionality`.
411
- Renamed classes,
512
`AspectSentiment` to `TargetSentiment`, `OpinionSentiment` to `AssesssmentSentiment`, `MinedOpinion` to `SentenceOpinion`.
613
- Renamed
714
`SentenceSentiment`'s method, `getMinedOpinions()` to `getOpinions()`.
8-
`MinedOpinion`'s methods, `getAspect()` to `getTarget()`, `getOpinions()` to `getAssessments()`,
15+
`MinedOpinion`'s methods, `getAspect()` to `getTarget()`, `getOpinions()` to `getAssessments()`.
16+
- Removed property, `relatedEntities` from `HealthcareEntity`.
917
- Removed constructors,
1018
`SentenceSentiment(String text, TextSentiment sentiment, SentimentConfidenceScores confidenceScores, IterableStream<MinedOpinion> minedOpinions, int offset)`,
1119
`AspectSentiment(String text, TextSentiment sentiment, int offset, SentimentConfidenceScores confidenceScores)`,
1220
`OpinionSentiment(String text, TextSentiment sentiment, int offset, boolean isNegated, SentimentConfidenceScores confidenceScores)`
13-
1421
## 5.1.0-beta.4 (2021-02-10)
1522
### New features
1623
- Added new classes, `StringIndexType`, `RecognizeEntitiesOptions`, `RecognizeLinkedEntitiesOptions`.

sdk/textanalytics/azure-ai-textanalytics/README.md

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ az cognitiveservices account keys list --resource-group <your-resource-group-nam
8888
```
8989

9090
Use the key as the credential parameter to authenticate the client:
91-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L66-L69 -->
91+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L63-L66 -->
9292
```java
9393
TextAnalyticsClient textAnalyticsClient = new TextAnalyticsClientBuilder()
9494
.credential(new AzureKeyCredential("{key}"))
@@ -97,7 +97,7 @@ TextAnalyticsClient textAnalyticsClient = new TextAnalyticsClientBuilder()
9797
```
9898

9999
The Azure Text Analytics client library provides a way to **rotate the existing key**.
100-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L97-L103 -->
100+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L94-L100 -->
101101
```java
102102
AzureKeyCredential credential = new AzureKeyCredential("{key}");
103103
TextAnalyticsClient textAnalyticsClient = new TextAnalyticsClientBuilder()
@@ -135,7 +135,7 @@ Authorization is easiest using [DefaultAzureCredential][wiki_identity]. It finds
135135
running environment. For more information about using Azure Active Directory authorization with Text Analytics, please
136136
refer to [the associated documentation][aad_authorization].
137137

138-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L86-L90 -->
138+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L83-L87 -->
139139
```java
140140
TokenCredential defaultCredential = new DefaultAzureCredentialBuilder().build();
141141
TextAnalyticsAsyncClient textAnalyticsClient = new TextAnalyticsClientBuilder()
@@ -196,14 +196,14 @@ The following sections provide several code snippets covering some of the most c
196196
Text analytics support both synchronous and asynchronous client creation by using
197197
`TextAnalyticsClientBuilder`,
198198

199-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L66-L69 -->
199+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L63-L66 -->
200200
``` java
201201
TextAnalyticsClient textAnalyticsClient = new TextAnalyticsClientBuilder()
202202
.credential(new AzureKeyCredential("{key}"))
203203
.endpoint("{endpoint}")
204204
.buildClient();
205205
```
206-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L76-L79 -->
206+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L73-L76 -->
207207
``` java
208208
TextAnalyticsAsyncClient textAnalyticsClient = new TextAnalyticsClientBuilder()
209209
.credential(new AzureKeyCredential("{key}"))
@@ -215,7 +215,7 @@ TextAnalyticsAsyncClient textAnalyticsClient = new TextAnalyticsClientBuilder()
215215
Run a Text Analytics predictive model to identify the positive, negative, neutral or mixed sentiment contained in the
216216
provided document or batch of documents.
217217

218-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L126-L130 -->
218+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L123-L127 -->
219219
```java
220220
String document = "The hotel was dark and unclean. I like microsoft.";
221221
DocumentSentiment documentSentiment = textAnalyticsClient.analyzeSentiment(document);
@@ -234,7 +234,7 @@ Please refer to the service documentation for a conceptual discussion of [sentim
234234
### Detect language
235235
Run a Text Analytics predictive model to determine the language that the provided document or batch of documents are written in.
236236

237-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L137-L140 -->
237+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L134-L137 -->
238238
```java
239239
String document = "Bonjour tout le monde";
240240
DetectedLanguage detectedLanguage = textAnalyticsClient.detectLanguage(document);
@@ -247,7 +247,7 @@ Please refer to the service documentation for a conceptual discussion of [langua
247247
### Extract key phrases
248248
Run a model to identify a collection of significant phrases found in the provided document or batch of documents.
249249

250-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L171-L173 -->
250+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L168-L170 -->
251251
```java
252252
String document = "My cat might need to see a veterinarian.";
253253
System.out.println("Extracted phrases:");
@@ -261,7 +261,7 @@ Run a predictive model to identify a collection of named entities in the provide
261261
categorize those entities into categories such as person, location, or organization. For more information on available
262262
categories, see [Text Analytics Named Entity Categories][named_entities_categories].
263263

264-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L147-L150 -->
264+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L144-L147 -->
265265
```java
266266
String document = "Satya Nadella is the CEO of Microsoft";
267267
textAnalyticsClient.recognizeEntities(document).forEach(entity ->
@@ -277,7 +277,7 @@ document. It recognizes and categorizes PII entities in its input text, such as
277277
Social Security Numbers, bank account information, credit card numbers, and more. This endpoint is only supported for
278278
API versions v3.1-preview.1 and above.
279279

280-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L180-L186 -->
280+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L177-L183 -->
281281
```java
282282
String document = "My SSN is 859-98-0987";
283283
PiiEntityCollection piiEntityCollection = textAnalyticsClient.recognizePiiEntities(document);
@@ -295,7 +295,7 @@ Please refer to the service documentation for [supported PII entity types][pii_e
295295
Run a predictive model to identify a collection of entities found in the provided document or batch of documents,
296296
and include information linking the entities to their corresponding entries in a well-known knowledge base.
297297

298-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L157-L164 -->
298+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L154-L161 -->
299299

300300
```java
301301
String document = "Old Faithful is a geyser at Yellowstone Park.";
@@ -315,7 +315,7 @@ Text Analytics for health is a containerized service that extracts and labels re
315315
unstructured texts such as doctor's notes, discharge summaries, clinical documents, and electronic health records.
316316
Currently, Azure Active Directory (AAD) is not supported in the Healthcare recognition feature. In order to use this
317317
functionality, request to access public preview is required. For more information see [How to: Use Text Analytics for health][healthcare].
318-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L193-L237 -->
318+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L190-L236 -->
319319
```java
320320
List<TextDocumentInput> documents = Arrays.asList(new TextDocumentInput("0",
321321
"RECORD #333582770390100 | MH | 85986313 | | 054351 | 2/14/2001 12:00:00 AM | "
@@ -353,13 +353,15 @@ syncPoller.getFinalResult().forEach(healthcareTaskResult -> healthcareTaskResult
353353
"\t\tEntity ID in data source: %s, data source: %s.%n",
354354
healthcareEntityLink.getEntityId(), healthcareEntityLink.getName()));
355355
}
356-
Map<HealthcareEntity, HealthcareEntityRelationType> relatedHealthcareEntities =
357-
healthcareEntity.getRelatedEntities();
358-
if (!CoreUtils.isNullOrEmpty(relatedHealthcareEntities)) {
359-
relatedHealthcareEntities.forEach((relatedHealthcareEntity, entityRelationType) -> System.out.printf(
360-
"\t\tRelated entity: %s, relation type: %s.%n",
361-
relatedHealthcareEntity.getText(), entityRelationType));
362-
}
356+
});
357+
// Healthcare entity relation groups
358+
healthcareEntitiesResult.getEntityRelations().forEach(entityRelation -> {
359+
System.out.printf("\tRelation type: %s.%n", entityRelation.getRelationType());
360+
entityRelation.getRoles().forEach(role -> {
361+
final HealthcareEntity entity = role.getEntity();
362+
System.out.printf("\t\tEntity text: %s, category: %s, role: %s.%n",
363+
entity.getText(), entity.getCategory(), role.getName());
364+
});
363365
});
364366
}));
365367
```
@@ -368,7 +370,7 @@ syncPoller.getFinalResult().forEach(healthcareTaskResult -> healthcareTaskResult
368370
The `Analyze` functionality allows to choose which of the supported Text Analytics features to execute in the same
369371
set of documents. Currently, the supported features are: `entity recognition`, `key phrase extraction`, and
370372
`Personally Identifiable Information (PII) recognition`.
371-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L244-L292 -->
373+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L243-L291 -->
372374
```java
373375
List<TextDocumentInput> documents = Arrays.asList(
374376
new TextDocumentInput("0",
@@ -428,7 +430,7 @@ Text Analytics clients raise exceptions. For example, if you try to detect the l
428430
document IDs, `400` error is return that indicating bad request. In the following code snippet, the error is handled
429431
gracefully by catching the exception and display the additional information about the error.
430432

431-
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L110-L119 -->
433+
<!-- embedme ./src/samples/java/com/azure/ai/textanalytics/ReadmeSamples.java#L107-L116 -->
432434
```java
433435
List<DetectLanguageInput> documents = Arrays.asList(
434436
new DetectLanguageInput("1", "This is written in English.", "us"),

sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/implementation/AnalyzeHealthcareEntitiesResultPropertiesHelper.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import com.azure.ai.textanalytics.models.HealthcareEntity;
77
import com.azure.ai.textanalytics.models.AnalyzeHealthcareEntitiesResult;
8+
import com.azure.ai.textanalytics.models.HealthcareEntityRelation;
89
import com.azure.ai.textanalytics.models.TextAnalyticsWarning;
910
import com.azure.core.util.IterableStream;
1011

@@ -24,6 +25,8 @@ public interface AnalyzeHealthcareEntitiesResultAccessor {
2425
void setEntities(AnalyzeHealthcareEntitiesResult entitiesResult, IterableStream<HealthcareEntity> entities);
2526
void setWarnings(AnalyzeHealthcareEntitiesResult entitiesResult,
2627
IterableStream<TextAnalyticsWarning> warnings);
28+
void setEntityRelations(AnalyzeHealthcareEntitiesResult entitiesResult,
29+
IterableStream<HealthcareEntityRelation> entityRelations);
2730
}
2831

2932
/**
@@ -45,4 +48,9 @@ public static void setWarnings(AnalyzeHealthcareEntitiesResult entitiesResult,
4548
IterableStream<TextAnalyticsWarning> warnings) {
4649
accessor.setWarnings(entitiesResult, warnings);
4750
}
51+
52+
public static void setEntityRelations(AnalyzeHealthcareEntitiesResult entitiesResult,
53+
IterableStream<HealthcareEntityRelation> entityRelations) {
54+
accessor.setEntityRelations(entitiesResult, entityRelations);
55+
}
4856
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.ai.textanalytics.implementation;
5+
6+
import com.azure.ai.textanalytics.models.EntityCertainty;
7+
import com.azure.ai.textanalytics.models.EntityConditionality;
8+
import com.azure.ai.textanalytics.models.EntityAssociation;
9+
import com.azure.ai.textanalytics.models.HealthcareEntityAssertion;
10+
11+
/**
12+
* The helper class to set the non-public properties of an {@link HealthcareEntityAssertion} instance.
13+
*/
14+
public final class HealthcareEntityAssertionPropertiesHelper {
15+
private static HealthcareEntityAssertionAccessor accessor;
16+
17+
private HealthcareEntityAssertionPropertiesHelper() { }
18+
19+
/**
20+
* Type defining the methods to set the non-public properties of an {@link HealthcareEntityAssertion} instance.
21+
*/
22+
public interface HealthcareEntityAssertionAccessor {
23+
void setAssociation(HealthcareEntityAssertion assertion,
24+
EntityAssociation entityAssociation);
25+
void setCertainty(HealthcareEntityAssertion assertion,
26+
EntityCertainty entityCertainty);
27+
void setConditionality(HealthcareEntityAssertion assertion,
28+
EntityConditionality conditionality);
29+
}
30+
31+
/**
32+
* The method called from {@link HealthcareEntityAssertion} to set it's accessor.
33+
*
34+
* @param assertionAccessor The accessor.
35+
*/
36+
public static void setAccessor(final HealthcareEntityAssertionAccessor assertionAccessor) {
37+
accessor = assertionAccessor;
38+
}
39+
40+
public static void setAssociation(HealthcareEntityAssertion assertion,
41+
EntityAssociation entityAssociation) {
42+
accessor.setAssociation(assertion, entityAssociation);
43+
}
44+
45+
public static void setCertainty(HealthcareEntityAssertion assertion,
46+
EntityCertainty entityCertainty) {
47+
accessor.setCertainty(assertion, entityCertainty);
48+
}
49+
50+
public static void setConditionality(HealthcareEntityAssertion assertion,
51+
EntityConditionality conditionality) {
52+
accessor.setConditionality(assertion, conditionality);
53+
}
54+
}

sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/implementation/HealthcareEntityPropertiesHelper.java

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55

66
import com.azure.ai.textanalytics.models.EntityDataSource;
77
import com.azure.ai.textanalytics.models.HealthcareEntity;
8-
import com.azure.ai.textanalytics.models.HealthcareEntityRelationType;
8+
import com.azure.ai.textanalytics.models.HealthcareEntityAssertion;
99
import com.azure.core.util.IterableStream;
1010

11-
import java.util.Map;
12-
1311
/**
1412
* The helper class to set the non-public properties of an {@link HealthcareEntity} instance.
1513
*/
@@ -23,15 +21,14 @@ private HealthcareEntityPropertiesHelper() { }
2321
*/
2422
public interface HealthcareEntityAccessor {
2523
void setText(HealthcareEntity healthcareEntity, String text);
24+
void setNormalizedText(HealthcareEntity healthcareEntity, String normalizedText);
2625
void setCategory(HealthcareEntity healthcareEntity, String category);
2726
void setSubcategory(HealthcareEntity healthcareEntity, String subcategory);
2827
void setConfidenceScore(HealthcareEntity healthcareEntity, double confidenceScore);
28+
void setDataSources(HealthcareEntity healthcareEntity, IterableStream<EntityDataSource> dataSources);
29+
void setAssertion(HealthcareEntity healthcareEntity, HealthcareEntityAssertion assertion);
2930
void setOffset(HealthcareEntity healthcareEntity, int offset);
3031
void setLength(HealthcareEntity healthcareEntity, int length);
31-
void setNegated(HealthcareEntity healthcareEntity, boolean negated);
32-
void setDataSources(HealthcareEntity healthcareEntity, IterableStream<EntityDataSource> dataSources);
33-
void setRelatedEntities(HealthcareEntity healthcareEntity,
34-
Map<HealthcareEntity, HealthcareEntityRelationType> relatedEntities);
3532
}
3633

3734
/**
@@ -59,25 +56,24 @@ public static void setConfidenceScore(HealthcareEntity healthcareEntity, double
5956
accessor.setConfidenceScore(healthcareEntity, confidenceScore);
6057
}
6158

62-
public static void setOffset(HealthcareEntity healthcareEntity, int offset) {
63-
accessor.setOffset(healthcareEntity, offset);
59+
public static void setDataSources(HealthcareEntity healthcareEntity,
60+
IterableStream<EntityDataSource> dataSources) {
61+
accessor.setDataSources(healthcareEntity, dataSources);
6462
}
6563

66-
public static void setLength(HealthcareEntity healthcareEntity, int length) {
67-
accessor.setLength(healthcareEntity, length);
64+
public static void setNormalizedText(HealthcareEntity healthcareEntity, String normalizedText) {
65+
accessor.setNormalizedText(healthcareEntity, normalizedText);
6866
}
6967

70-
public static void setNegated(HealthcareEntity healthcareEntity, boolean negated) {
71-
accessor.setNegated(healthcareEntity, negated);
68+
public static void setAssertion(HealthcareEntity healthcareEntity, HealthcareEntityAssertion assertion) {
69+
accessor.setAssertion(healthcareEntity, assertion);
7270
}
7371

74-
public static void setDataSources(HealthcareEntity healthcareEntity,
75-
IterableStream<EntityDataSource> dataSources) {
76-
accessor.setDataSources(healthcareEntity, dataSources);
72+
public static void setOffset(HealthcareEntity healthcareEntity, int offset) {
73+
accessor.setOffset(healthcareEntity, offset);
7774
}
7875

79-
public static void setRelatedEntities(HealthcareEntity healthcareEntity,
80-
Map<HealthcareEntity, HealthcareEntityRelationType> relatedEntities) {
81-
accessor.setRelatedEntities(healthcareEntity, relatedEntities);
76+
public static void setLength(HealthcareEntity healthcareEntity, int length) {
77+
accessor.setLength(healthcareEntity, length);
8278
}
8379
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.ai.textanalytics.implementation;
5+
6+
import com.azure.ai.textanalytics.models.HealthcareEntityRelation;
7+
import com.azure.ai.textanalytics.models.HealthcareEntityRelationRole;
8+
import com.azure.ai.textanalytics.models.HealthcareEntityRelationType;
9+
import com.azure.core.util.IterableStream;
10+
11+
/**
12+
* The helper class to set the non-public properties of an {@link HealthcareEntityRelation} instance.
13+
*/
14+
public final class HealthcareEntityRelationPropertiesHelper {
15+
private static HealthcareEntityRelationAccessor accessor;
16+
17+
private HealthcareEntityRelationPropertiesHelper() { }
18+
19+
/**
20+
* Type defining the methods to set the non-public properties of an {@link HealthcareEntityRelation} instance.
21+
*/
22+
public interface HealthcareEntityRelationAccessor {
23+
void setRelationType(HealthcareEntityRelation healthcareEntityRelation,
24+
HealthcareEntityRelationType relationType);
25+
void setRoles(HealthcareEntityRelation healthcareEntityRelation,
26+
IterableStream<HealthcareEntityRelationRole> roles);
27+
}
28+
29+
/**
30+
* The method called from {@link HealthcareEntityRelation} to set it's accessor.
31+
*
32+
* @param entityRelationAccessor The accessor.
33+
*/
34+
public static void setAccessor(final HealthcareEntityRelationAccessor entityRelationAccessor) {
35+
accessor = entityRelationAccessor;
36+
}
37+
38+
public static void setRelationType(HealthcareEntityRelation healthcareEntityRelation,
39+
HealthcareEntityRelationType relationType) {
40+
accessor.setRelationType(healthcareEntityRelation, relationType);
41+
}
42+
43+
public static void setRoles(HealthcareEntityRelation healthcareEntityRelation,
44+
IterableStream<HealthcareEntityRelationRole> roles) {
45+
accessor.setRoles(healthcareEntityRelation, roles);
46+
}
47+
}

0 commit comments

Comments
 (0)