-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #223 from quarkiverse/openshift-ai
Introduce first version of OpenShift AI extension
- Loading branch information
Showing
16 changed files
with
590 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?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>io.quarkiverse.langchain4j</groupId> | ||
<artifactId>quarkus-langchain4j-openshift-ai-parent</artifactId> | ||
<version>999-SNAPSHOT</version> | ||
</parent> | ||
|
||
|
||
<artifactId>quarkus-langchain4j-openshift-ai-deployment</artifactId> | ||
<name>Quarkus Langchain4j - OpenShift AI - Deployment</name> | ||
<dependencies> | ||
<dependency> | ||
<groupId>io.quarkiverse.langchain4j</groupId> | ||
<artifactId>quarkus-langchain4j-openshift-ai</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-rest-client-reactive-jackson-deployment</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkiverse.langchain4j</groupId> | ||
<artifactId>quarkus-langchain4j-core-deployment</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-junit5-internal</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.assertj</groupId> | ||
<artifactId>assertj-core</artifactId> | ||
<version>${assertj.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.wiremock</groupId> | ||
<artifactId>wiremock-standalone</artifactId> | ||
<version>${wiremock.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<configuration> | ||
<annotationProcessorPaths> | ||
<path> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-extension-processor</artifactId> | ||
<version>${quarkus.version}</version> | ||
</path> | ||
</annotationProcessorPaths> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
16 changes: 16 additions & 0 deletions
16
...rc/main/java/io/quarkiverse/langchain4j/openshift/ai/deployment/ChatModelBuildConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package io.quarkiverse.langchain4j.openshift.ai.deployment; | ||
|
||
import java.util.Optional; | ||
|
||
import io.quarkus.runtime.annotations.ConfigDocDefault; | ||
import io.quarkus.runtime.annotations.ConfigGroup; | ||
|
||
@ConfigGroup | ||
public interface ChatModelBuildConfig { | ||
|
||
/** | ||
* Whether the model should be enabled | ||
*/ | ||
@ConfigDocDefault("true") | ||
Optional<Boolean> enabled(); | ||
} |
16 changes: 16 additions & 0 deletions
16
...io/quarkiverse/langchain4j/openshift/ai/deployment/Langchain4jOpenshiftAiBuildConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package io.quarkiverse.langchain4j.openshift.ai.deployment; | ||
|
||
import static io.quarkus.runtime.annotations.ConfigPhase.BUILD_TIME; | ||
|
||
import io.quarkus.runtime.annotations.ConfigRoot; | ||
import io.smallrye.config.ConfigMapping; | ||
|
||
@ConfigRoot(phase = BUILD_TIME) | ||
@ConfigMapping(prefix = "quarkus.langchain4j.openshift-ai") | ||
public interface Langchain4jOpenshiftAiBuildConfig { | ||
|
||
/** | ||
* Chat model related settings | ||
*/ | ||
ChatModelBuildConfig chatModel(); | ||
} |
56 changes: 56 additions & 0 deletions
56
...rc/main/java/io/quarkiverse/langchain4j/openshift/ai/deployment/OpenshiftAiProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package io.quarkiverse.langchain4j.openshift.ai.deployment; | ||
|
||
import static io.quarkiverse.langchain4j.deployment.Langchain4jDotNames.CHAT_MODEL; | ||
|
||
import java.util.Optional; | ||
|
||
import jakarta.enterprise.context.ApplicationScoped; | ||
|
||
import io.quarkiverse.langchain4j.deployment.items.ChatModelProviderCandidateBuildItem; | ||
import io.quarkiverse.langchain4j.deployment.items.SelectedChatModelProviderBuildItem; | ||
import io.quarkiverse.langchain4j.openshiftai.runtime.OpenshiftAiRecorder; | ||
import io.quarkiverse.langchain4j.openshiftai.runtime.config.Langchain4jOpenshiftAiConfig; | ||
import io.quarkus.arc.deployment.SyntheticBeanBuildItem; | ||
import io.quarkus.deployment.annotations.BuildProducer; | ||
import io.quarkus.deployment.annotations.BuildStep; | ||
import io.quarkus.deployment.annotations.ExecutionTime; | ||
import io.quarkus.deployment.annotations.Record; | ||
import io.quarkus.deployment.builditem.FeatureBuildItem; | ||
|
||
public class OpenshiftAiProcessor { | ||
|
||
private static final String FEATURE = "langchain4j-openshift-ai"; | ||
|
||
private static final String PROVIDER = "openshift-ai"; | ||
|
||
@BuildStep | ||
FeatureBuildItem feature() { | ||
return new FeatureBuildItem(FEATURE); | ||
} | ||
|
||
@BuildStep | ||
public void providerCandidates(BuildProducer<ChatModelProviderCandidateBuildItem> chatProducer, | ||
Langchain4jOpenshiftAiBuildConfig config) { | ||
if (config.chatModel().enabled().isEmpty() || config.chatModel().enabled().get()) { | ||
chatProducer.produce(new ChatModelProviderCandidateBuildItem(PROVIDER)); | ||
} | ||
} | ||
|
||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType") | ||
@BuildStep | ||
@Record(ExecutionTime.RUNTIME_INIT) | ||
void generateBeans(OpenshiftAiRecorder recorder, | ||
Optional<SelectedChatModelProviderBuildItem> selectedChatItem, | ||
Langchain4jOpenshiftAiConfig config, | ||
BuildProducer<SyntheticBeanBuildItem> beanProducer) { | ||
if (selectedChatItem.isPresent() && PROVIDER.equals(selectedChatItem.get().getProvider())) { | ||
beanProducer.produce(SyntheticBeanBuildItem | ||
.configure(CHAT_MODEL) | ||
.setRuntimeInit() | ||
.defaultBean() | ||
.scope(ApplicationScoped.class) | ||
.supplier(recorder.chatModel(config)) | ||
.done()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?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>io.quarkiverse.langchain4j</groupId> | ||
<artifactId>quarkus-langchain4j-parent</artifactId> | ||
<version>999-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>quarkus-langchain4j-openshift-ai-parent</artifactId> | ||
<name>Quarkus Langchain4j - OpenShift AI - Parent</name> | ||
<packaging>pom</packaging> | ||
|
||
<modules> | ||
<module>deployment</module> | ||
<module>runtime</module> | ||
</modules> | ||
|
||
|
||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?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>io.quarkiverse.langchain4j</groupId> | ||
<artifactId>quarkus-langchain4j-openshift-ai-parent</artifactId> | ||
<version>999-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>quarkus-langchain4j-openshift-ai</artifactId> | ||
<name>Quarkus Langchain4j - OpenShift AI - Runtime</name> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-arc</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-rest-client-reactive-jackson</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkiverse.langchain4j</groupId> | ||
<artifactId>quarkus-langchain4j-core</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
</dependencies> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-extension-maven-plugin</artifactId> | ||
<version>${quarkus.version}</version> | ||
<executions> | ||
<execution> | ||
<phase>compile</phase> | ||
<goals> | ||
<goal>extension-descriptor</goal> | ||
</goals> | ||
<configuration> | ||
<deployment>${project.groupId}:${project.artifactId}-deployment:${project.version}</deployment> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<configuration> | ||
<annotationProcessorPaths> | ||
<path> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-extension-processor</artifactId> | ||
<version>${quarkus.version}</version> | ||
</path> | ||
</annotationProcessorPaths> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<id>generate-codestart-jar</id> | ||
<phase>generate-resources</phase> | ||
<goals> | ||
<goal>jar</goal> | ||
</goals> | ||
<configuration> | ||
<classesDirectory>${project.basedir}/src/main</classesDirectory> | ||
<includes> | ||
<include>codestarts/**</include> | ||
</includes> | ||
<classifier>codestarts</classifier> | ||
<skipIfEmpty>true</skipIfEmpty> | ||
</configuration> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
|
||
</project> |
106 changes: 106 additions & 0 deletions
106
...ai/runtime/src/main/java/io/quarkiverse/langchain4j/openshiftai/OpenshiftAiChatModel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package io.quarkiverse.langchain4j.openshiftai; | ||
|
||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.net.URL; | ||
import java.time.Duration; | ||
import java.util.List; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import org.jboss.resteasy.reactive.client.api.LoggingScope; | ||
|
||
import dev.langchain4j.agent.tool.ToolSpecification; | ||
import dev.langchain4j.data.message.AiMessage; | ||
import dev.langchain4j.data.message.ChatMessage; | ||
import dev.langchain4j.model.chat.ChatLanguageModel; | ||
import dev.langchain4j.model.output.Response; | ||
import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder; | ||
|
||
public class OpenshiftAiChatModel implements ChatLanguageModel { | ||
public static final String TLS_TRUST_ALL = "quarkus.tls.trust-all"; | ||
private final String modelId; | ||
private final OpenshiftAiRestApi client; | ||
|
||
public OpenshiftAiChatModel(Builder config) { | ||
QuarkusRestClientBuilder builder = QuarkusRestClientBuilder.newBuilder() | ||
.baseUri(config.url) | ||
.connectTimeout(config.timeout.toSeconds(), TimeUnit.SECONDS) | ||
.readTimeout(config.timeout.toSeconds(), TimeUnit.SECONDS); | ||
|
||
if (config.logRequests || config.logResponses) { | ||
builder.loggingScope(LoggingScope.REQUEST_RESPONSE); | ||
builder.clientLogger(new OpenshiftAiRestApi.OpenshiftAiClientLogger(config.logRequests, | ||
config.logResponses)); | ||
} | ||
|
||
this.client = builder.build(OpenshiftAiRestApi.class); | ||
this.modelId = config.modelId; | ||
} | ||
|
||
public static Builder builder() { | ||
return new Builder(); | ||
} | ||
|
||
@Override | ||
public Response<AiMessage> generate(List<ChatMessage> messages) { | ||
|
||
TextGenerationRequest request = new TextGenerationRequest(modelId, messages.get(0).text()); | ||
|
||
TextGenerationResponse textGenerationResponse = client.chat(request); | ||
|
||
return Response.from(AiMessage.from(textGenerationResponse.generatedText())); | ||
} | ||
|
||
@Override | ||
public Response<AiMessage> generate(List<ChatMessage> messages, List<ToolSpecification> toolSpecifications) { | ||
throw new IllegalArgumentException("Tools are currently not supported for OpenShift AI models"); | ||
} | ||
|
||
@Override | ||
public Response<AiMessage> generate(List<ChatMessage> messages, ToolSpecification toolSpecification) { | ||
throw new IllegalArgumentException("Tools are currently not supported for OpenShift AI models"); | ||
} | ||
|
||
public static final class Builder { | ||
|
||
private String modelId; | ||
private Duration timeout = Duration.ofSeconds(15); | ||
|
||
private URI url; | ||
public boolean logResponses; | ||
public boolean logRequests; | ||
|
||
public Builder modelId(String modelId) { | ||
this.modelId = modelId; | ||
return this; | ||
} | ||
|
||
public Builder url(URL url) { | ||
try { | ||
this.url = url.toURI(); | ||
} catch (URISyntaxException e) { | ||
throw new RuntimeException(e); | ||
} | ||
return this; | ||
} | ||
|
||
public Builder timeout(Duration timeout) { | ||
this.timeout = timeout; | ||
return this; | ||
} | ||
|
||
public OpenshiftAiChatModel build() { | ||
return new OpenshiftAiChatModel(this); | ||
} | ||
|
||
public Builder logRequests(boolean logRequests) { | ||
this.logRequests = logRequests; | ||
return this; | ||
} | ||
|
||
public Builder logResponses(boolean logResponses) { | ||
this.logResponses = logResponses; | ||
return this; | ||
} | ||
} | ||
} |
Oops, something went wrong.