Java Sample Code modified to modernized code and easy to understand (#1175)

This is the update pull request of 
https://github.com/microsoft/semantic-kernel/pull/1128

I closed the previous Pull Request #1128.

1 Modified getConfigValue()
1.1: local variable name from apiKey to propertyValue 1.2: Use NIO.2
libraries instead of old FileInputStream 1.3: modified Exception throw
code

2. Defined TEXT_TO_SUMMARIZE Instead of local variable definition, I
defined static final field

3. As a sample, I wrote non blocking code for Async operation Previously
it was wrote as
summarize.invokeAsync(TEXT_TO_SUMMARIZE).block() to subscribe()

4. In order to show the result, I added following code to receive the
result. try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
LOGGER.warn("Interrupted : {}", e.getMessage());
Thread.currentThread().interrupt();
}

5. Code Structure modified: I modified the code structure of both
'InlineFunctionExample.java' and
'InlineFunctionWithPreBuiltSkillExample.java' to be as similar as
possible, making them easier to compare.

---------

Co-authored-by: Mark Wallace <[email protected]>
This commit is contained in:
Yoshio Terada
2023-05-24 11:23:06 +01:00
committed by GitHub
co-authored by Mark Wallace
parent 2a70a69275
commit 2223a8b319
2 changed files with 191 additions and 153 deletions
@@ -7,7 +7,6 @@ import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelConfig;
import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
@@ -20,107 +19,129 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CountDownLatch;
public class InlineFunctionExample {
public static final String AZURE_CONF_PROPERTIES = "conf.properties";
private static final Logger LOGGER = LoggerFactory.getLogger(InlineFunctionExample.class);
private static final String MODEL = "text-davinci-003";
public static String getToken(String configName) throws IOException {
private static String API_KEY = "";
private static String ENDPOINT = "";
static{
try {
API_KEY = getToken(AZURE_CONF_PROPERTIES);
ENDPOINT = getEndpoint(AZURE_CONF_PROPERTIES);
} catch (IOException e) {
throw new ExceptionInInitializerError ("Error reading config file or properties. " + e.getMessage());
}
}
private static final String TEXT_TO_SUMMARIZE = """
Demo (ancient Greek poet)
From Wikipedia, the free encyclopedia
Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
Roman period, known for a single epigram, engraved upon the Colossus of
Memnon, which bears her name. She speaks of herself therein as a lyric
poetess dedicated to the Muses, but nothing is known of her life.[1]
Identity
Demo was evidently Greek, as her name, a traditional epithet of Demeter,
signifies. The name was relatively common in the Hellenistic world, in
Egypt and elsewhere, and she cannot be further identified. The date of her
visit to the Colossus of Memnon cannot be established with certainty, but
internal evidence on the left leg suggests her poem was inscribed there at
some point in or after AD 196.[2]
Epigram
There are a number of graffiti inscriptions on the Colossus of Memnon.
Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
couplets, entitled and presumably authored by "Demo" or "Damo" (the
Greek inscription is difficult to read), is a dedication to the Muses.[2]
The poem is traditionally published with the works of Balbilla, though the
internal evidence suggests a different author.[1]
In the poem, Demo explains that Memnon has shown her special respect. In
return, Demo offers the gift for poetry, as a gift to the hero. At the end
of this epigram, she addresses Memnon, highlighting his divine status by
recalling his strength and holiness.[2]
Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
dialect. The language indicates she was knowledgeable in Homeric
poetry—'bearing a pleasant gift', for example, alludes to the use of that
phrase throughout the Iliad and Odyssey.[a][2];
""";
private static String getToken(String configName) throws IOException {
return getConfigValue(configName, "token");
}
public static String getEndpoint(String configName) throws IOException {
private static String getEndpoint(String configName) throws IOException {
return getConfigValue(configName, "endpoint");
}
private static String getConfigValue(String configName, String propertyName)
throws IOException {
String propertyValue = "";
Path configPath = Paths.get(System.getProperty("user.home"), ".oai", configName);
Properties props = new Properties();
try (var reader = Files.newBufferedReader(configPath)) {
props.load(reader);
propertyValue = props.getProperty(propertyName);
if (propertyValue == null || propertyValue.isEmpty()) {
throw new IOException("No property for: " + propertyName + " in " + configPath);
}
} catch (IOException e) {
LOGGER.error("Failed to read config file: " + configPath);
throw e;
throw new IOException("Please create a file at " + configPath, e);
}
String apiKey = props.getProperty(propertyName);
if (apiKey == null) {
LOGGER.error("NO PROPERTY " + propertyName);
return "";
}
return apiKey;
return propertyValue;
}
public static void main(String[] args) throws IOException {
String apiKey = getToken(AZURE_CONF_PROPERTIES);
OpenAIAsyncClient client =
new AzureOpenAIClient(
new OpenAIClientBuilder()
.endpoint(getEndpoint(AZURE_CONF_PROPERTIES))
.credential(new AzureKeyCredential(apiKey))
.buildAsyncClient());
public static void main(String[] args) {
OpenAIAsyncClient client = new AzureOpenAIClient(
new OpenAIClientBuilder()
.endpoint(ENDPOINT)
.credential(new AzureKeyCredential(API_KEY))
.buildAsyncClient());
TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, MODEL);
String prompt = "{{$input}}\n" + "Summarize the content above.";
KernelConfig kernelConfig =
new KernelConfig.Builder()
.addTextCompletionService(MODEL, kernel -> textCompletion)
.build();
KernelConfig kernelConfig = new KernelConfig.Builder()
.addTextCompletionService(MODEL, kernel -> textCompletion)
.build();
Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
String prompt = "{{$input}}\n" + "Summarize the content above.";
CompletionSKFunction summarize = kernel.getSemanticFunctionBuilder()
.createFunction(
prompt,
"summarize",
null,
null,
new PromptTemplateConfig.CompletionConfig(
0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
CompletionSKFunction summarize =
kernel.getSemanticFunctionBuilder()
.createFunction(
prompt,
"summarize",
null,
null,
new PromptTemplateConfig.CompletionConfig(
0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
if (summarize == null) {
LOGGER.error("Null function");
return;
}
String text =
"""
Demo (ancient Greek poet)
From Wikipedia, the free encyclopedia
Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
Roman period, known for a single epigram, engraved upon the Colossus of
Memnon, which bears her name. She speaks of herself therein as a lyric
poetess dedicated to the Muses, but nothing is known of her life.[1]
Identity
Demo was evidently Greek, as her name, a traditional epithet of Demeter,
signifies. The name was relatively common in the Hellenistic world, in
Egypt and elsewhere, and she cannot be further identified. The date of her
visit to the Colossus of Memnon cannot be established with certainty, but
internal evidence on the left leg suggests her poem was inscribed there at
some point in or after AD 196.[2]
Epigram
There are a number of graffiti inscriptions on the Colossus of Memnon.
Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
couplets, entitled and presumably authored by "Demo" or "Damo" (the
Greek inscription is difficult to read), is a dedication to the Muses.[2]
The poem is traditionally published with the works of Balbilla, though the
internal evidence suggests a different author.[1]
In the poem, Demo explains that Memnon has shown her special respect. In
return, Demo offers the gift for poetry, as a gift to the hero. At the end
of this epigram, she addresses Memnon, highlighting his divine status by
recalling his strength and holiness.[2]
Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
dialect. The language indicates she was knowledgeable in Homeric
poetry—'bearing a pleasant gift', for example, alludes to the use of that
phrase throughout the Iliad and Odyssey.[a][2];
""";
CompletionSKContext context = summarize.invokeAsync(text).block();
if (context != null) {
LOGGER.info("Result: " + context.getResult());
} else {
LOGGER.error("Null result");
CountDownLatch cdl = new CountDownLatch(1);
summarize.invokeAsync(TEXT_TO_SUMMARIZE).subscribe(
context -> {
LOGGER.info("Result: {} ", context.getResult());
},
error -> {
LOGGER.error("Error: {} ", error.getMessage());
cdl.countDown();
},
() -> {
LOGGER.info("Completed");
cdl.countDown();
});
try{
cdl.await();
}catch(InterruptedException e){
LOGGER.error("Error: {} ", e.getMessage());
}
}
}
@@ -7,57 +7,68 @@ import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelConfig;
import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.rmi.RemoteException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CountDownLatch;
public class InlineFunctionWithPreBuiltSkillExample {
public static final String AZURE_CONF_PROPERTIES = "conf.properties";
private static final Logger LOGGER =
LoggerFactory.getLogger(InlineFunctionWithPreBuiltSkillExample.class);
private static final Logger LOGGER = LoggerFactory.getLogger(InlineFunctionWithPreBuiltSkillExample.class);
private static final String MODEL = "text-davinci-003";
private static final String TEXT_TO_SUMMARIZE =
"Demo (ancient Greek poet)\n"
+ "From Wikipedia, the free encyclopedia\n"
+ "Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the"
+ " Roman period, known for a single epigram, engraved upon the Colossus of"
+ " Memnon, which bears her name. She speaks of herself therein as a lyric"
+ " poetess dedicated to the Muses, but nothing is known of her life.[1]\n"
+ "Identity\n"
+ "Demo was evidently Greek, as her name, a traditional epithet of Demeter,"
+ " signifies. The name was relatively common in the Hellenistic world, in"
+ " Egypt and elsewhere, and she cannot be further identified. The date of her"
+ " visit to the Colossus of Memnon cannot be established with certainty, but"
+ " internal evidence on the left leg suggests her poem was inscribed there at"
+ " some point in or after AD 196.[2]\n"
+ "Epigram\n"
+ "There are a number of graffiti inscriptions on the Colossus of Memnon."
+ " Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac"
+ " couplets, entitled and presumably authored by \"Demo\" or \"Damo\" (the"
+ " Greek inscription is difficult to read), is a dedication to the Muses.[2]"
+ " The poem is traditionally published with the works of Balbilla, though the"
+ " internal evidence suggests a different author.[1]\n"
+ "In the poem, Demo explains that Memnon has shown her special respect. In"
+ " return, Demo offers the gift for poetry, as a gift to the hero. At the end"
+ " of this epigram, she addresses Memnon, highlighting his divine status by"
+ " recalling his strength and holiness.[2]\n"
+ "Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic"
+ " dialect. The language indicates she was knowledgeable in Homeric"
+ " poetry—'bearing a pleasant gift', for example, alludes to the use of that"
+ " phrase throughout the Iliad and Odyssey.[a][2]\n";
private static String API_KEY = "";
private static String ENDPOINT = "";
static{
try {
API_KEY = getToken(AZURE_CONF_PROPERTIES);
ENDPOINT = getEndpoint(AZURE_CONF_PROPERTIES);
} catch (IOException e) {
throw new ExceptionInInitializerError ("Error reading config file or properties. " + e.getMessage());
}
}
private static final String TEXT_TO_SUMMARIZE = """
Demo (ancient Greek poet)
From Wikipedia, the free encyclopedia
Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
Roman period, known for a single epigram, engraved upon the Colossus of
Memnon, which bears her name. She speaks of herself therein as a lyric
poetess dedicated to the Muses, but nothing is known of her life.[1]
Identity
Demo was evidently Greek, as her name, a traditional epithet of Demeter,
signifies. The name was relatively common in the Hellenistic world, in
Egypt and elsewhere, and she cannot be further identified. The date of her
visit to the Colossus of Memnon cannot be established with certainty, but
internal evidence on the left leg suggests her poem was inscribed there at
some point in or after AD 196.[2]
Epigram
There are a number of graffiti inscriptions on the Colossus of Memnon.
Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
couplets, entitled and presumably authored by "Demo" or "Damo" (the
Greek inscription is difficult to read), is a dedication to the Muses.[2]
The poem is traditionally published with the works of Balbilla, though the
internal evidence suggests a different author.[1]
In the poem, Demo explains that Memnon has shown her special respect. In
return, Demo offers the gift for poetry, as a gift to the hero. At the end
of this epigram, she addresses Memnon, highlighting his divine status by
recalling his strength and holiness.[2]
Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
dialect. The language indicates she was knowledgeable in Homeric
poetry—'bearing a pleasant gift', for example, alludes to the use of that
phrase throughout the Iliad and Odyssey.[a][2];
""";
public static String getToken(String configName) throws IOException {
return getConfigValue(configName, "token");
@@ -69,65 +80,71 @@ public class InlineFunctionWithPreBuiltSkillExample {
private static String getConfigValue(String configName, String propertyName)
throws IOException {
String home = new File(System.getProperty("user.home")).getAbsolutePath();
try (FileInputStream fis = new FileInputStream(home + "/.oai/" + configName)) {
Properties props = new Properties();
props.load(fis);
String apiKey = props.getProperty(propertyName);
if (apiKey == null) {
System.err.println("NO PROPERTY " + propertyName);
return "";
String propertyValue = "";
Path configPath = Paths.get(System.getProperty("user.home"), ".oai", configName);
Properties props = new Properties();
try (var reader = Files.newBufferedReader(configPath)) {
props.load(reader);
propertyValue = props.getProperty(propertyName);
if (propertyValue == null || propertyValue.isEmpty()) {
throw new IOException("No property for: " + propertyName + " in " + configPath);
}
return apiKey;
} catch (IOException e) {
throw new IOException("Please create a file at " + configPath, e);
}
return propertyValue;
}
public static void main(String[] args) throws IOException {
String apiKey = getToken(AZURE_CONF_PROPERTIES);
OpenAIAsyncClient client =
new AzureOpenAIClient(
new OpenAIClientBuilder()
.endpoint(getEndpoint(AZURE_CONF_PROPERTIES))
.credential(new AzureKeyCredential(apiKey))
.buildAsyncClient());
public static void main(String[] args) {
OpenAIAsyncClient client = new AzureOpenAIClient(
new OpenAIClientBuilder()
.endpoint(ENDPOINT)
.credential(new AzureKeyCredential(API_KEY))
.buildAsyncClient());
TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, MODEL);
String prompt = "{{$input}}\n" + "Summarize the content above.";
String prompt = "{{$input}}\nSummarize the content above.";
CompletionSKFunction summarizeFunc = SKBuilders.completionFunctions()
.createFunction(
prompt,
"summarize",
null,
null,
new PromptTemplateConfig.CompletionConfig(
0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
CompletionSKFunction summarizeFunc =
SKBuilders.completionFunctions()
.createFunction(
prompt,
"summarize",
null,
null,
new PromptTemplateConfig.CompletionConfig(
0.2, 0.5, 0, 0, 2000, new ArrayList<>()));
KernelConfig kernelConfig =
new KernelConfig.Builder()
.addTextCompletionService(MODEL, kernel -> textCompletion)
.addSkill(summarizeFunc)
.build();
KernelConfig kernelConfig = new KernelConfig.Builder()
.addTextCompletionService(MODEL, kernel -> textCompletion)
.addSkill(summarizeFunc)
.build();
Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
CompletionSKFunction summarize =
kernel.getSkills().getFunction("summarize", CompletionSKFunction.class);
CompletionSKFunction summarize = kernel.getSkills().getFunction("summarize", CompletionSKFunction.class);
if (summarize == null) {
throw new RemoteException("No function");
LOGGER.error("Null function");
return;
}
CompletionSKContext context = summarize.invokeAsync(TEXT_TO_SUMMARIZE).block();
if (context != null) {
LOGGER.info("Result: " + context.getResult());
} else {
LOGGER.error("Null result");
CountDownLatch cdl = new CountDownLatch(1);
summarize.invokeAsync(TEXT_TO_SUMMARIZE).subscribe(
context -> {
LOGGER.info("Result: {} ", context.getResult());
},
error -> {
LOGGER.error("Error: {} ", error.getMessage());
cdl.countDown();
},
() -> {
LOGGER.info("Completed");
cdl.countDown();
});
try{
cdl.await();
}catch(InterruptedException e){
LOGGER.error("Error: {} ", e.getMessage());
}
}
}