mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
Merge branch 'experimental-java' of https://github.com/microsoft/semantic-kernel into experimental-java
This commit is contained in:
+11
-12
@@ -10,7 +10,7 @@ The Semantic Kernel for Java is an SDK that implements the key concepts of the S
|
||||
to be used in Java applications and services in an idiomatic way, and to be easily integrated with other Java libraries
|
||||
and frameworks.
|
||||
|
||||
## Get Started
|
||||
## Get started
|
||||
|
||||
To run the LLM prompts and semantic functions in this kernel, make sure you have
|
||||
an [Open AI API Key](https://openai.com/api/)
|
||||
@@ -18,26 +18,25 @@ or [Azure Open AI service key](https://learn.microsoft.com/azure/cognitive-servi
|
||||
|
||||
### Requirements
|
||||
|
||||
To build the semantic kernel, you will need to have:
|
||||
To build the Semantic Kernel, you will need:
|
||||
|
||||
- **Required**:
|
||||
- [JDK 8](https://microsoft.com/openjdk/) or newer to build the Semantic Kernel library
|
||||
- [JDK 17](https://microsoft.com/openjdk/) or newer to run samples
|
||||
- [OpenJDK 17](https://microsoft.com/openjdk/) or newer
|
||||
|
||||
### Build the semantic kernel
|
||||
### Build the Semantic Kernel
|
||||
|
||||
1. Clone this repository
|
||||
|
||||
git clone git@github.com:microsoft/semantic-kernel.git
|
||||
|
||||
2. Build the semantic kernel
|
||||
2. Build the Semantic Kernel
|
||||
|
||||
cd semantic-kernel/java
|
||||
mvn install
|
||||
./mvnw install
|
||||
|
||||
## Using the semantic kernel
|
||||
## Using the Semantic Kernel
|
||||
|
||||
Check the `samples` folder for examples of how to use the semantic kernel.
|
||||
Check the `samples` folder for examples of how to use the Semantic Kernel for Java.
|
||||
|
||||
## Discord community
|
||||
|
||||
@@ -48,7 +47,7 @@ and get help from the community. We have a `#java` channel for Java-specific que
|
||||
|
||||
### Testing locally
|
||||
|
||||
The project may contain integration tests that require an OpenAI key to run. To run the integration tests locally, you
|
||||
The project may contain end-to-end tests that require an OpenAI key to run. To run these tests locally, you
|
||||
will need to set the following environment variable:
|
||||
|
||||
- `OPENAI_API_KEY` - the OpenAI API key.
|
||||
@@ -65,11 +64,11 @@ on [how to get your Azure OpenAI credentials](https://learn.microsoft.com/en-us/
|
||||
|
||||
To run the unit tests only, run the following command:
|
||||
|
||||
mvn package
|
||||
./mvnw package
|
||||
|
||||
To run all tests, including integration tests that require an OpenAI key, run the following command:
|
||||
|
||||
mvn verify
|
||||
./mvnw verify
|
||||
|
||||
### Submitting a pull request
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.e2e; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.e2e;
|
||||
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.openai; // Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package com.microsoft.openai;
|
||||
|
||||
import com.azure.ai.openai.models.*;
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.openai; // Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
package com.microsoft.openai;
|
||||
|
||||
/** Builds an OpenAIClient for use with <a href="https://api.openai.com/v1">api.openai.com/v1</a> */
|
||||
public final class OpenAIClientBuilder {
|
||||
|
||||
@@ -203,6 +203,7 @@
|
||||
<licenseHeader>
|
||||
<content>// Copyright (c) Microsoft. All rights reserved.</content>
|
||||
</licenseHeader>
|
||||
<toggleOffOn/>
|
||||
</java>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
package com.microsoft.semantickernel.syntaxexamples;// Copyright (c) Microsoft. All rights reserved.
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples;
|
||||
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
import com.microsoft.semantickernel.Config;
|
||||
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
package com.microsoft.semantickernel.syntaxexamples;// Copyright (c) Microsoft. All rights reserved.
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples;
|
||||
|
||||
import com.azure.ai.openai.OpenAIClientBuilder;
|
||||
import com.azure.core.credential.AzureKeyCredential;
|
||||
|
||||
@@ -55,7 +55,7 @@ public interface Kernel {
|
||||
* @param pipeline List of functions
|
||||
* @return Result of the function composition
|
||||
*/
|
||||
Mono<SKContext<?>> runAsync(SKFunction... pipeline);
|
||||
Mono<SKContext<?>> runAsync(SKFunction<?, ?>... pipeline);
|
||||
|
||||
/**
|
||||
* Run a pipeline composed of synchronous and asynchronous functions.
|
||||
@@ -64,7 +64,7 @@ public interface Kernel {
|
||||
* @param pipeline List of functions
|
||||
* @return Result of the function composition
|
||||
*/
|
||||
Mono<SKContext<?>> runAsync(String input, SKFunction... pipeline);
|
||||
Mono<SKContext<?>> runAsync(String input, SKFunction<?, ?>... pipeline);
|
||||
|
||||
/**
|
||||
* Run a pipeline composed of synchronous and asynchronous functions.
|
||||
@@ -73,7 +73,7 @@ public interface Kernel {
|
||||
* @param pipeline List of functions
|
||||
* @return Result of the function composition
|
||||
*/
|
||||
Mono<SKContext<?>> runAsync(ContextVariables variables, SKFunction... pipeline);
|
||||
Mono<SKContext<?>> runAsync(ContextVariables variables, SKFunction<?, ?>... pipeline);
|
||||
|
||||
/**
|
||||
* Import a set of skills
|
||||
@@ -128,8 +128,6 @@ public interface Kernel {
|
||||
@Nullable private KernelConfig kernelConfig = null;
|
||||
@Nullable private PromptTemplateEngine promptTemplateEngine = null;
|
||||
|
||||
@Nullable private ReadOnlySkillCollection skillCollection = null;
|
||||
|
||||
public Builder setKernelConfig(KernelConfig kernelConfig) {
|
||||
this.kernelConfig = kernelConfig;
|
||||
return this;
|
||||
@@ -140,11 +138,6 @@ public interface Kernel {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSkillCollection(@Nullable ReadOnlySkillCollection skillCollection) {
|
||||
this.skillCollection = skillCollection;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Kernel build() {
|
||||
if (kernelConfig == null) {
|
||||
throw new IllegalStateException("Must provide a kernel configuration");
|
||||
@@ -152,14 +145,12 @@ public interface Kernel {
|
||||
|
||||
return BuildersSingleton.INST
|
||||
.getKernelBuilder()
|
||||
.build(kernelConfig, promptTemplateEngine, skillCollection);
|
||||
.build(kernelConfig, promptTemplateEngine);
|
||||
}
|
||||
}
|
||||
|
||||
interface InternalBuilder {
|
||||
Kernel build(
|
||||
KernelConfig kernelConfig,
|
||||
@Nullable PromptTemplateEngine promptTemplateEngine,
|
||||
@Nullable ReadOnlySkillCollection skillCollection);
|
||||
KernelConfig kernelConfig, @Nullable PromptTemplateEngine promptTemplateEngine);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.ai; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.ai;
|
||||
|
||||
import com.microsoft.semantickernel.SKException;
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.ai.embeddings; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.ai.embeddings;
|
||||
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public enum BuildersSingleton {
|
||||
private static final String FALLBACK_FUNCTION_BUILDER_CLASS =
|
||||
"com.microsoft.semantickernel.SkFunctionBuilders";
|
||||
private static final String FALLBACK_KERNEL_BUILDER_CLASS =
|
||||
"com.microsoft.semantickernel.KernelDefaultBuilder";
|
||||
"com.microsoft.semantickernel.DefaultKernelBuilder";
|
||||
private static final String FALLBACK_TEXT_COMPLETION_BUILDER_CLASS =
|
||||
"com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletionBuilder";
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.memory; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.memory;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import com.microsoft.semantickernel.builders.SKBuilders;
|
||||
import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
|
||||
-2
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.skilldefinition.ParameterView;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.skilldefinition; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.skilldefinition;
|
||||
|
||||
/// <summary>
|
||||
/// Class used to copy and export data from
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.skilldefinition; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.skilldefinition;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.SKFunction;
|
||||
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
|
||||
|
||||
-14
@@ -6,20 +6,6 @@ public abstract class Block {
|
||||
private final String content;
|
||||
private final BlockTypes type;
|
||||
|
||||
/*
|
||||
|
||||
// internal virtual bool? SynchronousRendering => null;
|
||||
|
||||
/// <summary>
|
||||
/// The block content
|
||||
/// </summary>
|
||||
internal string Content { get; }
|
||||
|
||||
/// <summary>
|
||||
/// App logger
|
||||
/// </summary>
|
||||
protected ILogger Log { get; } = NullLogger.Instance;
|
||||
*/
|
||||
/// <summary>
|
||||
/// Base constructor
|
||||
/// </summary>
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
public enum BlockTypes {
|
||||
Undefined(0),
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.textcompletion; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.textcompletion;
|
||||
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
<groupId>com.microsoft.semantickernel</groupId>
|
||||
<artifactId>openai-sdk</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.inject</groupId>
|
||||
<artifactId>jakarta.inject-api</artifactId>
|
||||
<version>2.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.connectors.ai.openai.azuresdk; // Copyright (c) Microsoft. All
|
||||
// rights reserved.
|
||||
package com.microsoft.semantickernel.connectors.ai.openai.azuresdk;
|
||||
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
|
||||
|
||||
+3
@@ -10,6 +10,8 @@ import com.microsoft.semantickernel.connectors.ai.openai.azuresdk.ClientBase;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionRequestSettings;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -29,6 +31,7 @@ public class OpenAITextCompletion extends ClientBase implements TextCompletion {
|
||||
/// <param name="organization">OpenAI Organization Id (usually optional)</param>
|
||||
/// <param name="handlerFactory">Retry handler factory for HTTP requests.</param>
|
||||
/// <param name="log">Application logger</param>
|
||||
@Inject
|
||||
public OpenAITextCompletion(OpenAIAsyncClient client, String modelId) {
|
||||
super(client, modelId);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.coreskills; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.coreskills;
|
||||
|
||||
import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.coreskills; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.coreskills;
|
||||
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.coreskills; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.coreskills;
|
||||
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
|
||||
|
||||
|
||||
@@ -90,5 +90,16 @@
|
||||
<artifactId>semantickernel-core-skills</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.semantickernel.extensions</groupId>
|
||||
<artifactId>sequentialplanner-extensions</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.inject</groupId>
|
||||
<artifactId>jakarta.inject-api</artifactId>
|
||||
<version>2.0.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+36
-20
@@ -7,7 +7,11 @@ import com.microsoft.semantickernel.coreskills.SkillImporter;
|
||||
import com.microsoft.semantickernel.exceptions.NotSupportedException;
|
||||
import com.microsoft.semantickernel.exceptions.SkillsNotFoundException;
|
||||
import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
import com.microsoft.semantickernel.orchestration.*;
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
import com.microsoft.semantickernel.orchestration.DefaultCompletionSKFunction;
|
||||
import com.microsoft.semantickernel.orchestration.RegistrableSkFunction;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.orchestration.SKFunction;
|
||||
import com.microsoft.semantickernel.semanticfunctions.SemanticFunctionConfig;
|
||||
import com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection;
|
||||
import com.microsoft.semantickernel.skilldefinition.FunctionNotFound;
|
||||
@@ -17,6 +21,8 @@ import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -26,32 +32,37 @@ import java.util.function.Function;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class KernelDefault implements Kernel {
|
||||
public class DefaultKernel implements Kernel {
|
||||
|
||||
private final KernelConfig kernelConfig;
|
||||
private DefaultSkillCollection defaultSkillCollection;
|
||||
private final DefaultSkillCollection defaultSkillCollection;
|
||||
private final PromptTemplateEngine promptTemplateEngine;
|
||||
@Nullable private SemanticTextMemory memory; // TODO: make this final
|
||||
|
||||
public KernelDefault(
|
||||
@Inject
|
||||
public DefaultKernel(
|
||||
KernelConfig kernelConfig,
|
||||
PromptTemplateEngine promptTemplateEngine,
|
||||
ReadOnlySkillCollection skillCollection) {
|
||||
@Nullable SemanticTextMemory memory) {
|
||||
if (kernelConfig == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
this.kernelConfig = kernelConfig;
|
||||
this.promptTemplateEngine = promptTemplateEngine;
|
||||
this.defaultSkillCollection = new DefaultSkillCollection(skillCollection);
|
||||
this.defaultSkillCollection = new DefaultSkillCollection();
|
||||
|
||||
if (kernelConfig.getSkills() != null) {
|
||||
kernelConfig.getSkills().forEach(this::registerSemanticFunction);
|
||||
if (memory != null) {
|
||||
this.memory = memory.copy();
|
||||
} else {
|
||||
this.memory = null;
|
||||
}
|
||||
|
||||
kernelConfig.getSkills().forEach(this::registerSemanticFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getService(@Nullable String serviceId, Class<T> clazz) throws KernelException {
|
||||
public <T> T getService(String serviceId, Class<T> clazz) {
|
||||
if (TextCompletion.class.isAssignableFrom(clazz)) {
|
||||
Function<Kernel, TextCompletion> factory =
|
||||
kernelConfig.getTextCompletionServiceOrDefault(serviceId);
|
||||
@@ -84,7 +95,7 @@ public class KernelDefault implements Kernel {
|
||||
throw new RuntimeException("This function does not implement RegistrableSkFunction");
|
||||
}
|
||||
((RegistrableSkFunction) func).registerOnKernel(this);
|
||||
defaultSkillCollection = defaultSkillCollection.addSemanticFunction(func);
|
||||
defaultSkillCollection.addSemanticFunction(func);
|
||||
return func;
|
||||
}
|
||||
|
||||
@@ -136,8 +147,6 @@ public class KernelDefault implements Kernel {
|
||||
Object skillInstance, @Nullable String skillName) {
|
||||
if (skillName == null || skillName.isEmpty()) {
|
||||
skillName = ReadOnlySkillCollection.GlobalSkill;
|
||||
// this._log.LogTrace("Importing skill {0} in the global namespace",
|
||||
// skillInstance.GetType().FullName);
|
||||
}
|
||||
|
||||
// skill = new Dictionary<string, ISKFunction>(StringComparer.OrdinalIgnoreCase);
|
||||
@@ -151,7 +160,7 @@ public class KernelDefault implements Kernel {
|
||||
DefaultSkillCollection::addNativeFunction,
|
||||
DefaultSkillCollection::merge);
|
||||
|
||||
this.defaultSkillCollection = this.defaultSkillCollection.merge(newSkills);
|
||||
this.defaultSkillCollection.merge(newSkills);
|
||||
|
||||
return functions;
|
||||
}
|
||||
@@ -250,27 +259,34 @@ public class KernelDefault implements Kernel {
|
||||
*/
|
||||
|
||||
@Override
|
||||
public Mono<SKContext<?>> runAsync(SKFunction... pipeline) {
|
||||
public Mono<SKContext<?>> runAsync(SKFunction<?, ?>... pipeline) {
|
||||
return runAsync(SKBuilders.variables().build(), pipeline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<SKContext<?>> runAsync(String input, SKFunction... pipeline) {
|
||||
public Mono<SKContext<?>> runAsync(String input, SKFunction<?, ?>... pipeline) {
|
||||
return runAsync(SKBuilders.variables().build(input), pipeline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<SKContext<?>> runAsync(ContextVariables variables, SKFunction... pipeline) {
|
||||
DefaultSemanticSKContext context =
|
||||
new DefaultSemanticSKContext(variables, this.memory, this.defaultSkillCollection);
|
||||
public Mono<SKContext<?>> runAsync(ContextVariables variables, SKFunction<?, ?>... pipeline) {
|
||||
if (pipeline == null || pipeline.length == 0) {
|
||||
throw new SKException("No parameters provided to pipeline");
|
||||
}
|
||||
|
||||
Mono<SKContext<?>> pipelineBuilder = Mono.just(context);
|
||||
Mono<SKContext<?>> pipelineBuilder =
|
||||
Mono.just(pipeline[0].buildContext(variables, memory, getSkills()));
|
||||
|
||||
for (SKFunction f : Arrays.asList(pipeline)) {
|
||||
pipelineBuilder =
|
||||
pipelineBuilder.flatMap(
|
||||
newContext -> {
|
||||
return f.invokeAsync(newContext, null);
|
||||
SKContext context =
|
||||
f.buildContext(
|
||||
newContext.getVariables(),
|
||||
newContext.getSemanticMemory(),
|
||||
newContext.getSkills());
|
||||
return f.invokeAsync(context, null);
|
||||
});
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel;
|
||||
|
||||
import com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine;
|
||||
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class DefaultKernelBuilder implements Kernel.InternalBuilder {
|
||||
|
||||
@Override
|
||||
public Kernel build(
|
||||
KernelConfig kernelConfig, @Nullable PromptTemplateEngine promptTemplateEngine) {
|
||||
if (promptTemplateEngine == null) {
|
||||
promptTemplateEngine = new DefaultPromptTemplateEngine();
|
||||
}
|
||||
|
||||
if (kernelConfig == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
return new DefaultKernel(kernelConfig, promptTemplateEngine, null);
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel;
|
||||
|
||||
import com.microsoft.semantickernel.skilldefinition.DefaultSkillCollection;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
|
||||
import com.microsoft.semantickernel.templateengine.DefaultPromptTemplateEngine;
|
||||
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class KernelDefaultBuilder implements Kernel.InternalBuilder {
|
||||
|
||||
@Override
|
||||
public Kernel build(
|
||||
KernelConfig kernelConfig,
|
||||
@Nullable PromptTemplateEngine promptTemplateEngine,
|
||||
@Nullable ReadOnlySkillCollection skillCollection) {
|
||||
if (promptTemplateEngine == null) {
|
||||
promptTemplateEngine = new DefaultPromptTemplateEngine();
|
||||
}
|
||||
|
||||
if (skillCollection == null) {
|
||||
skillCollection = new DefaultSkillCollection();
|
||||
}
|
||||
|
||||
if (kernelConfig == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
return new KernelDefault(kernelConfig, promptTemplateEngine, skillCollection);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
|
||||
-2
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import com.microsoft.semantickernel.skilldefinition.CaseInsensitiveMap;
|
||||
|
||||
import reactor.util.annotation.NonNull;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.builders.SKBuilders;
|
||||
import com.microsoft.semantickernel.memory.NullMemory;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.orchestration;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.memory.SemanticTextMemory;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.semanticfunctions;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.skilldefinition.ParameterView;
|
||||
|
||||
+12
-27
@@ -1,11 +1,9 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.skilldefinition; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.skilldefinition;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.SKFunction;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -63,27 +61,18 @@ public class DefaultSkillCollection implements ReadOnlySkillCollection {
|
||||
this.skillCollection = new CaseInsensitiveMap<>();
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
public DefaultSkillCollection addSemanticFunction(SKFunction functionInstance) {
|
||||
FunctionCollection existingFunctionCollection;
|
||||
if (!skillCollection.containsKey(functionInstance.getSkillName().toLowerCase())) {
|
||||
existingFunctionCollection =
|
||||
new FunctionCollection(functionInstance.getSkillName().toLowerCase());
|
||||
if (!skillCollection.containsKey(functionInstance.getSkillName())) {
|
||||
existingFunctionCollection = new FunctionCollection(functionInstance.getSkillName());
|
||||
skillCollection.put(functionInstance.getSkillName(), existingFunctionCollection);
|
||||
} else {
|
||||
existingFunctionCollection =
|
||||
skillCollection.get(functionInstance.getSkillName().toLowerCase());
|
||||
existingFunctionCollection = skillCollection.get(functionInstance.getSkillName());
|
||||
}
|
||||
|
||||
existingFunctionCollection =
|
||||
existingFunctionCollection.put(
|
||||
functionInstance.getName().toLowerCase(), functionInstance);
|
||||
existingFunctionCollection.put(functionInstance.getName(), functionInstance);
|
||||
|
||||
HashMap<String, FunctionCollection> clonedSkillCollection = new HashMap<>(skillCollection);
|
||||
|
||||
clonedSkillCollection.put(
|
||||
functionInstance.getSkillName().toLowerCase(), existingFunctionCollection);
|
||||
|
||||
return new DefaultSkillCollection(clonedSkillCollection);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,25 +116,21 @@ public class DefaultSkillCollection implements ReadOnlySkillCollection {
|
||||
}
|
||||
|
||||
public DefaultSkillCollection merge(DefaultSkillCollection in) {
|
||||
HashMap<String, FunctionCollection> clone = new HashMap<>(skillCollection);
|
||||
|
||||
in.asMap()
|
||||
.entrySet()
|
||||
.forEach(
|
||||
entry -> {
|
||||
FunctionCollection existing = clone.get(entry.getKey().toLowerCase());
|
||||
FunctionCollection existing =
|
||||
skillCollection.get(entry.getKey().toLowerCase());
|
||||
if (existing == null) {
|
||||
clone.put(
|
||||
skillCollection.put(
|
||||
entry.getKey().toLowerCase(),
|
||||
new FunctionCollection(entry.getValue()));
|
||||
} else {
|
||||
clone.put(
|
||||
entry.getKey().toLowerCase(),
|
||||
existing.merge(new FunctionCollection(entry.getValue())));
|
||||
existing.merge(new FunctionCollection(entry.getValue()));
|
||||
}
|
||||
});
|
||||
|
||||
return new DefaultSkillCollection(clone);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-11
@@ -102,13 +102,9 @@ public class FunctionCollection implements ReadOnlyFunctionCollection {
|
||||
* @param functionInstance
|
||||
* @return Collection for fluent callse
|
||||
*/
|
||||
@CheckReturnValue
|
||||
public FunctionCollection put(String functionName, SKFunction<?, ?> functionInstance) {
|
||||
HashMap<String, SKFunction<?, ?>> functionCollection =
|
||||
new HashMap<>(this.functionCollection);
|
||||
functionCollection.put(functionName.toLowerCase(), functionInstance);
|
||||
|
||||
return new FunctionCollection(skillName, functionCollection);
|
||||
this.functionCollection.put(functionName.toLowerCase(), functionInstance);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,10 +114,7 @@ public class FunctionCollection implements ReadOnlyFunctionCollection {
|
||||
* @return Collection for fluent calls
|
||||
*/
|
||||
public FunctionCollection merge(FunctionCollection value) {
|
||||
HashMap<String, SKFunction<?, ?>> mutable = new HashMap<>(functionCollection);
|
||||
|
||||
mutable.putAll(value.functionCollection);
|
||||
|
||||
return new FunctionCollection(skillName, mutable);
|
||||
functionCollection.putAll(value.functionCollection);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-10
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine;
|
||||
|
||||
import com.microsoft.semantickernel.templateengine.blocks.*;
|
||||
|
||||
@@ -169,10 +168,9 @@ public class CodeTokenizer {
|
||||
|
||||
if (currentTokenType == TokenTypes.None) {
|
||||
if (!spaceSeparatorFound) {
|
||||
throw new TemplateException();
|
||||
// TODO error code
|
||||
// throw new TemplateException(TemplateException.ErrorCodes.SyntaxError,
|
||||
// "Tokens must be separated by one space least");
|
||||
throw new TemplateException(
|
||||
TemplateException.ErrorCodes.SyntaxError,
|
||||
"Tokens must be separated by one space least");
|
||||
}
|
||||
|
||||
if (isQuote(currentChar)) {
|
||||
@@ -205,10 +203,9 @@ public class CodeTokenizer {
|
||||
break;
|
||||
|
||||
case None:
|
||||
throw new TemplateException();
|
||||
// TODO error code
|
||||
// throw new TemplateException(TemplateException.ErrorCodes.SyntaxError,
|
||||
// "Tokens must be separated by one space least");
|
||||
throw new TemplateException(
|
||||
TemplateException.ErrorCodes.SyntaxError,
|
||||
"Tokens must be separated by one space least");
|
||||
}
|
||||
|
||||
return blocks;
|
||||
|
||||
+14
-11
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.templateengine.blocks.Block;
|
||||
@@ -8,6 +7,9 @@ import com.microsoft.semantickernel.templateengine.blocks.CodeBlock;
|
||||
import com.microsoft.semantickernel.templateengine.blocks.CodeRendering;
|
||||
import com.microsoft.semantickernel.templateengine.blocks.TextRendering;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -25,7 +27,7 @@ import java.util.List;
|
||||
// immutable when invoked within the template
|
||||
/// </summary>
|
||||
public class DefaultPromptTemplateEngine implements PromptTemplateEngine {
|
||||
// private readonly ILogger _log;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPromptTemplateEngine.class);
|
||||
|
||||
private final TemplateTokenizer tokenizer;
|
||||
|
||||
@@ -46,9 +48,8 @@ public class DefaultPromptTemplateEngine implements PromptTemplateEngine {
|
||||
if (validate) {
|
||||
blocks.forEach(
|
||||
block -> {
|
||||
// TODO ERROR MESSAGE
|
||||
if (!block.isValid()) {
|
||||
throw new TemplateException();
|
||||
throw new TemplateException(TemplateException.ErrorCodes.SyntaxError);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -76,13 +77,15 @@ public class DefaultPromptTemplateEngine implements PromptTemplateEngine {
|
||||
} else if (block instanceof CodeRendering) {
|
||||
return ((CodeBlock) block).renderCodeAsync(context);
|
||||
} else {
|
||||
// const string error = "Unexpected block type, the block doesn't
|
||||
// have a rendering method";
|
||||
// this._log.LogError(error);
|
||||
// throw new
|
||||
// TemplateException(TemplateException.ErrorCodes.UnexpectedBlockType, error);
|
||||
String message =
|
||||
"Unexpected block type, the block doesn't have a rendering"
|
||||
+ " method";
|
||||
LOGGER.error(message);
|
||||
return Mono.error(
|
||||
new TemplateException(
|
||||
TemplateException.ErrorCodes.UnexpectedBlockType,
|
||||
message));
|
||||
}
|
||||
return Mono.just("");
|
||||
})
|
||||
.collectList()
|
||||
.map(
|
||||
|
||||
+132
-1
@@ -3,4 +3,135 @@ package com.microsoft.semantickernel.templateengine;
|
||||
|
||||
import com.microsoft.semantickernel.SKException;
|
||||
|
||||
public class TemplateException extends SKException {}
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TemplateException extends SKException {
|
||||
|
||||
@Nonnull private final ErrorCodes errorCode;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@code TemplateException} class with a provided error code.
|
||||
*
|
||||
* @param error The error code.
|
||||
*/
|
||||
public TemplateException(@Nonnull ErrorCodes error) {
|
||||
this(error, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@code TemplateException} class with a provided error code.
|
||||
*
|
||||
* @param errorCode The error code.
|
||||
* @param message The exception message.
|
||||
*/
|
||||
public TemplateException(@Nonnull ErrorCodes errorCode, @Nullable String message) {
|
||||
this(errorCode, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@code TemplateException} class with a provided error code.
|
||||
*
|
||||
* @param errorCode The error code.
|
||||
* @param message The exception message.
|
||||
* @param innerException The exception that is the cause of the current exception.
|
||||
*/
|
||||
public TemplateException(
|
||||
@Nonnull ErrorCodes errorCode,
|
||||
@Nullable String message,
|
||||
@Nullable Throwable innerException) {
|
||||
super(getDefaultMessage(errorCode, message), innerException);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
// spotless:off
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Gets the error code for this exception.
|
||||
* </p>
|
||||
*/
|
||||
//spotless:on
|
||||
public ErrorCodes getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
// spotless:off
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Translate the error code into a default message.
|
||||
* </p>
|
||||
*/
|
||||
//spotless:on
|
||||
private static String getDefaultMessage(
|
||||
@Nonnull ErrorCodes errorCode, @Nullable String message) {
|
||||
return String.format("%s: %s", errorCode.getMessage(), message);
|
||||
}
|
||||
|
||||
// spotless:off
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Error codes for {@code TemplateException}.
|
||||
* </p>
|
||||
*/
|
||||
//spotless:on
|
||||
public enum ErrorCodes {
|
||||
|
||||
// spotless:off
|
||||
/**
|
||||
* <p>
|
||||
* Unknown error.
|
||||
* </p>
|
||||
*/
|
||||
//spotless:on
|
||||
UnknownError("Unknown error"),
|
||||
|
||||
// spotless:off
|
||||
/**
|
||||
* <p>
|
||||
* Syntax error, the template syntax used is not valid.
|
||||
* </p>
|
||||
*/
|
||||
//spotless:on
|
||||
SyntaxError("Syntax error, the template syntax used is not valid"),
|
||||
|
||||
// spotless:off
|
||||
/**
|
||||
* <p>
|
||||
* The block type produced be the tokenizer was not expected.
|
||||
* </p>
|
||||
*/
|
||||
UnexpectedBlockType("The block type produced be the tokenizer was not expected"),
|
||||
|
||||
//spotless:off
|
||||
/**
|
||||
* <p>
|
||||
* The template requires an unknown function.
|
||||
* </p>
|
||||
*/
|
||||
//spotless:on
|
||||
FunctionNotFound("The template requires an unknown function"),
|
||||
|
||||
// spotless:off
|
||||
/**
|
||||
* <p>
|
||||
* The template execution failed, e.g. a function call threw an exception.
|
||||
* </p>
|
||||
*/
|
||||
//spotless:on
|
||||
RuntimeError("The template execution failed, e.g. a function call threw an exception"),
|
||||
;
|
||||
|
||||
private final String message;
|
||||
|
||||
ErrorCodes(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-27
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine;
|
||||
|
||||
import com.microsoft.semantickernel.templateengine.blocks.Block;
|
||||
import com.microsoft.semantickernel.templateengine.blocks.CodeBlock;
|
||||
@@ -69,7 +68,7 @@ public class TemplateTokenizer {
|
||||
return Collections.singletonList(new TextBlock(text));
|
||||
}
|
||||
|
||||
List<Block> blocks = new ArrayList<Block>();
|
||||
List<Block> blocks = new ArrayList<>();
|
||||
|
||||
int endOfLastBlock = 0;
|
||||
|
||||
@@ -148,12 +147,10 @@ public class TemplateTokenizer {
|
||||
switch (codeBlocks.get(0).getType()) {
|
||||
case Variable:
|
||||
if (codeBlocks.size() > 1) {
|
||||
throw new TemplateException();
|
||||
// TODO errorcode
|
||||
// throw new
|
||||
// TemplateException(TemplateException.ErrorCodes.SyntaxError,
|
||||
// $"Invalid token detected after the variable:
|
||||
// {contentWithoutDelimiters}");
|
||||
throw new TemplateException(
|
||||
TemplateException.ErrorCodes.SyntaxError,
|
||||
"Invalid token detected after the variable: "
|
||||
+ contentWithoutDelimiters);
|
||||
}
|
||||
|
||||
blocks.add(codeBlocks.get(0));
|
||||
@@ -161,12 +158,10 @@ public class TemplateTokenizer {
|
||||
|
||||
case Value:
|
||||
if (codeBlocks.size() > 1) {
|
||||
throw new TemplateException();
|
||||
// TODO errorcode
|
||||
// throw new
|
||||
// TemplateException(TemplateException.ErrorCodes.SyntaxError,
|
||||
// $"Invalid token detected after the value:
|
||||
// {contentWithoutDelimiters}");
|
||||
throw new TemplateException(
|
||||
TemplateException.ErrorCodes.SyntaxError,
|
||||
"Invalid token detected after the value: "
|
||||
+ contentWithoutDelimiters);
|
||||
}
|
||||
|
||||
blocks.add(codeBlocks.get(0));
|
||||
@@ -174,12 +169,10 @@ public class TemplateTokenizer {
|
||||
|
||||
case FunctionId:
|
||||
if (codeBlocks.size() > 2) {
|
||||
throw new TemplateException();
|
||||
// TODO errorcode
|
||||
// throw new
|
||||
// TemplateException(TemplateException.ErrorCodes.SyntaxError,
|
||||
// $"Functions support only one parameter:
|
||||
// {contentWithoutDelimiters}");
|
||||
throw new TemplateException(
|
||||
TemplateException.ErrorCodes.SyntaxError,
|
||||
"Functions support only one parameter: "
|
||||
+ contentWithoutDelimiters);
|
||||
}
|
||||
|
||||
blocks.add(new CodeBlock(codeBlocks, contentWithoutDelimiters));
|
||||
@@ -189,12 +182,10 @@ public class TemplateTokenizer {
|
||||
case Text:
|
||||
case Undefined:
|
||||
default:
|
||||
throw new TemplateException();
|
||||
// TODO errorcode
|
||||
// throw new
|
||||
// TemplateException(TemplateException.ErrorCodes.UnexpectedBlockType,
|
||||
// $"Code tokenizer returned an incorrect first token
|
||||
// type {codeBlocks[0].Type:G}");
|
||||
throw new TemplateException(
|
||||
TemplateException.ErrorCodes.UnexpectedBlockType,
|
||||
"Code tokenizer returned an incorrect first token type "
|
||||
+ codeBlocks.get(0).getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-12
@@ -1,21 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.orchestration.SKFunction;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlyFunctionCollection;
|
||||
import com.microsoft.semantickernel.skilldefinition.ReadOnlySkillCollection;
|
||||
import com.microsoft.semantickernel.templateengine.TemplateException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.annotation.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// ReSharper disable TemplateIsNotCompileTimeConstantProblem
|
||||
public class CodeBlock extends Block implements CodeRendering {
|
||||
public final class CodeBlock extends Block implements CodeRendering {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CodeBlock.class);
|
||||
private final List<Block> tokens;
|
||||
|
||||
public CodeBlock(List<Block> tokens, String content) {
|
||||
@@ -30,21 +35,39 @@ public class CodeBlock extends Block implements CodeRendering {
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
// TODO
|
||||
Optional<Block> invalid = tokens.stream().filter(token -> !token.isValid()).findFirst();
|
||||
if (invalid.isPresent()) {
|
||||
LOGGER.error("Invalid block" + invalid.get().getContent());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.tokens.size() > 1) {
|
||||
if (this.tokens.get(0).getType() != BlockTypes.FunctionId) {
|
||||
LOGGER.error("Unexpected second token found: " + this.tokens.get(1).getContent());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.tokens.get(1).getType() != BlockTypes.Value
|
||||
&& this.tokens.get(1).getType() != BlockTypes.Variable) {
|
||||
LOGGER.error("Functions support only one parameter");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.tokens.size() > 2) {
|
||||
LOGGER.error("Unexpected second token found: " + this.tokens.get(1).getContent());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Mono<String> renderCodeAsync(SKContext context) {
|
||||
/* TODO
|
||||
if (!this.isValid()) {
|
||||
throw new TemplateException(TemplateException.ErrorCodes.SyntaxError);
|
||||
}
|
||||
if (!this._validated && !this.IsValid(out var error))
|
||||
{
|
||||
throw new TemplateException(TemplateException.ErrorCodes.SyntaxError, error);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// this.Log.LogTrace("Rendering code: `{0}`", this.Content);
|
||||
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
|
||||
|
||||
+2
-3
@@ -1,12 +1,11 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FunctionIdBlock extends Block implements TextRendering {
|
||||
public final class FunctionIdBlock extends Block implements TextRendering {
|
||||
private final String skillName;
|
||||
|
||||
private final String functionName;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
public class Symbols {
|
||||
public static final char BlockStarter = '{';
|
||||
|
||||
+2
-19
@@ -1,12 +1,9 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
|
||||
public class TextBlock extends Block implements TextRendering {
|
||||
|
||||
// internal override BlockTypes Type => BlockTypes.Text;
|
||||
public final class TextBlock extends Block implements TextRendering {
|
||||
|
||||
public TextBlock(String text) {
|
||||
super(text, BlockTypes.Text);
|
||||
@@ -25,18 +22,4 @@ public class TextBlock extends Block implements TextRendering {
|
||||
public TextBlock(String text, int startIndex, int stopIndex) {
|
||||
super(text.substring(startIndex, stopIndex), BlockTypes.Text);
|
||||
}
|
||||
/*
|
||||
|
||||
public override bool IsValid(out string errorMsg)
|
||||
{
|
||||
errorMsg = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
public string Render(ContextVariables? variables)
|
||||
{
|
||||
return this.Content;
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
|
||||
|
||||
+46
-72
@@ -1,91 +1,65 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import reactor.util.annotation.Nullable;
|
||||
|
||||
public class ValBlock extends Block implements TextRendering {
|
||||
public ValBlock(String content) {
|
||||
super(content, BlockTypes.Value);
|
||||
}
|
||||
public final class ValBlock extends Block implements TextRendering {
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return false;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ValBlock.class);
|
||||
|
||||
// Cache the first and last char
|
||||
private char first = '\0';
|
||||
private char last = '\0';
|
||||
|
||||
// Content, excluding start/end quote chars
|
||||
private String value = "";
|
||||
|
||||
public ValBlock(String quotedValue) {
|
||||
super(quotedValue.trim(), BlockTypes.Value);
|
||||
|
||||
if (this.getContent().length() < 2) {
|
||||
LOGGER.error("A value must have single quotes or double quotes on both sides");
|
||||
return;
|
||||
}
|
||||
|
||||
this.first = this.getContent().charAt(0);
|
||||
this.last = this.getContent().charAt(getContent().length() - 1);
|
||||
this.value = this.getContent().substring(1, this.getContent().length() - 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String render(ContextVariables variables) {
|
||||
return null;
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
internal override BlockTypes Type => BlockTypes.Value;
|
||||
|
||||
// Cache the first and last char
|
||||
private readonly char _first = '\0';
|
||||
private readonly char _last = '\0';
|
||||
|
||||
// Content, excluding start/end quote chars
|
||||
private readonly string _value = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance
|
||||
/// </summary>
|
||||
/// <param name="quotedValue">Block content, including the delimiting chars</param>
|
||||
/// <param name="log">Optional logger</param>
|
||||
public ValBlock(string? quotedValue, ILogger? log = null)
|
||||
: base(quotedValue?.Trim(), log)
|
||||
{
|
||||
if (this.Content.Length < 2)
|
||||
{
|
||||
this.Log.LogError("A value must have single quotes or double quotes on both sides");
|
||||
return;
|
||||
}
|
||||
|
||||
this._first = this.Content[0];
|
||||
this._last = this.Content[this.Content.Length - 1];
|
||||
this._value = this.Content.Substring(1, this.Content.Length - 2);
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
// Content includes the quotes, so it must be at least 2 chars long
|
||||
if (this.getContent().length() < 2) {
|
||||
LOGGER.error("A value must have single quotes or double quotes on both sides");
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma warning disable CA2254 // error strings are used also internally, not just for logging
|
||||
// ReSharper disable TemplateIsNotCompileTimeConstantProblem
|
||||
public override bool IsValid(out string errorMsg)
|
||||
{
|
||||
errorMsg = string.Empty;
|
||||
|
||||
// Content includes the quotes, so it must be at least 2 chars long
|
||||
if (this.Content.Length < 2)
|
||||
{
|
||||
errorMsg = "A value must have single quotes or double quotes on both sides";
|
||||
this.Log.LogError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if delimiting chars are consistent
|
||||
if (this._first != this._last)
|
||||
{
|
||||
errorMsg = "A value must be defined using either single quotes or double quotes, not both";
|
||||
this.Log.LogError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma warning restore CA2254
|
||||
|
||||
public string Render(ContextVariables? variables)
|
||||
{
|
||||
return this._value;
|
||||
// Check if delimiting chars are consistent
|
||||
if (first != last) {
|
||||
LOGGER.error(
|
||||
"A value must be defined using either single quotes or double quotes, not"
|
||||
+ " both");
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool HasValPrefix(string? text)
|
||||
{
|
||||
return !text.IsNullOrEmpty()
|
||||
&& text.Length > 0
|
||||
&& (text[0] is Symbols.DblQuote or Symbols.SglQuote);
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean hasValPrefix(@Nullable String text) {
|
||||
return text != null
|
||||
&& text.length() > 0
|
||||
&& (text.charAt(0) == Symbols.DblQuote || text.charAt(0) == Symbols.SglQuote);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-83
@@ -1,23 +1,25 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.templateengine.blocks;
|
||||
|
||||
import com.microsoft.semantickernel.orchestration.ContextVariables;
|
||||
import com.microsoft.semantickernel.templateengine.TemplateException;
|
||||
|
||||
public class VarBlock extends Block implements TextRendering {
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class VarBlock extends Block implements TextRendering {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(VarBlock.class);
|
||||
private final String name;
|
||||
|
||||
public VarBlock(String content) {
|
||||
super(content, BlockTypes.Variable);
|
||||
|
||||
this.name = content.substring(1);
|
||||
}
|
||||
if (content.length() < 2) {
|
||||
LOGGER.error("The variable name is empty");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
this.name = content.substring(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -27,93 +29,47 @@ public class VarBlock extends Block implements TextRendering {
|
||||
}
|
||||
|
||||
if (name == null || name.isEmpty()) {
|
||||
// TODO
|
||||
// const string errMsg = "Variable rendering failed, the variable name is empty";
|
||||
// this.Log.LogError(errMsg);
|
||||
// throw new TemplateException(TemplateException.ErrorCodes.SyntaxError, errMsg);
|
||||
throw new TemplateException();
|
||||
throw new TemplateException(
|
||||
TemplateException.ErrorCodes.SyntaxError,
|
||||
"Variable rendering failed, the variable name is empty");
|
||||
}
|
||||
|
||||
String value = variables.asMap().get(name);
|
||||
|
||||
if (value == null) {
|
||||
// TODO
|
||||
// this.Log.LogWarning("Variable `{0}{1}` not found", Symbols.VarPrefix, this.Name);
|
||||
|
||||
LOGGER.warn("Variable `{}{}` not found", Symbols.VarPrefix, name);
|
||||
}
|
||||
|
||||
return value != null ? value : "";
|
||||
}
|
||||
/*
|
||||
internal override BlockTypes Type => BlockTypes.Variable;
|
||||
|
||||
internal string Name { get; } = string.Empty;
|
||||
|
||||
public VarBlock(string? content, ILogger? log = null) : base(content?.Trim(), log)
|
||||
{
|
||||
if (this.Content.Length < 2)
|
||||
{
|
||||
this.Log.LogError("The variable name is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
this.Name = this.Content.Substring(1);
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
if (getContent() == null || getContent().isEmpty()) {
|
||||
LOGGER.error(
|
||||
"A variable must start with the symbol {} and have a name", Symbols.VarPrefix);
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma warning disable CA2254 // error strings are used also internally, not just for logging
|
||||
// ReSharper disable TemplateIsNotCompileTimeConstantProblem
|
||||
public override bool IsValid(out string errorMsg)
|
||||
{
|
||||
errorMsg = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(this.Content))
|
||||
{
|
||||
errorMsg = $"A variable must start with the symbol {Symbols.VarPrefix} and have a name";
|
||||
this.Log.LogError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.Content[0] != Symbols.VarPrefix)
|
||||
{
|
||||
errorMsg = $"A variable must start with the symbol {Symbols.VarPrefix}";
|
||||
this.Log.LogError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.Content.Length < 2)
|
||||
{
|
||||
errorMsg = "The variable name is empty";
|
||||
this.Log.LogError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Regex.IsMatch(this.Name, "^[a-zA-Z0-9_]*$"))
|
||||
{
|
||||
errorMsg = $"The variable name '{this.Name}' contains invalid characters. " +
|
||||
"Only alphanumeric chars and underscore are allowed.";
|
||||
this.Log.LogError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#pragma warning restore CA2254
|
||||
|
||||
public string Render(ContextVariables? variables)
|
||||
{
|
||||
if (variables == null) { return string.Empty; }
|
||||
|
||||
if (string.IsNullOrEmpty(this.Name))
|
||||
{
|
||||
const string errMsg = "Variable rendering failed, the variable name is empty";
|
||||
this.Log.LogError(errMsg);
|
||||
throw new TemplateException(TemplateException.ErrorCodes.SyntaxError, errMsg);
|
||||
}
|
||||
|
||||
var exists = variables.Get(this.Name, out string value);
|
||||
if (!exists) { this.Log.LogWarning("Variable `{0}{1}` not found", Symbols.VarPrefix, this.Name); }
|
||||
|
||||
return exists ? value : string.Empty;
|
||||
if (getContent().charAt(0) != Symbols.VarPrefix) {
|
||||
LOGGER.error("A variable must start with the symbol {}", Symbols.VarPrefix);
|
||||
return false;
|
||||
}
|
||||
|
||||
*/
|
||||
if (getContent().length() < 2) {
|
||||
LOGGER.error("The variable name is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!name.matches("^[a-zA-Z0-9_]*$")) {
|
||||
LOGGER.error(
|
||||
"The variable name '{}' contains invalid characters. "
|
||||
+ "Only alphanumeric chars and underscore are allowed.",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
com.microsoft.semantickernel.KernelDefaultBuilder
|
||||
com.microsoft.semantickernel.DefaultKernelBuilder
|
||||
+35
-26
@@ -5,6 +5,7 @@ import com.azure.ai.openai.models.Choice;
|
||||
import com.azure.ai.openai.models.Completions;
|
||||
import com.azure.ai.openai.models.CompletionsOptions;
|
||||
import com.microsoft.openai.AzureOpenAIClient;
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
import com.microsoft.semantickernel.builders.SKBuilders;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.textcompletion.OpenAITextCompletion;
|
||||
import com.microsoft.semantickernel.extensions.KernelExtensions;
|
||||
@@ -17,6 +18,7 @@ import com.microsoft.semantickernel.textcompletion.TextCompletion;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -27,6 +29,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DefaultKernelTest {
|
||||
|
||||
@@ -34,10 +37,9 @@ public class DefaultKernelTest {
|
||||
void contextVariableTest() {
|
||||
String model = "a-model";
|
||||
|
||||
List<Tuple2<String, String>> responses =
|
||||
Arrays.asList(Tuples.of("A", "a"), Tuples.of("user: Aauser: B", "b"));
|
||||
|
||||
com.azure.ai.openai.OpenAIAsyncClient client = mockCompletionOpenAIAsyncClient(responses);
|
||||
OpenAIAsyncClient client =
|
||||
mockCompletionOpenAIAsyncClient(
|
||||
Tuples.of("A", "a"), Tuples.of("user: Aauser: B", "b"));
|
||||
|
||||
Kernel kernel = buildKernel(model, client);
|
||||
|
||||
@@ -82,8 +84,7 @@ public class DefaultKernelTest {
|
||||
@Test
|
||||
void tellAJoke() {
|
||||
String expectedResponse = "a result joke";
|
||||
com.azure.ai.openai.OpenAIAsyncClient client =
|
||||
mockCompletionOpenAIAsyncClient("WRITE", expectedResponse);
|
||||
OpenAIAsyncClient client = mockCompletionOpenAIAsyncClient("WRITE", expectedResponse);
|
||||
String model = "a-model-name";
|
||||
Kernel kernel = buildKernel(model, client);
|
||||
|
||||
@@ -117,10 +118,7 @@ public class DefaultKernelTest {
|
||||
assertTheResultEquals(result, expectedResponse);
|
||||
}
|
||||
|
||||
public static Kernel buildKernel(
|
||||
String model, com.azure.ai.openai.OpenAIAsyncClient openAIAsyncClient) {
|
||||
|
||||
com.microsoft.openai.OpenAIAsyncClient client = new AzureOpenAIClient(openAIAsyncClient);
|
||||
public static Kernel buildKernel(String model, OpenAIAsyncClient client) {
|
||||
|
||||
TextCompletion textCompletion = new OpenAITextCompletion(client, model);
|
||||
|
||||
@@ -132,12 +130,11 @@ public class DefaultKernelTest {
|
||||
return SKBuilders.kernel().setKernelConfig(kernelConfig).build();
|
||||
}
|
||||
|
||||
private static com.azure.ai.openai.OpenAIAsyncClient mockCompletionOpenAIAsyncClient(
|
||||
String arg, String response) {
|
||||
private static AzureOpenAIClient mockCompletionOpenAIAsyncClient(String arg, String response) {
|
||||
List<Tuple2<String, String>> responses =
|
||||
Collections.singletonList(Tuples.of(arg, response));
|
||||
|
||||
return mockCompletionOpenAIAsyncClient(responses);
|
||||
return mockCompletionOpenAIAsyncClient(responses.toArray(new Tuple2[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -152,12 +149,28 @@ public class DefaultKernelTest {
|
||||
|
||||
This if the client is prompted with "Tell me a joke", the mocked client would respond with "This is a joke"
|
||||
*/
|
||||
public static com.azure.ai.openai.OpenAIAsyncClient mockCompletionOpenAIAsyncClient(
|
||||
List<Tuple2<String, String>> responses) {
|
||||
|
||||
public static AzureOpenAIClient mockCompletionOpenAIAsyncClient(
|
||||
Tuple2<String, String>... responses) {
|
||||
|
||||
List<Tuple2<ArgumentMatcher<String>, String>> matchers =
|
||||
Arrays.stream(responses)
|
||||
.map(
|
||||
response ->
|
||||
Tuples.<ArgumentMatcher<String>, String>of(
|
||||
arg -> arg.contains(response.getT1()),
|
||||
response.getT2()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return mockCompletionOpenAIAsyncClientMatchers(matchers.toArray(new Tuple2[0]));
|
||||
}
|
||||
|
||||
public static AzureOpenAIClient mockCompletionOpenAIAsyncClientMatchers(
|
||||
Tuple2<ArgumentMatcher<String>, String>... responses) {
|
||||
com.azure.ai.openai.OpenAIAsyncClient openAIAsyncClient =
|
||||
Mockito.mock(com.azure.ai.openai.OpenAIAsyncClient.class);
|
||||
|
||||
for (Tuple2<String, String> response : responses) {
|
||||
for (Tuple2<ArgumentMatcher<String>, String> response : responses) {
|
||||
|
||||
Choice choice = Mockito.mock(Choice.class);
|
||||
Mockito.when(choice.getText()).thenReturn(response.getT2());
|
||||
@@ -170,13 +183,11 @@ public class DefaultKernelTest {
|
||||
openAIAsyncClient.getCompletions(
|
||||
Mockito.any(String.class),
|
||||
Mockito.<CompletionsOptions>argThat(
|
||||
it ->
|
||||
it.getPrompt()
|
||||
.get(0)
|
||||
.contains(response.getT1()))))
|
||||
it -> response.getT1().matches(it.getPrompt().get(0)))))
|
||||
.thenReturn(Mono.just(completions));
|
||||
}
|
||||
return openAIAsyncClient;
|
||||
AzureOpenAIClient client = new AzureOpenAIClient(openAIAsyncClient);
|
||||
return Mockito.spy(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -185,7 +196,7 @@ public class DefaultKernelTest {
|
||||
String model = "a-model";
|
||||
|
||||
String expectedResponse = "foo";
|
||||
com.azure.ai.openai.OpenAIAsyncClient openAIAsyncClient =
|
||||
OpenAIAsyncClient openAIAsyncClient =
|
||||
mockCompletionOpenAIAsyncClient("block", expectedResponse);
|
||||
|
||||
Kernel kernel = buildKernel(model, openAIAsyncClient);
|
||||
@@ -219,13 +230,11 @@ public class DefaultKernelTest {
|
||||
}
|
||||
|
||||
private static void assertCompletionsWasCalledWithModelAndText(
|
||||
com.azure.ai.openai.OpenAIAsyncClient openAIAsyncClient,
|
||||
String model,
|
||||
String expected) {
|
||||
OpenAIAsyncClient openAIAsyncClient, String model, String expected) {
|
||||
Mockito.verify(openAIAsyncClient, Mockito.times(1))
|
||||
.getCompletions(
|
||||
Mockito.matches(model),
|
||||
Mockito.<CompletionsOptions>argThat(
|
||||
Mockito.argThat(
|
||||
completionsOptions ->
|
||||
completionsOptions.getPrompt().size() == 1
|
||||
&& completionsOptions
|
||||
|
||||
-2
@@ -8,7 +8,6 @@ import com.microsoft.semantickernel.ai.embeddings.EmbeddingGeneration;
|
||||
import com.microsoft.semantickernel.connectors.ai.openai.textembeddings.OpenAITextEmbeddingGeneration;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
@@ -43,7 +42,6 @@ public class TextEmbeddingsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void testEmbedding() {
|
||||
testEmbeddingGeneration(mockEmbeddingOpenAIAsyncClient(), 1);
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples;
|
||||
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
import com.microsoft.semantickernel.DefaultKernelTest;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
@@ -12,13 +13,10 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Example02PipelineTest {
|
||||
@Test
|
||||
public void run() {
|
||||
com.azure.ai.openai.OpenAIAsyncClient client =
|
||||
DefaultKernelTest.mockCompletionOpenAIAsyncClient(new ArrayList<>());
|
||||
OpenAIAsyncClient client = DefaultKernelTest.mockCompletionOpenAIAsyncClient();
|
||||
Kernel kernel = DefaultKernelTest.buildKernel("model", client);
|
||||
|
||||
// Load native skill
|
||||
|
||||
+2
-4
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples;
|
||||
|
||||
import com.microsoft.openai.OpenAIAsyncClient;
|
||||
import com.microsoft.semantickernel.DefaultKernelTest;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.builders.SKBuilders;
|
||||
@@ -14,13 +15,10 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Example03VariablesTest {
|
||||
@Test
|
||||
public void run() {
|
||||
com.azure.ai.openai.OpenAIAsyncClient client =
|
||||
DefaultKernelTest.mockCompletionOpenAIAsyncClient(new ArrayList<>());
|
||||
OpenAIAsyncClient client = DefaultKernelTest.mockCompletionOpenAIAsyncClient();
|
||||
Kernel kernel = DefaultKernelTest.buildKernel("model", client);
|
||||
|
||||
// Load native skill
|
||||
|
||||
+11
-33
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples;
|
||||
|
||||
import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient;
|
||||
|
||||
import com.microsoft.openai.AzureOpenAIClient;
|
||||
import com.microsoft.semantickernel.DefaultKernelTest;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.KernelConfig;
|
||||
import com.microsoft.semantickernel.builders.SKBuilders;
|
||||
@@ -16,17 +16,17 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public class Example04CombineLLMPromptsAndNativeCode {
|
||||
public class Example04CombineLLMPromptsAndNativeCodeTest {
|
||||
|
||||
@Test
|
||||
public void run() {
|
||||
com.microsoft.openai.OpenAIAsyncClient client =
|
||||
new AzureOpenAIClient(
|
||||
DefaultKernelTest.mockCompletionOpenAIAsyncClient(new ArrayList<>()));
|
||||
AzureOpenAIClient client =
|
||||
mockCompletionOpenAIAsyncClient(
|
||||
Tuples.of(
|
||||
"Gran Torre Santiago is the tallest building in South America",
|
||||
"A-SUMMARY"));
|
||||
|
||||
KernelConfig kernelConfig =
|
||||
SKBuilders.kernelConfig()
|
||||
@@ -62,28 +62,6 @@ public class Example04CombineLLMPromptsAndNativeCode {
|
||||
kernel.getSkills().getFunction("Search", null),
|
||||
kernel.getSkill("SummarizeSkill").getFunction("Summarize", null));
|
||||
|
||||
Assertions.assertEquals(
|
||||
"Gran Torre Santiago is the tallest building in South America summary",
|
||||
result.block().getResult());
|
||||
|
||||
/*
|
||||
var result2 = await kernel.RunAsync(
|
||||
ask,
|
||||
search["Search"],
|
||||
sumSkill["Summarize"]
|
||||
);
|
||||
|
||||
var result3 = await kernel.RunAsync(
|
||||
ask,
|
||||
search["Search"],
|
||||
sumSkill["Notegen"]
|
||||
);
|
||||
|
||||
Console.WriteLine(ask + "\n");
|
||||
Console.WriteLine("Bing Answer: " + result1 + "\n");
|
||||
Console.WriteLine("Summary: " + result2 + "\n");
|
||||
Console.WriteLine("Notes: " + result3 + "\n");
|
||||
|
||||
*/
|
||||
Assertions.assertEquals("A-SUMMARY", result.block().getResult());
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples;
|
||||
|
||||
import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClientMatchers;
|
||||
|
||||
import com.microsoft.openai.AzureOpenAIClient;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.KernelConfig;
|
||||
import com.microsoft.semantickernel.builders.SKBuilders;
|
||||
import com.microsoft.semantickernel.extensions.KernelExtensions;
|
||||
import com.microsoft.semantickernel.planner.sequentialplanner.SequentialPlanner;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
public class Example05UsingThePlannerTest {
|
||||
|
||||
public static SequentialPlanner getPlanner(Kernel kernel) {
|
||||
kernel.importSkill(
|
||||
"SummarizeSkill",
|
||||
KernelExtensions.importSemanticSkillFromDirectory(
|
||||
"../../samples/skills", "SummarizeSkill"));
|
||||
kernel.importSkill(
|
||||
"WriterSkill",
|
||||
KernelExtensions.importSemanticSkillFromDirectory(
|
||||
"../../samples/skills", "WriterSkill"));
|
||||
|
||||
return new SequentialPlanner(kernel, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void run() {
|
||||
ArgumentMatcher<String> matcher =
|
||||
prompt -> {
|
||||
return prompt.contains(
|
||||
"Create an XML plan step by step, to satisfy the goal given");
|
||||
};
|
||||
|
||||
AzureOpenAIClient client =
|
||||
mockCompletionOpenAIAsyncClientMatchers(Tuples.of(matcher, "A-PLAN"));
|
||||
|
||||
KernelConfig config =
|
||||
SKBuilders.kernelConfig()
|
||||
.addTextCompletionService(
|
||||
"davinci",
|
||||
kernel ->
|
||||
SKBuilders.textCompletionService()
|
||||
.build(client, "text-davinci-003"))
|
||||
.build();
|
||||
|
||||
Kernel kernel = SKBuilders.kernel().setKernelConfig(config).build();
|
||||
|
||||
SequentialPlanner planner = getPlanner(kernel);
|
||||
System.out.println(
|
||||
planner.createPlanAsync(
|
||||
"Write a poem about John Doe, then translate it into Italian.")
|
||||
.block()
|
||||
.getResult());
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples;
|
||||
|
||||
import static com.microsoft.semantickernel.DefaultKernelTest.mockCompletionOpenAIAsyncClient;
|
||||
|
||||
import com.microsoft.openai.AzureOpenAIClient;
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.KernelConfig;
|
||||
import com.microsoft.semantickernel.builders.SKBuilders;
|
||||
import com.microsoft.semantickernel.coreskills.TimeSkill;
|
||||
import com.microsoft.semantickernel.orchestration.SKContext;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplate;
|
||||
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
|
||||
import com.microsoft.semantickernel.templateengine.PromptTemplateEngine;
|
||||
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Example06TemplateLanguageTest {
|
||||
|
||||
@Test
|
||||
public void run() {
|
||||
AzureOpenAIClient client =
|
||||
mockCompletionOpenAIAsyncClient(Tuples.of("Today is", "A-RESULT"));
|
||||
|
||||
KernelConfig kernelConfig =
|
||||
SKBuilders.kernelConfig()
|
||||
.addTextCompletionService(
|
||||
"text-davinci-003",
|
||||
kernel ->
|
||||
SKBuilders.textCompletionService()
|
||||
.build(client, "text-davinci-003"))
|
||||
.addTextEmbeddingsGenerationService(
|
||||
"text-embedding-ada-002",
|
||||
kernel ->
|
||||
SKBuilders.textEmbeddingGenerationService()
|
||||
.build(client, "text-embedding-ada-002"))
|
||||
.build();
|
||||
|
||||
Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();
|
||||
|
||||
// Load native skill into the kernel skill collection, sharing its functions with prompt
|
||||
// templates
|
||||
// Functions loaded here are available as "time.*"
|
||||
kernel.importSkill(new TimeSkill(), "time");
|
||||
|
||||
// Semantic Function invoking time.Date and time.Time native functions
|
||||
String functionDefinition =
|
||||
"\n"
|
||||
+ "Today is: {{time.Date}}\n"
|
||||
+ "Current time is: {{time.Time}}\n"
|
||||
+ "\n"
|
||||
+ "Answer to the following questions using JSON syntax, including the data"
|
||||
+ " used.\n"
|
||||
+ "Is it morning, afternoon, evening, or night"
|
||||
+ " (morning/afternoon/evening/night)?\n"
|
||||
+ "Is it weekend time (weekend/not weekend)?";
|
||||
|
||||
PromptTemplate promptRenderer = SKBuilders.promptTemplate().build(functionDefinition, null);
|
||||
|
||||
SKContext skContext = SKBuilders.context().build(kernel.getSkills());
|
||||
|
||||
PromptTemplateEngine promptTemplateEngine = SKBuilders.promptTemplateEngine().build();
|
||||
|
||||
Mono<String> renderedPrompt = promptRenderer.renderAsync(skContext, promptTemplateEngine);
|
||||
|
||||
// Check that it has been rendered
|
||||
Assertions.assertTrue(!renderedPrompt.block().contains("time.Date"));
|
||||
|
||||
// Run the prompt / semantic function
|
||||
CompletionSKFunction kindOfDay =
|
||||
kernel.getSemanticFunctionBuilder()
|
||||
.createFunction(
|
||||
functionDefinition,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new PromptTemplateConfig.CompletionConfig(
|
||||
0, 0, 0, 0, 256, new ArrayList<>()));
|
||||
|
||||
Assertions.assertEquals("A-RESULT", kindOfDay.invokeAsync("").block().getResult());
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples.skills; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples.skills;
|
||||
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples.skills; // Copyright (c) Microsoft. All rights
|
||||
// reserved.
|
||||
package com.microsoft.semantickernel.syntaxexamples.skills;
|
||||
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.DefineSKFunction;
|
||||
import com.microsoft.semantickernel.skilldefinition.annotations.SKFunctionParameters;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.planner; // Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.planner;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.planner.sequentialplanner; // Copyright (c) Microsoft. All
|
||||
// rights reserved.
|
||||
package com.microsoft.semantickernel.planner.sequentialplanner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
package com.microsoft.semantickernel.planner.sequentialplanner; // Copyright (c) Microsoft. All
|
||||
// rights reserved.
|
||||
package com.microsoft.semantickernel.planner.sequentialplanner;
|
||||
|
||||
import com.microsoft.semantickernel.Kernel;
|
||||
import com.microsoft.semantickernel.builders.FunctionBuilders;
|
||||
|
||||
Reference in New Issue
Block a user