-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Available Ollama models support for
quarkus.langchain4j.ollama.chat-model.model-id property value Signed-off-by: azerr <azerr@redhat.com>
- Loading branch information
1 parent
9f4c520
commit fa24e22
Showing
6 changed files
with
285 additions
and
2 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
181 changes: 181 additions & 0 deletions
181
...kus.ls/src/main/java/com/redhat/quarkus/extensions/ollama/OllamaItemMetadataProvider.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,181 @@ | ||
/******************************************************************************* | ||
* 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 java.io.StringReader; | ||
import java.net.URI; | ||
import java.net.http.HttpClient; | ||
import java.net.http.HttpRequest; | ||
import java.net.http.HttpResponse; | ||
import java.net.http.HttpResponse.BodyHandlers; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
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.google.gson.GsonBuilder; | ||
|
||
/** | ||
* 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 static final Logger LOGGER = Logger.getLogger(OllamaItemMetadataProvider.class.getName()); | ||
|
||
private static final String QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY = "quarkus.langchain4j.ollama.chat-model.model-id"; | ||
|
||
private static final String QUARKUS_LANGCHAIN4J_OLLAMA_BASE_URL_KEY = "quarkus.langchain4j.ollama.base-url"; | ||
|
||
private static final String DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434"; | ||
|
||
private ExtendedMicroProfileProjectInfo projectInfo; | ||
private boolean available; | ||
|
||
private String currentSearchUrl; | ||
|
||
public OllamaItemMetadataProvider(ExtendedMicroProfileProjectInfo projectInfo) { | ||
this.projectInfo = projectInfo; | ||
// the Ollama models are collected only if | ||
// 'quarkus.langchain4j.ollama.chat-model.model-id' property exists. | ||
this.available = this.projectInfo.getProperties().stream() | ||
.anyMatch(p -> QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY.equals(p.getName())); | ||
} | ||
|
||
@Override | ||
public boolean isAvailable() { | ||
return available; | ||
} | ||
|
||
@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; | ||
if (hasModelProperty) { | ||
// 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 searchUrl = getOllamaSearchUrl(document); | ||
if (!Objects.equals(searchUrl, currentSearchUrl)) { | ||
// The current search url is different with the new, collect Ollama models. | ||
ItemHint hint = projectInfo.getHint(QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY); | ||
if (hint == null) { | ||
hint = new ItemHint(); | ||
hint.setName(QUARKUS_LANGCHAIN4J_OLLAMA_CHAT_MODEL_MODEL_ID_KEY); | ||
projectInfo.getHints().add(hint); | ||
} | ||
// Update the available models values for the property | ||
// 'quarkus.langchain4j.ollama.chat-model.model-id' | ||
hint.setValues(collectOllamaModels(searchUrl)); | ||
currentSearchUrl = searchUrl; | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public List<ItemMetadata> getProperties() { | ||
// This provider doesn't contribute to add/remove properties | ||
return null; | ||
} | ||
|
||
private static List<ValueHint> collectOllamaModels(String searchUrl) { | ||
try { | ||
// Call Http search Url (ex : http://localhost:11434/v1/models) | ||
HttpRequest request = HttpRequest.newBuilder() // | ||
.uri(new URI(searchUrl)) // | ||
.GET() // | ||
.build(); | ||
|
||
HttpResponse<String> response = HttpClient.newBuilder() // | ||
.build() // | ||
.send(request, BodyHandlers.ofString()); | ||
String result = response.body(); | ||
|
||
// ex : | ||
// {"object":"list","data":[{"id":"qwen2:latest","object":"model","created":1724172988,"owned_by":"library"}]} | ||
OllamaModelsResult r = new GsonBuilder() // | ||
.create()// | ||
.fromJson(new StringReader(result), OllamaModelsResult.class); | ||
if (r != null && r.getData() != null) { | ||
return r.getData() // | ||
.stream() // | ||
.map(m -> { | ||
ValueHint model = new ValueHint(); | ||
String modelId = m.getId(); | ||
if (modelId.endsWith(":latest")) { | ||
modelId = modelId.substring(0, modelId.length() - ":latest".length()); | ||
} | ||
model.setValue(modelId); | ||
return model; | ||
}) // | ||
.collect(Collectors.toList()); | ||
|
||
} | ||
|
||
} catch (Exception e) { | ||
LOGGER.log(Level.SEVERE, "Error while collecting Ollama Models with '" + searchUrl + "'.", e); | ||
} | ||
return Collections.emptyList(); | ||
} | ||
|
||
private static String getOllamaSearchUrl(PropertiesModel document) { | ||
return getSearchBaseUrl(document) + "/v1/models"; | ||
} | ||
|
||
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; | ||
} | ||
|
||
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; | ||
} | ||
|
||
} |
33 changes: 33 additions & 0 deletions
33
...src/main/java/com/redhat/quarkus/extensions/ollama/OllamaItemMetadataProviderFactory.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,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); | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
...com.redhat.quarkus.ls/src/main/java/com/redhat/quarkus/extensions/ollama/OllamaModel.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,31 @@ | ||
/******************************************************************************* | ||
* 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; | ||
|
||
/** | ||
* Ollama model. | ||
*/ | ||
public class OllamaModel { | ||
|
||
private String id; | ||
|
||
public String getId() { | ||
return id; | ||
} | ||
|
||
public void setId(String id) { | ||
this.id = id; | ||
} | ||
|
||
} |
37 changes: 37 additions & 0 deletions
37
...hat.quarkus.ls/src/main/java/com/redhat/quarkus/extensions/ollama/OllamaModelsResult.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,37 @@ | ||
/******************************************************************************* | ||
* 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 java.util.List; | ||
|
||
/** | ||
* Bean class which maps the HTTP response of http://localhost:11434/v1/models | ||
* | ||
* Example: | ||
* <p> | ||
* {"object":"list","data":[{"id":"qwen2:latest","object":"model","created":1724172988,"owned_by":"library"}]} | ||
* </p> | ||
*/ | ||
public class OllamaModelsResult { | ||
|
||
private List<OllamaModel> data; | ||
|
||
public List<OllamaModel> getData() { | ||
return data; | ||
} | ||
|
||
public void setData(List<OllamaModel> data) { | ||
this.data = data; | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...ain/resources/META-INF/services/org.eclipse.lsp4mp.extensions.ItemMetadataProviderFactory
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 @@ | ||
com.redhat.quarkus.extensions.ollama.OllamaItemMetadataProviderFactory |