-
Notifications
You must be signed in to change notification settings - Fork 467
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
735fd7a
commit 4137367
Showing
15 changed files
with
242 additions
and
29 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
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
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
5 changes: 3 additions & 2 deletions
5
dotCMS/src/main/java/com/dotcms/ai/client/AIDefaultStrategy.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 |
---|---|---|
@@ -1,17 +1,18 @@ | ||
package com.dotcms.ai.client; | ||
|
||
import com.dotcms.ai.domain.AIRequest; | ||
import io.vavr.Tuple2; | ||
|
||
import java.io.OutputStream; | ||
import java.io.Serializable; | ||
|
||
public class AIDefaultStrategy implements AIClientStrategy { | ||
|
||
@Override | ||
public void applyStrategy(final AIClient client, | ||
public void applyStrategy(final Tuple2<AIClient, AIResponseValidator> clientAndParser, | ||
final AIRequest<? extends Serializable> request, | ||
final OutputStream output) { | ||
client.sendRequest(request, output); | ||
clientAndParser._1.sendRequest(request, output); | ||
} | ||
|
||
} |
77 changes: 75 additions & 2 deletions
77
dotCMS/src/main/java/com/dotcms/ai/client/AIModelFallbackStrategy.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 |
---|---|---|
@@ -1,16 +1,89 @@ | ||
package com.dotcms.ai.client; | ||
|
||
import com.dotcms.ai.AiKeys; | ||
import com.dotcms.ai.app.AIModel; | ||
import com.dotcms.ai.domain.AIRequest; | ||
import com.dotcms.ai.domain.AIResponseMetadata; | ||
import com.dotcms.ai.domain.JSONObjectAIRequest; | ||
import com.dotcms.ai.domain.Model; | ||
import com.dotmarketing.exception.DotRuntimeException; | ||
import com.dotmarketing.util.Logger; | ||
import com.dotmarketing.util.json.JSONObject; | ||
import io.vavr.Tuple2; | ||
import org.apache.commons.io.IOUtils; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.io.Serializable; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public class AIModelFallbackStrategy implements AIClientStrategy { | ||
|
||
@Override | ||
public void applyStrategy(final AIClient client, | ||
public void applyStrategy(final Tuple2<AIClient, AIResponseValidator> clientAndParser, | ||
final AIRequest<? extends Serializable> request, | ||
final OutputStream output) { | ||
final OutputStream originalOutput) { | ||
final JSONObject payload = ((JSONObjectAIRequest) request).getPayload(); | ||
final String modelInPayload = payload.optString(AiKeys.MODEL); | ||
final AIModel aiModel = request.getConfig().resolveModelOrThrow(modelInPayload); | ||
|
||
final List<Model> activeModels = aiModel.getActiveModels(); | ||
if (activeModels.isEmpty()) { | ||
Logger.debug( | ||
this, | ||
() -> String.format( | ||
"There are no active models left in model fallback strategy [%s]", | ||
aiModel.getModels().stream().map(Model::getName).collect(Collectors.joining(", ")))); | ||
return; | ||
} | ||
|
||
boolean success = false; | ||
for (int index = 0; index < aiModel.getModels().size(); index++) { | ||
final Model model = aiModel.getModels().get(index); | ||
if (!model.isOperational()) { | ||
Logger.debug("Model [%s] is not operational. Skipping.", model.getName()); | ||
continue; | ||
} | ||
|
||
final ByteArrayOutputStream output = new ByteArrayOutputStream(); | ||
final AIResponseMetadata metadata = clientAndParser._1.sendRequest(request, output); | ||
final String response = output.toString(); | ||
|
||
clientAndParser._2.lookForError(response, metadata); | ||
if (metadata.isSuccess()) { | ||
try { | ||
IOUtils.copy(new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8)), originalOutput); | ||
} catch (IOException e) { | ||
throw new DotRuntimeException(e); | ||
} | ||
|
||
aiModel.setCurrentModelIndex(index); | ||
success = true; | ||
|
||
break; | ||
} | ||
|
||
Logger.debug( | ||
this, | ||
() -> String.format( | ||
"Model [%s] failed with response [%s%s%s]. Trying next model.", | ||
model.getName(), | ||
System.lineSeparator(), | ||
response, | ||
System.lineSeparator())); | ||
model.setStatus(metadata.getStatus()); | ||
Logger.debug( | ||
this, | ||
() -> String.format( | ||
"Model [%s] status updated to [%s].", | ||
model.getName(), | ||
response)); | ||
} | ||
|
||
} | ||
|
||
} |
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
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
9 changes: 9 additions & 0 deletions
9
dotCMS/src/main/java/com/dotcms/ai/client/AIResponseValidator.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,9 @@ | ||
package com.dotcms.ai.client; | ||
|
||
import com.dotcms.ai.domain.AIResponseMetadata; | ||
|
||
public interface AIResponseValidator { | ||
|
||
void lookForError(String response, AIResponseMetadata metadata); | ||
|
||
} |
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
41 changes: 41 additions & 0 deletions
41
dotCMS/src/main/java/com/dotcms/ai/client/openai/OpenAIResponseValidator.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,41 @@ | ||
package com.dotcms.ai.client.openai; | ||
|
||
import com.dotcms.ai.AiKeys; | ||
import com.dotcms.ai.client.AIResponseValidator; | ||
import com.dotcms.ai.domain.AIResponseMetadata; | ||
import com.dotcms.ai.domain.ModelStatus; | ||
import com.dotmarketing.util.json.JSONObject; | ||
import io.vavr.Lazy; | ||
|
||
public class OpenAIResponseValidator implements AIResponseValidator { | ||
|
||
private static final Lazy<OpenAIResponseValidator> INSTANCE = Lazy.of(OpenAIResponseValidator::new); | ||
|
||
public static OpenAIResponseValidator get() { | ||
return INSTANCE.get(); | ||
} | ||
|
||
private OpenAIResponseValidator() { | ||
} | ||
|
||
@Override | ||
public void lookForError(final String response, final AIResponseMetadata metadata) { | ||
final JSONObject jsonResponse = new JSONObject(response); | ||
if (jsonResponse.has(AiKeys.ERROR)) { | ||
final String error = jsonResponse.getString(AiKeys.ERROR); | ||
metadata.setError(error); | ||
metadata.setStatus(resolveStatus(error)); | ||
} | ||
} | ||
|
||
private ModelStatus resolveStatus(final String error) { | ||
if (error.contains("has been deprecated")) { | ||
return ModelStatus.DECOMMISSIONED; | ||
} else if (error.contains("does not exist or you do not have access to it")) { | ||
return ModelStatus.INVALID; | ||
} else { | ||
return null; | ||
} | ||
} | ||
|
||
} |
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
Oops, something went wrong.