Skip to content

Commit

Permalink
Initial proposal for Java Kernel (#1081)
Browse files Browse the repository at this point in the history
### 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 SK Contribution Guidelines
(https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md)
- [ ] The code follows the .NET coding conventions
(https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions)
verified with `dotnet format`
- [ ] All unit tests pass, and I have added new tests where possible
- [ ] I didn't break anyone 😄

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Milder Hernandez Cagua <[email protected]>
Co-authored-by: Milder Hernandez <[email protected]>
Co-authored-by: Yoshio Terada <[email protected]>
Co-authored-by: Mark Wallace <[email protected]>
Co-authored-by: name <email>
Co-authored-by: Almir Kazazic <[email protected]>
Co-authored-by: Gudge <[email protected]>
Co-authored-by: Devis Lucato <[email protected]>
Co-authored-by: Alexander Siniouguine <[email protected]>
Co-authored-by: Harleen Thind <[email protected]>
Co-authored-by: David Barkol <[email protected]>
Co-authored-by: Adrian Bonar <[email protected]>
Co-authored-by: Mark Karle <[email protected]>
Co-authored-by: poweihuang0817 <[email protected]>
Co-authored-by: Po-Wei Huang <[email protected]>
Co-authored-by: Lee Miller <[email protected]>
Co-authored-by: Ikko Eltociear Ashimine <[email protected]>
Co-authored-by: Adrian Bonar (HE/HIM) <[email protected]>
Co-authored-by: Tao Chen <[email protected]>
Co-authored-by: Teresa Hoang <[email protected]>
Co-authored-by: Gil LaHaye <[email protected]>
Co-authored-by: Shawn Callegari <[email protected]>
Co-authored-by: Vivien Hung <[email protected]>
Co-authored-by: Abby Harrison <[email protected]>
Co-authored-by: Abby Harrison <[email protected]>
Co-authored-by: Devis Lucato <[email protected]>
Co-authored-by: Gina Triolo <[email protected]>
Co-authored-by: fabio fumarola <[email protected]>
Co-authored-by: cdMSFT <[email protected]>
Co-authored-by: Dmytro Struk <[email protected]>
Co-authored-by: Lex Li <[email protected]>
Co-authored-by: Damir Dobric <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aman Sachan <[email protected]>
Co-authored-by: Roger Barreto <[email protected]>
Co-authored-by: Stephen Toub <[email protected]>
Co-authored-by: Craig Presti <[email protected]>
Co-authored-by: Joowon <[email protected]>
Co-authored-by: Richard Edgar <[email protected]>
Co-authored-by: nacharya1 <[email protected]>
Co-authored-by: Kevdome3000 <[email protected]>
Co-authored-by: tech <[email protected]>
Co-authored-by: Masumi Morishige <[email protected]>
Co-authored-by: adityachallapally <[email protected]>
Co-authored-by: Jadyn <[email protected]>
Co-authored-by: Alex Chao <[email protected]>
Co-authored-by: Alex Chao <[email protected]>
  • Loading branch information
Show file tree
Hide file tree
Showing 179 changed files with 13,885 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/java-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Build Java Semantic Kernel

on:
push:
branches: [ "experimental-java", "java-dev" ]
pull_request:
branches: [ "experimental-java", "java-dev" ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: maven

- name: Build with Maven
run: cd java && ./mvnw -B -Pbug-check clean install --file pom.xml
30 changes: 30 additions & 0 deletions .github/workflows/java-integration-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Run Java Integration Tests and Samples

on:
push:
branches: [ "experimental-java", "java-dev" ]
pull_request:
branches: [ "experimental-java", "java-dev" ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven

- name: Build with Maven
run: cd java && ./mvnw -B -DskipTests -Pbug-check clean install --file pom.xml

- name: Run Tests
run: cd java/api-test && ../mvnw -B -Pbug-check clean install --file pom.xml

- name: Build samples
run: cd java/samples && ../mvnw -B clean install --file pom.xml
10 changes: 10 additions & 0 deletions java/.mvn/jvm.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
18 changes: 18 additions & 0 deletions java/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
102 changes: 102 additions & 0 deletions java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Semantic Kernel for Java

Semantic Kernel (SK) is a lightweight SDK that lets you easily mix conventional programming languages with the latest in
Large Language Model (LLM) AI "prompts" with templating, chaining, and planning capabilities out-of-the-box.

To learn more about Microsoft Semantic Kernel, visit
the [Microsoft Semantic Kernel documentation](https://learn.microsoft.com/en-us/semantic-kernel/whatissk).

The Semantic Kernel for Java is an SDK that implements the key concepts of the Semantic Kernel in Java. It is designed
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

To run the LLM prompts and semantic functions in this kernel, make sure you have
an [Open AI API Key](https://openai.com/api/)
or [Azure Open AI service key](https://learn.microsoft.com/azure/cognitive-services/openai/quickstart?pivots=rest-api).

### Requirements

To build the semantic kernel, you will need to have:

- **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

### Build the semantic kernel

1. Clone this repository

git clone [email protected]:microsoft/semantic-kernel.git

2. Build the semantic kernel

cd semantic-kernel/java
mvn install

## Using the semantic kernel

Check the `samples` folder for examples of how to use the semantic kernel.

## Discord community

Join the [Microsoft Semantic Kernel Discord community](https://aka.ms/java-sk-discord) to discuss the Semantic Kernel
and get help from the community. We have a `#java` channel for Java-specific questions.

## Contributing

### Testing locally

The project may contain integration tests that require an OpenAI key to run. To run the integration tests locally, you
will need to set the following environment variable:

- `OPENAI_API_KEY` - the OpenAI API key.

If you are using Azure OpenAI, you will also need to set the following environment variables:

- `AZURE_OPENAI_ENDPOINT` - the Azure OpenAI endpoint found in **Keys * Endpoint** section of the Azure OpenAI service.
- `AZURE_OPENAI_API_KEY` - the Azure OpoenAI API key found in **Keys * Endpoint** section of the Azure OpenAI service.
- `AZURE_OPENAI_DEPLOYMENT_NAME` - the custom name you chose for your deployment when you deployed a model. It can be
found under **Resource Management > Deployments** in the Azure Portal.

For more information, see the Azure OpenAI documentation
on [how to get your Azure OpenAI credentials](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/quickstart?pivots=rest-api&tabs=command-line#retrieve-key-and-endpoint).

To run the unit tests only, run the following command:

mvn package

To run all tests, including integration tests that require an OpenAI key, run the following command:

mvn verify

### Submitting a pull request

Before submitting a pull request, please make sure that you have run the project with the command:

```shell
./mvnw clean package -Pbug-check
```

The bug-check profile will detect some static analysis issues that will prevent merging as well as apply formatting
requirements to the code base.

Also ensure that:

- All new code is covered by unit tests
- All new code is covered by integration tests

Once your proposal is ready, submit a pull request to the `main` branch. The pull request will be reviewed by the
project maintainers.

Make sure your pull request has an objective title and a clear description explaining the problem and solution.

## License

This project is licensed under the [MIT License](LICENSE).

## Code of Conduct

This project has adopted the [Microsoft Open Source Code of Conduct](../CODE_OF_CONDUCT.md).

36 changes: 36 additions & 0 deletions java/api-test/api-usage-example/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?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">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.microsoft.semantickernel.test</groupId>
<artifactId>api-test</artifactId>
<version>0.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>api-usage-example</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>com.microsoft.semantickernel</groupId>
<artifactId>semantickernel-core</artifactId>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright (c) Microsoft. All rights reserved.
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.core.credential.AzureKeyCredential;
import com.microsoft.openai.AzureOpenAIClient;
import com.microsoft.openai.OpenAIAsyncClient;
import com.microsoft.semantickernel.Kernel;
import com.microsoft.semantickernel.KernelConfig;
import com.microsoft.semantickernel.builders.SKBuilders;
import com.microsoft.semantickernel.semanticfunctions.PromptTemplateConfig;
import com.microsoft.semantickernel.textcompletion.CompletionSKContext;
import com.microsoft.semantickernel.textcompletion.CompletionSKFunction;
import com.microsoft.semantickernel.textcompletion.TextCompletion;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Properties;

public class InlineFunctionExample {
public static final String AZURE_CONF_PROPERTIES = "conf.properties";
private static final Logger LOGGER = LoggerFactory.getLogger(InlineFunctionExample.class);
private static final String MODEL = "text-davinci-003";

public static String getToken(String configName) throws IOException {
return getConfigValue(configName, "token");
}

public static String getEndpoint(String configName) throws IOException {
return getConfigValue(configName, "endpoint");
}

private static String getConfigValue(String configName, String propertyName)
throws IOException {
Path configPath = Paths.get(System.getProperty("user.home"), ".oai", configName);
Properties props = new Properties();
try (var reader = Files.newBufferedReader(configPath)) {
props.load(reader);
} catch (IOException e) {
LOGGER.error("Failed to read config file: " + configPath);
throw e;
}
String apiKey = props.getProperty(propertyName);
if (apiKey == null) {
LOGGER.error("NO PROPERTY " + propertyName);
return "";
}
return apiKey;
}

public static void main(String[] args) throws IOException {
String apiKey = getToken(AZURE_CONF_PROPERTIES);

OpenAIAsyncClient client =
new AzureOpenAIClient(
new OpenAIClientBuilder()
.endpoint(getEndpoint(AZURE_CONF_PROPERTIES))
.credential(new AzureKeyCredential(apiKey))
.buildAsyncClient());

TextCompletion textCompletion = SKBuilders.textCompletionService().build(client, MODEL);

KernelConfig kernelConfig =
new KernelConfig.Builder()
.addTextCompletionService(MODEL, kernel -> textCompletion)
.build();

Kernel kernel = SKBuilders.kernel().setKernelConfig(kernelConfig).build();

String prompt = "{{$input}}\n" + "Summarize the content above.";

CompletionSKFunction summarize =
kernel.getSemanticFunctionBuilder()
.createFunction(
prompt,
"summarize",
null,
null,
new PromptTemplateConfig.CompletionConfig(
0.2, 0.5, 0, 0, 2000, new ArrayList<>()));

String text =
"""
Demo (ancient Greek poet)
From Wikipedia, the free encyclopedia
Demo or Damo (Greek: Δεμώ, Δαμώ; fl. c. AD 200) was a Greek woman of the
Roman period, known for a single epigram, engraved upon the Colossus of
Memnon, which bears her name. She speaks of herself therein as a lyric
poetess dedicated to the Muses, but nothing is known of her life.[1]
Identity
Demo was evidently Greek, as her name, a traditional epithet of Demeter,
signifies. The name was relatively common in the Hellenistic world, in
Egypt and elsewhere, and she cannot be further identified. The date of her
visit to the Colossus of Memnon cannot be established with certainty, but
internal evidence on the left leg suggests her poem was inscribed there at
some point in or after AD 196.[2]
Epigram
There are a number of graffiti inscriptions on the Colossus of Memnon.
Following three epigrams by Julia Balbilla, a fourth epigram, in elegiac
couplets, entitled and presumably authored by "Demo" or "Damo" (the
Greek inscription is difficult to read), is a dedication to the Muses.[2]
The poem is traditionally published with the works of Balbilla, though the
internal evidence suggests a different author.[1]
In the poem, Demo explains that Memnon has shown her special respect. In
return, Demo offers the gift for poetry, as a gift to the hero. At the end
of this epigram, she addresses Memnon, highlighting his divine status by
recalling his strength and holiness.[2]
Demo, like Julia Balbilla, writes in the artificial and poetic Aeolic
dialect. The language indicates she was knowledgeable in Homeric
poetry—'bearing a pleasant gift', for example, alludes to the use of that
phrase throughout the Iliad and Odyssey.[a][2];
""";

CompletionSKContext context = summarize.invokeAsync(text).block();

if (context != null) {
LOGGER.info("Result: " + context.getResult());
} else {
LOGGER.error("Null result");
}
}
}
Loading

0 comments on commit 4adc2ad

Please sign in to comment.