Skip to content

Commit ce0f5d5

Browse files
gguusslesv
authored andcommitted
Adds example usage and tests for v1beta2 (#622)
* Adds example usage and tests for v1beta2 * License dates on new files, NPE fix, and renames on some methods. * Updates copyright
1 parent 04e73bb commit ce0f5d5

File tree

4 files changed

+320
-0
lines changed

4 files changed

+320
-0
lines changed

language/analysis/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ java -cp target/language-entities-1.0-jar-with-dependencies.jar \
6868
"The quick brown fox jumped over the lazy dog."
6969
```
7070

71+
Analyze sentiment Beta
72+
```
73+
java -cp target/language-entities-1.0-jar-with-dependencies.jar \
74+
com.google.cloud.language.samples.AnalyzeBeta sentiment "Ich habe eine wundervolle Zeit." "DE"
75+
```
76+
77+
7178
Included with the sample are `demo.sh` and `demo.bat` which show additional
7279
examples of usage.
7380

language/analysis/demo-beta.sh

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/bash
2+
#
3+
# Demonstrates how to run the AnalyzeBeta sample.
4+
5+
##########################################################################
6+
# Copyright 2017 Google Inc.
7+
#
8+
# Licensed under the Apache License, Version 2.0 (the "License");
9+
# you may not use this file except in compliance with the License.
10+
# You may obtain a copy of the License at
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
##########################################################################
19+
20+
21+
#######################################
22+
# Performs a language operation on the given text or GCS object.
23+
# Globals:
24+
# None
25+
# Arguments:
26+
# $1 The operation to perform, either entities, sentiment, or syntax.
27+
# $2 The text or GCS object to operate on.
28+
# Returns:
29+
# None
30+
#######################################
31+
function run_nl() {
32+
local main_class=com.google.cloud.language.samples.AnalyzeBeta
33+
local jar_file=target/language-entities-1.0-jar-with-dependencies.jar
34+
java -cp ${jar_file} ${main_class} "$1" "$2"
35+
}
36+
37+
#######################################
38+
# Exercises the sample code on various example text and GCS objects.
39+
# Globals:
40+
# None
41+
# Arguments:
42+
# None
43+
# Returns:
44+
# None
45+
#######################################
46+
function run_nl_all() {
47+
local quote_de="Bananen sind die köstlichsten Früchte, ich liebe sie zu
48+
essen. Ich mag sie so sehr wie Ananas."
49+
local quote="Larry Page, Google's co-founder, once described the 'perfect
50+
search engine' as something that 'understands exactly what you mean and
51+
gives you back exactly what you want.' Since he spoke those words Google
52+
has grown to offer products beyond search, but the spirit of what he said
53+
remains."
54+
local gs_path="gs://cloud-samples-tests/natural-language/gettysburg.txt"
55+
56+
run_nl entities-sentiment "${quote}"
57+
run_nl entities-sentiment "${gs_path}"
58+
run_nl sentiment "${quote_de}" "DE"
59+
}
60+
61+
run_nl_all
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* Copyright 2017 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.language.samples;
18+
19+
import com.google.cloud.language.spi.v1beta2.LanguageServiceClient;
20+
21+
import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentRequest;
22+
import com.google.cloud.language.v1beta2.AnalyzeEntitySentimentResponse;
23+
import com.google.cloud.language.v1beta2.AnalyzeSentimentResponse;
24+
import com.google.cloud.language.v1beta2.Document;
25+
import com.google.cloud.language.v1beta2.Document.Type;
26+
import com.google.cloud.language.v1beta2.EncodingType;
27+
import com.google.cloud.language.v1beta2.Entity;
28+
import com.google.cloud.language.v1beta2.EntityMention;
29+
import com.google.cloud.language.v1beta2.Sentiment;
30+
import com.google.cloud.language.v1beta2.Token;
31+
import com.google.protobuf.Descriptors;
32+
33+
import java.io.IOException;
34+
import java.io.PrintStream;
35+
import java.security.GeneralSecurityException;
36+
import java.util.List;
37+
import java.util.Map;
38+
39+
/**
40+
* A sample application that uses the Natural Language API to perform
41+
* entity, sentiment and syntax analysis.
42+
*/
43+
public class AnalyzeBeta {
44+
private final LanguageServiceClient languageApi;
45+
46+
/**
47+
* Constructs a {@link Analyze} which connects to the Cloud Natural Language API.
48+
*/
49+
public AnalyzeBeta(LanguageServiceClient languageApi) {
50+
this.languageApi = languageApi;
51+
}
52+
53+
54+
/**
55+
* Detects entities,sentiment and syntax in a document using the Natural Language API.
56+
*/
57+
public static void main(String[] args) throws IOException, GeneralSecurityException {
58+
if (args.length < 2 || args.length > 4) {
59+
System.err.println("Usage:");
60+
System.err.printf(
61+
"\tjava %s \"command\" \"text to analyze\" \"language\" \n",
62+
Analyze.class.getCanonicalName());
63+
System.exit(1);
64+
}
65+
String command = args[0];
66+
String text = args[1];
67+
String lang = null;
68+
if (args.length > 2) {
69+
lang = args[2];
70+
}
71+
72+
AnalyzeBeta app = new AnalyzeBeta(LanguageServiceClient.create());
73+
74+
if (command.equals("entities-sentiment")) {
75+
if (text.startsWith("gs://")) {
76+
printEntities(System.out, app.entitySentimentFile(text));
77+
} else {
78+
printEntities(System.out, app.entitySentimentText(text));
79+
}
80+
} else if (command.equals("sentiment")) {
81+
printSentiment(System.out, app.analyzeSentimentText(text, lang));
82+
}
83+
}
84+
85+
/**
86+
* Print the Sentiment {@code sentiment}.
87+
*/
88+
public static void printSentiment(PrintStream out, Sentiment sentiment) {
89+
if (sentiment == null) {
90+
out.println("No sentiment found");
91+
return;
92+
}
93+
out.println("Found sentiment.");
94+
out.printf("\tMagnitude: %.3f\n", sentiment.getMagnitude());
95+
out.printf("\tScore: %.3f\n", sentiment.getScore());
96+
}
97+
98+
/**
99+
* Print a list of {@code entities}.
100+
*/
101+
public static void printEntities(PrintStream out, List<Entity> entities) {
102+
if (entities == null || entities.size() == 0) {
103+
out.println("No entities found.");
104+
return;
105+
}
106+
out.printf("Found %d entit%s.\n", entities.size(), entities.size() == 1 ? "y" : "ies");
107+
for (Entity entity : entities) {
108+
out.printf("----\n\"%s\"\n", entity.getName());
109+
out.printf("\tSalience: %.3f\n", entity.getSalience());
110+
out.printf("\tSentiment Magnitude: %.3f\n", entity.getSentiment().getMagnitude());
111+
out.printf("\tSentiment Score: %.3f\n", entity.getSentiment().getScore());
112+
out.printf("\tType: %s\n", entity.getType());
113+
if (entity.getMetadataMap() != null) {
114+
for (Map.Entry<String, String> metadata : entity.getMetadataMap().entrySet()) {
115+
out.printf("\tMetadata: %s = %s\n", metadata.getKey(), metadata.getValue());
116+
}
117+
}
118+
if (entity.getMentionsList() != null) {
119+
for (EntityMention mention : entity.getMentionsList()) {
120+
for (Map.Entry<Descriptors.FieldDescriptor, Object> mentionSetMember :
121+
mention.getAllFields().entrySet()) {
122+
out.printf("\tMention: %s = %s\n", mentionSetMember.getKey(),
123+
mentionSetMember.getValue());
124+
}
125+
}
126+
}
127+
}
128+
}
129+
130+
/**
131+
* Gets {@link Sentiment} from the string {@code text}.
132+
*/
133+
public Sentiment analyzeSentimentText(String text, String lang) throws IOException {
134+
if (lang == null || lang.length() < 2) {
135+
lang = "EN";
136+
}
137+
138+
// Note: This does not work on App Engine standard.
139+
Document doc = Document.newBuilder()
140+
.setLanguage(lang)
141+
.setContent(text).setType(Type.PLAIN_TEXT).build();
142+
AnalyzeSentimentResponse response = languageApi.analyzeSentiment(doc);
143+
return response.getDocumentSentiment();
144+
}
145+
146+
/**
147+
* Gets {@link Entity}s from the string {@code text} with sentiment.
148+
*/
149+
public List<Entity> entitySentimentText(String text) throws IOException {
150+
// Note: This does not work on App Engine standard.
151+
Document doc = Document.newBuilder()
152+
.setContent(text).setType(Type.PLAIN_TEXT).build();
153+
AnalyzeEntitySentimentRequest request = AnalyzeEntitySentimentRequest.newBuilder()
154+
.setDocument(doc)
155+
.setEncodingType(EncodingType.UTF16).build();
156+
AnalyzeEntitySentimentResponse response = languageApi.analyzeEntitySentiment(request);
157+
return response.getEntitiesList();
158+
}
159+
160+
/**
161+
* Gets {@link Entity}s from the contents of the object at the given GCS {@code path}
162+
* with sentiment.
163+
*/
164+
public List<Entity> entitySentimentFile(String path) throws IOException {
165+
// Note: This does not work on App Engine standard.
166+
Document doc = Document.newBuilder()
167+
.setGcsContentUri(path).setType(Type.PLAIN_TEXT).build();
168+
AnalyzeEntitySentimentRequest request = AnalyzeEntitySentimentRequest.newBuilder()
169+
.setDocument(doc)
170+
.setEncodingType(EncodingType.UTF16).build();
171+
AnalyzeEntitySentimentResponse response = languageApi.analyzeEntitySentiment(request);
172+
return response.getEntitiesList();
173+
}
174+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2017 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.language.samples;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
21+
import com.google.cloud.language.spi.v1beta2.LanguageServiceClient;
22+
import com.google.cloud.language.v1beta2.Entity;
23+
import com.google.cloud.language.v1beta2.Sentiment;
24+
25+
import org.junit.Before;
26+
import org.junit.Test;
27+
import org.junit.runner.RunWith;
28+
import org.junit.runners.JUnit4;
29+
30+
import java.util.List;
31+
import java.util.stream.Collectors;
32+
33+
/**
34+
* Integration (system) tests for {@link Analyze}.
35+
*/
36+
@RunWith(JUnit4.class)
37+
@SuppressWarnings("checkstyle:abbreviationaswordinname")
38+
public class AnalyzeBetaIT {
39+
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
40+
private static final String BUCKET = PROJECT_ID;
41+
42+
private AnalyzeBeta analyzeApp;
43+
44+
@Before public void setup() throws Exception {
45+
analyzeApp = new AnalyzeBeta(LanguageServiceClient.create());
46+
}
47+
48+
@Test public void analyzeSentiment_returnPositiveGerman() throws Exception {
49+
// Act
50+
Sentiment sentiment =
51+
analyzeApp.analyzeSentimentText(
52+
"Ich hatte die schönste Erfahrung mit euch allen.", "DE");
53+
54+
// Assert
55+
assertThat((double)sentiment.getMagnitude()).isGreaterThan(0.0);
56+
assertThat((double)sentiment.getScore()).isGreaterThan(0.0);
57+
}
58+
59+
@Test public void analyzeSyntax_entitySentimentText() throws Exception {
60+
List<Entity> entities = analyzeApp.entitySentimentText("Oranges, grapes, and apples can be " +
61+
"found in the cafeterias located in Mountain View, Seattle, and London.");
62+
63+
List<String> got = entities.stream().map(e -> e.getName()).collect(Collectors.toList());
64+
65+
// Assert
66+
assertThat(got).named("entity names").contains("Seattle");
67+
}
68+
69+
@Test public void analyzeSyntax_entitySentimentFile() throws Exception {
70+
List<Entity> entities =
71+
analyzeApp.entitySentimentFile("gs://" + BUCKET + "/natural-language/gettysburg.txt");
72+
73+
List<String> got = entities.stream().map(e -> e.getName()).collect(Collectors.toList());
74+
75+
// Assert
76+
assertThat(got).named("entity names").contains("God");
77+
}
78+
}

0 commit comments

Comments
 (0)