Skip to content

Commit

Permalink
feat: Available Ollama models support for
Browse files Browse the repository at this point in the history
quarkus.langchain4j.ollama.chat-model.model-id property value

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Sep 11, 2024
1 parent bad3f44 commit fe7d331
Show file tree
Hide file tree
Showing 12 changed files with 787 additions and 311 deletions.
616 changes: 308 additions & 308 deletions quarkus.ls.ext/com.redhat.quarkus.ls/mvnw
100755 → 100644

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions quarkus.ls.ext/com.redhat.quarkus.ls/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
<dev.build.timestamp>${maven.build.timestamp}</dev.build.timestamp>
<lsp4j.version>0.14.0</lsp4j.version>
<microprofile.ls.version>0.8.0</microprofile.ls.version>
<microprofile.ls.version>0.12.0-SNAPSHOT</microprofile.ls.version>
<jboss.releases.repo.id>jboss-releases-repository</jboss.releases.repo.id>
<jboss.releases.repo.url>https://repository.jboss.org/nexus/content/repositories/releases/</jboss.releases.repo.url>
<jboss.snapshots.repo.id>jboss-snapshots-repository</jboss.snapshots.repo.id>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.quarkus.extensions.ollama;

/**
* Quarkus Ollama constants.
*/
public class OllamaConstants {

public static final String QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY = "quarkus.langchain4j.ollama.chat-model.model-id";

public static final String QUARKUS_LANGCHAIN4J_OLLAMA_BASE_URL_KEY = "quarkus.langchain4j.ollama.base-url";

public static final String DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.quarkus.extensions.ollama;

import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4mp.services.properties.extensions.IPropertiesFileExtension;
import org.eclipse.lsp4mp.services.properties.extensions.PropertiesFileExtensionRegistry;

/**
* Ollama extension.
*/
public class OllamaExtension implements IPropertiesFileExtension {

private OllamaPropertyValidatorParticipant ollamaPropertyValidatorParticipant = new OllamaPropertyValidatorParticipant();

@Override
public void start(InitializeParams params, PropertiesFileExtensionRegistry registry) {
registry.registerPropertyValidatorParticipant(ollamaPropertyValidatorParticipant);

}

@Override
public void stop(PropertiesFileExtensionRegistry registry) {
registry.unregisterPropertyValidatorParticipant(ollamaPropertyValidatorParticipant);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.quarkus.extensions.ollama;

import static com.redhat.quarkus.extensions.ollama.OllamaConstants.DEFAULT_OLLAMA_BASE_URL;
import static com.redhat.quarkus.extensions.ollama.OllamaConstants.QUARKUS_LANGCHAIN4J_OLLAMA_BASE_URL_KEY;
import static com.redhat.quarkus.extensions.ollama.OllamaConstants.QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.lsp4mp.commons.metadata.ItemHint;
import org.eclipse.lsp4mp.commons.metadata.ItemMetadata;
import org.eclipse.lsp4mp.commons.metadata.ValueHint;
import org.eclipse.lsp4mp.commons.utils.StringUtils;
import org.eclipse.lsp4mp.extensions.ExtendedMicroProfileProjectInfo;
import org.eclipse.lsp4mp.extensions.ItemMetadataProvider;
import org.eclipse.lsp4mp.model.Node;
import org.eclipse.lsp4mp.model.Node.NodeType;
import org.eclipse.lsp4mp.model.PropertiesModel;
import org.eclipse.lsp4mp.model.Property;

import com.redhat.quarkus.extensions.ollama.client.OllamaClient;

/**
* Properties provider to collect available Ollama model values for the property
* 'quarkus.langchain4j.ollama.chat-model.model-id'.
*
* The Ollama models are collected by using Ollama Search Api by using the
* following base url:
*
* <ul>
* <li>defined with 'quarkus.langchain4j.ollama.base-url' property.
* <li>otherwise with 'http://localhost:11434'</li>
* </ul>
*/
public class OllamaItemMetadataProvider implements ItemMetadataProvider {

private ExtendedMicroProfileProjectInfo projectInfo;
private OllamaClient ollamaClient;

public OllamaItemMetadataProvider(ExtendedMicroProfileProjectInfo projectInfo) {
this.projectInfo = projectInfo;
// the Ollama models are collected only if
// 'quarkus.langchain4j.ollama.chat-model.model-id' property exists.
boolean available = this.projectInfo.getProperties().stream()
.anyMatch(p -> QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY.equals(p.getName()));
if (available) {
ItemHint hint = new ItemHint();
hint.setName(QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY);
hint.setValues(Collections.emptyList());
projectInfo.getHints().add(hint);
this.ollamaClient = new OllamaClient();
}
}

@Override
public boolean isAvailable() {
return ollamaClient != null;
}

@Override
public void update(PropertiesModel document) {
// Called when application.properties file is opened or updated (when user type
// something in the file).
boolean hasModelProperty = getProperty(document, QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY) != null;
ItemHint hint = projectInfo.getHint(QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY);
if (hasModelProperty && hint != null) {
// The application.properties declare the
// 'quarkus.langchain4j.ollama.chat-model.model-id' property,
// we need to collect available Ollama models by using Ollama Search Api
String baseUrl = getSearchBaseUrl(document);
if (ollamaClient.update(baseUrl) || ollamaClient.needToRefreshModels()) {
// The current search url is different with the new, collect Ollama models.
// Update the available models values for the property
// 'quarkus.langchain4j.ollama.chat-model.model-id'
hint.setValues(ollamaClient.getModels() //
.stream() //
.map(m -> {
ValueHint model = new ValueHint();
String modelId = m.getName();
if (modelId.endsWith(":latest")) {
modelId = modelId.substring(0, modelId.length() - 7);
}
model.setValue(modelId);
return model;
}) //
.collect(Collectors.toList()));
}
}
}

@Override
public List<ItemMetadata> getProperties() {
// This provider doesn't contribute to add/remove properties
return null;
}

private static Property getProperty(PropertiesModel document, String propertyName) {
for (Node node : document.getChildren()) {
if (node.getNodeType() == NodeType.PROPERTY) {
Property property = (Property) node;
if (propertyName.equals(property.getPropertyName())) {
return property;
}
}
}
return null;
}

private static String getSearchBaseUrl(PropertiesModel document) {
Property baseUrlProperty = getProperty(document, QUARKUS_LANGCHAIN4J_OLLAMA_BASE_URL_KEY);
if (baseUrlProperty != null) {
String propertyValue = baseUrlProperty.getPropertyValue();
if (StringUtils.hasText(propertyValue)) {
return propertyValue;
}
}
return DEFAULT_OLLAMA_BASE_URL;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.quarkus.extensions.ollama;

import org.eclipse.lsp4mp.extensions.ExtendedMicroProfileProjectInfo;
import org.eclipse.lsp4mp.extensions.ItemMetadataProvider;
import org.eclipse.lsp4mp.extensions.ItemMetadataProviderFactory;

/**
* Factory for creating {@link ItemMetadataProvider} instance to collect
* available Ollama models.
*
* @author Angelo ZERR
*
*/
public class OllamaItemMetadataProviderFactory implements ItemMetadataProviderFactory {

@Override
public ItemMetadataProvider create(ExtendedMicroProfileProjectInfo projectInfo) {
return new OllamaItemMetadataProvider(projectInfo);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.quarkus.extensions.ollama;

import static com.redhat.quarkus.extensions.ollama.OllamaConstants.QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY;

import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.eclipse.lsp4mp.services.properties.ValidationValueContext;
import org.eclipse.lsp4mp.services.properties.extensions.participants.IPropertyValidatorParticipant;

/**
* Custom validation for 'quarkus.langchain4j.ollama.chat-model.model-id'.
*/
public class OllamaPropertyValidatorParticipant implements IPropertyValidatorParticipant {

@Override
public boolean validatePropertyValue(ValidationValueContext context, CancelChecker cancelChecker) {
if (QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY.equals(context.getPropertyName())) {
// No validation for Ollama model.
return true;
}
return false;
}
}
Loading

0 comments on commit fe7d331

Please sign in to comment.