Java: Allow Semantic Kernel to obtain credentials via Managed identity and azure cli. Fix some tests (#3298)

### Motivation and Context

<!-- Thank you for your contribution to the semantic-kernel repo!
Please help reviewers and future users, providing the following
information:
  1. Why is this change required?
  2. What problem does it solve?
  3. What scenario does it contribute to?
  4. If it fixes an open issue, please link to the issue here.
-->

### Description

<!-- Describe your changes, the overall approach, the underlying design.
These notes will help understanding how your code works. Thanks! -->

### Contribution Checklist

<!-- Before submitting this PR, please make sure: -->

- [ ] The code builds clean without any errors or warnings
- [ ] The PR follows the [SK Contribution
Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
and the [pre-submission formatting
script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts)
raises no violations
- [ ] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄
This commit is contained in:
John Oliver
2023-11-07 12:00:42 +00:00
committed by GitHub
parent a69702917d
commit 3f894eada1
17 changed files with 355 additions and 152 deletions
@@ -20,6 +20,11 @@
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-api</artifactId>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -28,6 +29,16 @@
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-search-documents</artifactId>
<exclusions>
<!--
TODO: Remove pending a fix for:
https://github.com/Azure/azure-sdk-for-java/issues/36054
-->
<exclusion>
<groupId>com.azure</groupId>
<artifactId>azure-core-serializer-json-jackson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
@@ -28,5 +28,10 @@
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,97 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.connectors.ai.openai.util;
import com.azure.core.credential.TokenCredential;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import java.io.File;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.slf4j.Logger;
/** Defines the type of azure credential used for authenticating to this resource */
public enum AzureCredentialType {
KEY {
@Nullable
@Override
public TokenCredential getTokenCredential() {
return null;
}
},
MANAGED_IDENTITY {
@Nullable
@Override
public TokenCredential getTokenCredential() {
if (classIsPresent("com.azure.identity.ManagedIdentityCredentialBuilder")) {
return new com.azure.identity.ManagedIdentityCredentialBuilder().build();
}
return null;
}
},
AZURE_CLI {
@Nullable
@Override
public TokenCredential getTokenCredential() {
if (classIsPresent("com.azure.identity.AzureCliCredentialBuilder")) {
return new com.azure.identity.AzureCliCredentialBuilder().build();
}
return null;
}
};
private static final Logger LOGGER =
org.slf4j.LoggerFactory.getLogger(AzureCredentialType.class);
/**
* Create a TokenCredential instance.
*
* @return TokenCredential instance or null if not found
*/
@Nullable
public abstract TokenCredential getTokenCredential();
/**
* Create a TokenCredential instance, uses the default settings locations (see {@link
* SettingsMap} for details).
*
* <p>Set the 'client.azureopenai.credentialtype' environment variable within settings to
* determine the token type. {@link AzureCredentialType}
*
* @return TokenCredential instance or null if not found
*/
@Nullable
public static TokenCredential getCredential() throws ConfigurationException {
return getCredential((List<File>) null);
}
/**
* Create a TokenCredential instance, uses the provided settings locations (see {@link
* SettingsMap} for details).
*
* <p>Set the 'client.azureopenai.credentialtype' environment variable within settings to
* determine the token type. {@link AzureCredentialType}
*
* @return TokenCredential instance or null if not found
*/
@Nullable
public static TokenCredential getCredential(@Nullable List<File> propertyFileLocations)
throws ConfigurationException {
Map<String, String> settings = OpenAIClientProvider.getSettings(propertyFileLocations);
return new AzureOpenAISettings(settings)
.getAzureOpenAiCredentialsType()
.getTokenCredential();
}
private static boolean classIsPresent(String className) {
try {
Class.forName(className, false, Thread.currentThread().getContextClassLoader());
return true;
} catch (ClassNotFoundException e) {
LOGGER.warn(
"Requested Managed Identity or Azure CLI authentication, however the"
+ " azure-identity library is not available on the classpath");
return false;
}
}
}
@@ -7,15 +7,18 @@ import javax.annotation.Nullable;
/** Settings for Azure OpenAI client */
public class AzureOpenAISettings extends AbstractOpenAIClientSettings {
private static final String DEFAULT_SETTINGS_PREFIX = "client.azureopenai";
private static final String AZURE_OPEN_AI_ENDPOINT_SUFFIX = "endpoint";
private static final String AZURE_OPEN_AI_DEPLOYMENT_NAME_SUFFIX = "deploymentname";
private static final String AZURE_OPEN_AI_CREDENTIALS_TYPE = "credentialtype";
@Nullable private final String key;
@Nullable private final String endpoint;
@Nullable private final String deploymentName;
@Nullable private final AzureCredentialType credentialType;
private final String settingsPrefix;
public AzureOpenAISettings(Map<String, String> settings) {
@@ -27,6 +30,12 @@ public class AzureOpenAISettings extends AbstractOpenAIClientSettings {
key = settings.get(settingsPrefix + "." + KEY_SUFFIX);
endpoint = settings.get(settingsPrefix + "." + AZURE_OPEN_AI_ENDPOINT_SUFFIX);
deploymentName = settings.get(settingsPrefix + "." + AZURE_OPEN_AI_DEPLOYMENT_NAME_SUFFIX);
String credType =
settings.getOrDefault(settingsPrefix + "." + AZURE_OPEN_AI_CREDENTIALS_TYPE, "key")
.toUpperCase();
credentialType = AzureCredentialType.valueOf(credType);
}
/**
@@ -65,6 +74,10 @@ public class AzureOpenAISettings extends AbstractOpenAIClientSettings {
return key;
}
public AzureCredentialType getAzureOpenAiCredentialsType() {
return credentialType;
}
@Override
public boolean assertIsValid() throws ConfigurationException {
if (key == null) {
@@ -7,6 +7,7 @@ import com.azure.ai.openai.OpenAIAsyncClient;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.azure.core.credential.KeyCredential;
import com.azure.core.credential.TokenCredential;
import com.azure.core.util.ClientOptions;
import com.microsoft.semantickernel.SemanticKernelHttpSettings;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
@@ -79,7 +80,7 @@ public class OpenAIClientProvider {
return new OpenAIClientProvider(settings, clientType);
}
private static Map<String, String> getSettings(@Nullable List<File> propertyFileLocations)
static Map<String, String> getSettings(@Nullable List<File> propertyFileLocations)
throws ConfigurationException {
Map<String, String> settings;
@@ -235,19 +236,27 @@ public class OpenAIClientProvider {
private OpenAIAsyncClient buildAzureOpenAIClient() throws ConfigurationException {
AzureOpenAISettings settings = new AzureOpenAISettings(configuredSettings);
try {
settings.assertIsValid();
} catch (ConfigurationException e) {
LOGGER.warn("Could not instantiate Azure OpenAI client");
LOGGER.warn(e.getMessage());
throw e;
OpenAIClientBuilder builder = new OpenAIClientBuilder().endpoint(settings.getEndpoint());
TokenCredential tokenCredential = null;
if (settings.getAzureOpenAiCredentialsType() != null) {
tokenCredential = settings.getAzureOpenAiCredentialsType().getTokenCredential();
}
OpenAIClientBuilder builder =
new OpenAIClientBuilder()
.endpoint(settings.getEndpoint())
.clientOptions(clientOptions)
.credential(new AzureKeyCredential(settings.getKey()));
if (tokenCredential != null) {
builder.credential(tokenCredential);
} else {
try {
settings.assertIsValid();
} catch (ConfigurationException e) {
LOGGER.warn("Could not instantiate Azure OpenAI client");
LOGGER.warn(e.getMessage());
throw e;
}
builder.credential(new AzureKeyCredential(settings.getKey()));
}
return builder.buildAsyncClient();
}
+19 -4
View File
@@ -34,10 +34,14 @@ They can then be run by:
# Configuration
You can define the provider of Open AI by setting the `OPENAI_CLIENT_TYPE`
By default, the samples will use the Open AI client, but you can also use the Azure Open AI client.
## Open AI client type
You can define the provider of Open AI (openai.com or Azure), this can be done by setting the `OPENAI_CLIENT_TYPE`
property or environment variable to either [`OPENAI`](https://openai.com/api/)
or [`AZURE_OPEN_AI`](https://learn.microsoft.com/azure/cognitive-services/openai/).
By default, the samples will use the Open AI client.
or [`AZURE_OPEN_AI`](https://learn.microsoft.com/azure/cognitive-services/openai/). By default, the samples will use the
Open AI client.
```shell
OPENAI_CLIENT_TYPE=OPEN_AI ../../mvnw exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode
@@ -55,7 +59,6 @@ The samples search for the client settings in the following order:
1. Properties file at `java/samples/conf.properties`.
1. Properties file at `~/.sk/conf.properties`.
## Properties File
You can set the location of a properties file, by setting the `CONF_PROPERTIES` property or environment variable, ie:
@@ -123,3 +126,15 @@ OPEN_AI_KEY="my-key" \
OPEN_AI_ORGANIZATION_ID="organisation id" \
../../mvnw clean package exec:java -Dsample=Example04_CombineLLMPromptsAndNativeCode
```
## Managed Identity and Azure CLI Credentials (Azure only)
The `credentialtype` setting (i.e `client.openai.credentialtype`):
- `managed_identity`: will attempt to obtain credentials via Azure's managed identity.
- `azure_cli`: will attempt to obtain credentials via Azure's CLI, to use this you must have logged in to the az client
for instance by running `az login`.
To use either of these settings, the `azure-identity` dependency must be available to the application. Additionally, you
must have the "Cognitive Services User" role assigned to your identity.
+4
View File
@@ -76,6 +76,10 @@
<groupId>com.microsoft.semantic-kernel</groupId>
<artifactId>semantickernel-settings-loader</artifactId>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
</dependencies>
<build>
@@ -34,24 +34,20 @@ public class Example04_CombineLLMPromptsAndNativeCode {
public static void main(String[] args) throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
TextCompletion textCompletion = SKBuilders.textCompletion()
.withModelId("text-davinci-003")
TextCompletion textCompletion = SKBuilders.chatCompletion()
.withModelId("gpt-35-turbo-2")
.withOpenAIClient(client)
.build();
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build();
Kernel kernel = SKBuilders.kernel().withDefaultAIService(textCompletion).build();
kernel.importSkill(new SearchEngineSkill(), null);
kernel.importSkillFromDirectory("SummarizeSkill", SampleSkillsUtil.detectSkillDirLocation(),
"SummarizeSkill");
// Run
String ask = "What's the tallest building in South America?";
Mono<SKContext> result =
kernel.runAsync(ask, kernel.getSkills().getFunction("Search", null));
result =
kernel.runAsync(
ask,
kernel.getSkills().getFunction("Search", null),
@@ -183,16 +183,16 @@ public class Example12_SequentialPlanner {
private static Kernel initializeKernel() throws ConfigurationException {
OpenAIAsyncClient client = SamplesConfig.getClient();
var kernel = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.chatCompletion()
.withDefaultAIService(SKBuilders.textCompletion()
.withOpenAIClient(client)
.withModelId("gpt-35-turbo")
.withModelId("gpt-35-turbo-instruct")
.build())
.withMemory(SKBuilders
.semanticTextMemory()
.withEmbeddingGenerator(
SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(client)
.withModelId("gpt-35-turbo")
.withModelId("text-embedding-ada-002")
.build()
)
.withStorage(new VolatileMemoryStore())
@@ -1,17 +1,20 @@
// Copyright (c) Microsoft. All rights reserved.
package com.microsoft.semantickernel.samples.syntaxexamples;
import com.azure.core.credential.TokenCredential;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.SKBuilders;
import com.microsoft.semantickernel.SamplesConfig;
import com.microsoft.semantickernel.connectors.ai.openai.util.AzureCredentialType;
import com.microsoft.semantickernel.connectors.memory.azurecognitivesearch.AzureCognitiveSearchMemoryStore;
import com.microsoft.semantickernel.exceptions.ConfigurationException;
import com.microsoft.semantickernel.memory.VolatileMemoryStore;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import com.microsoft.semantickernel.settings.SettingsMap;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
@@ -32,75 +35,102 @@ import java.util.stream.Collectors;
* README</a> for configuring your environment to run the examples.
*/
public class Example14_SemanticMemory {
private static final String MEMORY_COLLECTION_NAME = "SKGitHub";
public static void main(String[] args) throws Exception {
System.out.println("==============================================================");
System.out.println("======== Semantic Memory using Azure Cognitive Search ========");
System.out.println("==============================================================");
private static final String MEMORY_COLLECTION_NAME = "SKGitHub";
var openAIAsyncClient = SamplesConfig.getClient();
public static void main(String[] args) throws Exception {
System.out.println("==============================================================");
System.out.println("======== Semantic Memory using Azure Cognitive Search ========");
System.out.println("==============================================================");
/* This example leverages Azure Cognitive Search to provide SK with Semantic Memory.
*
* Azure Cognitive Search automatically indexes your data semantically, so you don't
* need to worry about embedding generation.
*/
var kernelWithACS = SKBuilders.kernel()
.withMemoryStorage(
new AzureCognitiveSearchMemoryStore(System.getenv("ACS_ENDPOINT"), System.getenv("ACS_API_KEY")))
.withDefaultAIService(SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(openAIAsyncClient)
.withModelId("text-embedding-ada-002")
.build())
.build();
var openAIAsyncClient = SamplesConfig.getClient();
runExampleAsync(kernelWithACS).block();
AzureCognitiveSearchMemoryStore memoryStore = buildAzureCognitiveSearchMemoryStore();
/* This example leverages Azure Cognitive Search to provide SK with Semantic Memory.
*
* Azure Cognitive Search automatically indexes your data semantically, so you don't
* need to worry about embedding generation.
*/
var kernelWithACS = SKBuilders.kernel()
.withMemoryStorage(memoryStore)
.withDefaultAIService(SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(openAIAsyncClient)
.withModelId("text-embedding-ada-002")
.build())
.build();
System.out.println("====================================================");
System.out.println("======== Semantic Memory (volatile, in RAM) ========");
System.out.println("====================================================");
runExampleAsync(kernelWithACS).block();
/* You can build your own semantic memory combining an Embedding Generator
* with a Memory storage that supports search by similarity (ie semantic search).
*
* In this example we use a volatile memory, a local simulation of a vector DB.
*
* You can replace VolatileMemoryStore with Qdrant (see QdrantMemoryStore connector)
* or implement your connectors for Pinecone, Vespa, Postgres + pgvector, SQLite VSS, etc.
*/
System.out.println("====================================================");
System.out.println("======== Semantic Memory (volatile, in RAM) ========");
System.out.println("====================================================");
var kernelWithCustomDb = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(openAIAsyncClient)
.withModelId("text-embedding-ada-002")
.build())
.withMemoryStorage(new VolatileMemoryStore.Builder().build())
.build();
/* You can build your own semantic memory combining an Embedding Generator
* with a Memory storage that supports search by similarity (ie semantic search).
*
* In this example we use a volatile memory, a local simulation of a vector DB.
*
* You can replace VolatileMemoryStore with Qdrant (see QdrantMemoryStore connector)
* or implement your connectors for Pinecone, Vespa, Postgres + pgvector, SQLite VSS, etc.
*/
runExampleAsync(kernelWithCustomDb).block();
var kernelWithCustomDb = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textEmbeddingGeneration()
.withOpenAIClient(openAIAsyncClient)
.withModelId("text-embedding-ada-002")
.build())
.withMemoryStorage(new VolatileMemoryStore.Builder().build())
.build();
runExampleAsync(kernelWithCustomDb).block();
}
private static AzureCognitiveSearchMemoryStore buildAzureCognitiveSearchMemoryStore()
throws ConfigurationException {
Map<String, String> settings = SettingsMap.getDefault();
AzureCognitiveSearchMemoryStore memoryStore;
if (settings.get("cognativesearch.token") == null) {
// Attempt to obtain token via
TokenCredential token = AzureCredentialType.getCredential();
if (token == null) {
throw new IllegalStateException(
"Unable to obtain token credentials. Please provide a key for Azure Cognitive Search, or log in to az.");
}
memoryStore = new AzureCognitiveSearchMemoryStore(
settings.get("cognativesearch.endpoint"),
token
);
} else {
memoryStore = new AzureCognitiveSearchMemoryStore(
settings.get("cognativesearch.endpoint"),
settings.get("cognativesearch.token")
);
}
return memoryStore;
}
public static Mono<Void> runExampleAsync(Kernel kernel) {
return storeMemoryAsync(kernel)
.then(searchMemoryAsync(kernel, "How do I get started?"))
public static Mono<Void> runExampleAsync(Kernel kernel) {
return storeMemoryAsync(kernel)
.then(searchMemoryAsync(kernel, "How do I get started?"))
/*
Output:
/*
Output:
Query: How do I get started?
Query: How do I get started?
Result 1:
URL: : https://github.com/microsoft/semantic-kernel/blob/main/README.md
Title : README: Installation, getting started, and how to contribute
Result 1:
URL: : https://github.com/microsoft/semantic-kernel/blob/main/README.md
Title : README: Installation, getting started, and how to contribute
Result 2:
URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet-jupyter-notebooks/00-getting-started.ipynb
Title : Jupyter notebook describing how to get started with the Semantic Kernel
Result 2:
URL: : https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet-jupyter-notebooks/00-getting-started.ipynb
Title : Jupyter notebook describing how to get started with the Semantic Kernel
*/
*/
.then(searchMemoryAsync(kernel, "Can I build a chat with SK?"));
.then(searchMemoryAsync(kernel, "Can I build a chat with SK?"));
/*
Output:
@@ -116,60 +146,68 @@ public class Example14_SemanticMemory {
Title : README: README associated with a sample chat summary react-based webapp
*/
}
}
private static Mono<Void> searchMemoryAsync(Kernel kernel, String query) {
return kernel.getMemory().searchAsync(MEMORY_COLLECTION_NAME, query, 2, 0.5f, false)
.mapNotNull(memories -> {
System.out.println("\nQuery: " + query + "\n");
for (int n = 0; n < memories.size(); n++) {
var memory = memories.get(n);
System.out.println("Result " + (n + 1) + ":");
System.out.println(" URL: : " + memory.getMetadata().getId());
System.out.println(" Title : " + memory.getMetadata().getDescription());
System.out.println();
}
System.out.println("----------------------");
return null;
});
}
private static Mono<Void> searchMemoryAsync(Kernel kernel, String query) {
return kernel.getMemory().searchAsync(MEMORY_COLLECTION_NAME, query, 2, 0.5f, false)
.mapNotNull(memories -> {
System.out.println("\nQuery: " + query + "\n");
for (int n = 0; n < memories.size(); n++) {
var memory = memories.get(n);
System.out.println("Result " + (n + 1) + ":");
System.out.println(" URL: : " + memory.getMetadata().getId());
System.out.println(" Title : " + memory.getMetadata().getDescription());
System.out.println();
}
System.out.println("----------------------");
return null;
});
}
private static Mono<Void> storeMemoryAsync(Kernel kernel) {
/* Store some data in the semantic memory.
*
* When using Azure Cognitive Search the data is automatically indexed on write.
*
* When using the combination of VolatileStore and Embedding generation, SK takes
* care of creating and storing the index
*/
private static Mono<Void> storeMemoryAsync(Kernel kernel) {
/* Store some data in the semantic memory.
*
* When using Azure Cognitive Search the data is automatically indexed on write.
*
* When using the combination of VolatileStore and Embedding generation, SK takes
* care of creating and storing the index
*/
return Flux.fromIterable(sampleData().entrySet())
.doFirst(() -> System.out.println("\nAdding some GitHub file URLs and their descriptions to the semantic memory."))
.map(entry -> {
System.out.println("Save '" + entry.getKey() + "' to memory.");
return kernel.getMemory().saveReferenceAsync(
MEMORY_COLLECTION_NAME,
entry.getValue(),
entry.getKey(),
"GitHub",
entry.getValue(),
null);
}
)
.mapNotNull(Mono::block)
.doFinally(signalType -> System.out.println("\n----------------------"))
.then();
}
return Flux.fromIterable(sampleData().entrySet())
.doFirst(() -> System.out.println(
"\nAdding some GitHub file URLs and their descriptions to the semantic memory."))
.map(entry -> {
System.out.println("Save '" + entry.getKey() + "' to memory.");
return kernel.getMemory().saveReferenceAsync(
MEMORY_COLLECTION_NAME,
entry.getValue(),
entry.getKey(),
"GitHub",
entry.getValue(),
null);
}
)
.mapNotNull(Mono::block)
.doFinally(signalType -> System.out.println("\n----------------------"))
.then();
}
private static Map<String, String> sampleData() {
return Arrays.stream(new String[][]{
{"https://github.com/microsoft/semantic-kernel/blob/main/README.md", "README: Installation, getting started, and how to contribute"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb", "Jupyter notebook describing how to pass prompts from a file to a semantic skill or function"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb", "Jupyter notebook describing how to get started with the Semantic Kernel"},
{"https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT", "Sample demonstrating how to create a chat skill interfacing with ChatGPT"},
{"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/VolatileMemoryStore.cs", "C# class that defines a volatile embedding store"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet/KernelHttpServer/README.md", "README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md", "README: README associated with a sample chat summary react-based webapp"},
}).collect(Collectors.toMap(element -> element[0], element -> element[1]));
}
private static Map<String, String> sampleData() {
return Arrays.stream(new String[][]{
{"https://github.com/microsoft/semantic-kernel/blob/main/README.md",
"README: Installation, getting started, and how to contribute"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb",
"Jupyter notebook describing how to pass prompts from a file to a semantic skill or function"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/notebooks/dotnet/00-getting-started.ipynb",
"Jupyter notebook describing how to get started with the Semantic Kernel"},
{"https://github.com/microsoft/semantic-kernel/tree/main/samples/skills/ChatSkill/ChatGPT",
"Sample demonstrating how to create a chat skill interfacing with ChatGPT"},
{"https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/SemanticKernel/Memory/VolatileMemoryStore.cs",
"C# class that defines a volatile embedding store"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/dotnet/KernelHttpServer/README.md",
"README: How to set up a Semantic Kernel Service API using Azure Function Runtime v4"},
{"https://github.com/microsoft/semantic-kernel/blob/main/samples/apps/chat-summary-webapp-react/README.md",
"README: README associated with a sample chat summary react-based webapp"},
}).collect(Collectors.toMap(element -> element[0], element -> element[1]));
}
}
@@ -24,10 +24,10 @@ public class Example17_ChatGPT {
Kernel kernel = SKBuilders.kernel()
.withAIService(
"chat-test",
"gpt-35-turbo",
SKBuilders.chatCompletion()
.withOpenAIClient(client)
.withModelId("chat-test")
.withModelId("gpt-35-turbo")
.build(),
true,
ChatCompletion.class
@@ -25,7 +25,7 @@ public class Example28_ActionPlanner {
var kernel = SKBuilders.kernel()
.withDefaultAIService(SKBuilders.textCompletion()
.withModelId("text-davinci-002")
.withModelId("text-davinci-003")
.withOpenAIClient(client)
.build())
.build();
@@ -75,7 +75,8 @@ public interface SkillExecutor {
* @throws KernelException if it is not possible to correctly load the skill
*/
ReadOnlyFunctionCollection importSkillFromResources(
String pluginDirectory, String skillName, String functionName, @Nullable Class clazz) throws KernelException;
String pluginDirectory, String skillName, String functionName, @Nullable Class clazz)
throws KernelException;
/**
* Imports the native functions annotated on the given object as a skill.
@@ -97,7 +97,8 @@ public class KernelExtensions {
String pluginName,
String functionName,
@Nullable Class clazz,
PromptTemplateEngine promptTemplateEngine) throws KernelException {
PromptTemplateEngine promptTemplateEngine)
throws KernelException {
PromptTemplateConfig config =
getPromptTemplateConfig(pluginDirectory, pluginName, functionName, clazz);
@@ -150,7 +151,8 @@ public class KernelExtensions {
}
private static PromptTemplateConfig getPromptTemplateConfig(
String pluginDirectory, String pluginName, String functionName, @Nullable Class clazz) throws KernelException {
String pluginDirectory, String pluginName, String functionName, @Nullable Class clazz)
throws KernelException {
String configFileName =
pluginDirectory
+ File.separator
@@ -169,18 +171,19 @@ public class KernelExtensions {
ResourceLocation.CLASSPATH,
ResourceLocation.FILESYSTEM);
return new ObjectMapper().readValue(config, PromptTemplateConfig.class);
return new ObjectMapper().readValue(config, PromptTemplateConfig.class);
} catch (IOException e) {
if (e instanceof JsonMappingException) {
LOGGER.error("Failed to parse config file " + configFileName, e);
if (e instanceof JsonMappingException) {
LOGGER.error("Failed to parse config file " + configFileName, e);
throw new KernelException(
ErrorCodes.FUNCTION_CONFIGURATION_ERROR,
"Failed to parse config file " + configFileName, e);
} else {
LOGGER.debug("No config for " + functionName + " in " + pluginName);
}
return null;
throw new KernelException(
ErrorCodes.FUNCTION_CONFIGURATION_ERROR,
"Failed to parse config file " + configFileName,
e);
} else {
LOGGER.debug("No config for " + functionName + " in " + pluginName);
}
return null;
}
}
}
+5
View File
@@ -106,6 +106,11 @@
<artifactId>azure-ai-openai</artifactId>
<version>1.0.0-beta.5</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>1.10.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
@@ -235,7 +235,8 @@ public class DefaultKernel implements Kernel {
@Override
public ReadOnlyFunctionCollection importSkillFromResources(
String pluginDirectory, String skillName, String functionName, @Nullable Class clazz) throws KernelException {
String pluginDirectory, String skillName, String functionName, @Nullable Class clazz)
throws KernelException {
Map<String, SemanticFunctionConfig> skills =
KernelExtensions.importSemanticSkillFromResourcesDirectory(
pluginDirectory, skillName, functionName, clazz, promptTemplateEngine);