Skip to content

Commit

Permalink
#29281: returning available models as object that includes 'name' an…
Browse files Browse the repository at this point in the history
…d 'type' instead of just a list os strings
  • Loading branch information
victoralfaro-dotcms committed Aug 14, 2024
1 parent 003b2bb commit 8d6d344
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 17 deletions.
20 changes: 13 additions & 7 deletions dotCMS/src/main/java/com/dotcms/ai/app/AIModels.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.dotcms.ai.model.OpenAIModel;
import com.dotcms.ai.model.OpenAIModels;
import com.dotcms.ai.model.SimpleModel;
import com.dotcms.http.CircuitBreakerUrl;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.Logger;
Expand All @@ -15,7 +16,7 @@
import org.apache.commons.collections4.CollectionUtils;

import java.time.Duration;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
Expand Down Expand Up @@ -177,18 +178,23 @@ public List<String> getOrPullSupportedModels() {
*
* @return a list of available model names
*/
public List<String> getAvailableModels() {
final Set<String> configured = internalModels.entrySet().stream().flatMap(entry -> entry.getValue().stream())
public List<SimpleModel> getAvailableModels() {
final Set<SimpleModel> configured = internalModels.entrySet()
.stream()
.flatMap(entry -> entry.getValue().stream())
.map(Tuple2::_2)
.flatMap(model -> model.getNames().stream())
.flatMap(model -> model.getNames().stream().map(name -> new SimpleModel(name, model.getType())))
.collect(Collectors.toSet());
final Set<SimpleModel> supported = getOrPullSupportedModels()
.stream()
.map(SimpleModel::new)
.collect(Collectors.toSet());
final Set<String> supported = new HashSet<>(getOrPullSupportedModels());
configured.retainAll(supported);
return configured.stream().sorted().collect(Collectors.toList());

return new ArrayList<>(configured);
}

private static CircuitBreakerUrl.Response<OpenAIModels> fetchOpenAIModels(final AppConfig appConfig) {

final CircuitBreakerUrl.Response<OpenAIModels> response = CircuitBreakerUrl.builder()
.setMethod(CircuitBreakerUrl.Method.GET)
.setUrl(OPEN_AI_MODELS_URL)
Expand Down
8 changes: 7 additions & 1 deletion dotCMS/src/main/java/com/dotcms/ai/app/AppConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* The AppConfig class provides a configuration for the AI application.
Expand Down Expand Up @@ -294,8 +295,13 @@ public static void debugLogger(final Class<?> clazz, final Supplier<String> mess
}
}

/**
* Checks if the configuration is enabled.
*
* @return true if the configuration is enabled, false otherwise
*/
public boolean isEnabled() {
return StringUtils.isNotBlank(apiKey);
return Stream.of(apiUrl, apiImageUrl, apiEmbeddingsUrl, apiKey).allMatch(StringUtils::isNotBlank);
}

}
8 changes: 5 additions & 3 deletions dotCMS/src/main/java/com/dotcms/ai/app/AppKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ public enum AppKeys {
IMAGE_MODEL_TOKENS_PER_MINUTE("imageModelTokensPerMinute", "0"),
IMAGE_MODEL_API_PER_MINUTE("imageModelApiPerMinute", "50"),
IMAGE_MODEL_MAX_TOKENS("imageModelMaxTokens", "0"),
IMAGE_MODEL_COMPLETION("imageModelCompletion", "false"),
IMAGE_MODEL_COMPLETION("imageModelCompletion", AppKeys.FALSE),
EMBEDDINGS_MODEL_NAMES("embeddingsModelNames", null),
EMBEDDINGS_MODEL_TOKENS_PER_MINUTE("embeddingsModelTokensPerMinute", "1000000"),
EMBEDDINGS_MODEL_API_PER_MINUTE("embeddingsModelApiPerMinute", "3000"),
EMBEDDINGS_MODEL_MAX_TOKENS("embeddingsModelMaxTokens", "8191"),
EMBEDDINGS_MODEL_COMPLETION("embeddingsModelCompletion", "false"),
EMBEDDINGS_MODEL_COMPLETION("embeddingsModelCompletion", AppKeys.FALSE),
EMBEDDINGS_SPLIT_AT_TOKENS("com.dotcms.ai.embeddings.split.at.tokens", "512"),
EMBEDDINGS_MINIMUM_TEXT_LENGTH_TO_INDEX("com.dotcms.ai.embeddings.minimum.text.length", "64"),
EMBEDDINGS_MINIMUM_FILE_SIZE_TO_INDEX("com.dotcms.ai.embeddings.minimum.file.size", "1024"),
Expand All @@ -39,7 +39,7 @@ public enum AppKeys {
EMBEDDINGS_CACHE_TTL_SECONDS("com.dotcms.ai.embeddings.cache.ttl.seconds", "600"),
EMBEDDINGS_CACHE_SIZE("com.dotcms.ai.embeddings.cache.size", "1000"),
EMBEDDINGS_DB_DELETE_OLD_ON_UPDATE("com.dotcms.ai.embeddings.delete.old.on.update", "true"),
DEBUG_LOGGING("com.dotcms.ai.debug.logging", "false"),
DEBUG_LOGGING("com.dotcms.ai.debug.logging", AppKeys.FALSE),
COMPLETION_TEMPERATURE("com.dotcms.ai.completion.default.temperature", "1"),
COMPLETION_ROLE_PROMPT(
"com.dotcms.ai.completion.role.prompt",
Expand All @@ -52,6 +52,8 @@ public enum AppKeys {
AI_MODELS_CACHE_TTL("com.dotcms.ai.models.supported.ttl", "28800"),
AI_MODELS_CACHE_SIZE("com.dotcms.ai.models.supported.size", "64");

private static final String FALSE = "false";

public static final String APP_KEY = "dotAI";

public final String key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private AppConfig getAppConfig(final String hostId) {

final AppConfig appConfig = ConfigService.INSTANCE.config(host);
if (!appConfig.isEnabled()) {
throw new DotRuntimeException("No API key found in app config");
throw new DotRuntimeException("No API urls or API key found in app config");
}

return appConfig;
Expand Down
53 changes: 53 additions & 0 deletions dotCMS/src/main/java/com/dotcms/ai/model/SimpleModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.dotcms.ai.model;

import com.dotcms.ai.app.AIModelType;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.io.Serializable;
import java.util.Objects;

/**
* Represents a simple model with a name and type.
* This class is immutable and uses Jackson annotations for JSON serialization and deserialization.
*
* @author vico
*/
public class SimpleModel implements Serializable {

private final String name;
private final AIModelType type;

@JsonCreator
public SimpleModel(@JsonProperty("name") final String name, @JsonProperty("type") final AIModelType type) {
this.name = name;
this.type = type;
}

@JsonCreator
public SimpleModel(@JsonProperty("name") final String name) {
this(name, null);
}

public String getName() {
return name;
}

public AIModelType getType() {
return type;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SimpleModel that = (SimpleModel) o;
return Objects.equals(name, that.name);
}

@Override
public int hashCode() {
return Objects.hashCode(name);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.dotcms.ai.app.AppConfig;
import com.dotcms.ai.app.AppKeys;
import com.dotcms.ai.app.ConfigService;
import com.dotcms.ai.model.SimpleModel;
import com.dotcms.ai.rest.forms.CompletionsForm;
import com.dotcms.ai.util.LineReadingOutputStream;
import com.dotcms.rest.WebResource;
Expand Down Expand Up @@ -118,7 +119,7 @@ public final Response getConfig(@Context final HttpServletRequest request,
final String apiKey = UtilMethods.isSet(app.getApiKey()) ? "*****" : "NOT SET";
map.put(AppKeys.API_KEY.key, apiKey);

final List<String> models = AIModels.get().getAvailableModels();
final List<SimpleModel> models = AIModels.get().getAvailableModels();
map.put(AiKeys.AVAILABLE_MODELS, models);

return Response.ok(map).build();
Expand Down
3 changes: 1 addition & 2 deletions dotCMS/src/main/java/com/dotcms/ai/util/OpenAIRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ public static void doRequest(final String urlIn,
final OutputStream out) {

if (!appConfig.isEnabled()) {
Logger.debug(OpenAIRequest.class, "OpenAI is not enabled and will not send request.");
return;
throw new DotRuntimeException("OpenAI is not enabled and will not send request.");
}

final AIModel model = appConfig.resolveModelOrThrow(json.optString(AiKeys.MODEL));
Expand Down
7 changes: 5 additions & 2 deletions dotCMS/src/main/webapp/html/portlet/ext/dotai/dotai.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,13 @@ const writeModelToDropdown = async () => {
}

for (i = 0; i < dotAiState.config.availableModels.length; i++) {
if (dotAiState.config.availableModels[i].type !== 'TEXT') {
continue;
}

const newOption = document.createElement("option");
newOption.value = dotAiState.config.availableModels[i];
newOption.text = `${dotAiState.config.availableModels[i]}`
newOption.value = dotAiState.config.availableModels[i].name;
newOption.text = `${dotAiState.config.availableModels[i].name}`
if (dotAiState.config.availableModels[i] === dotAiState.config.model) {
newOption.selected = true;
newOption.text = `${dotAiState.config.availableModels[i]} (default)`
Expand Down

0 comments on commit 8d6d344

Please sign in to comment.