Skip to content

Commit

Permalink
Introduce a retranslation UI (#156)
Browse files Browse the repository at this point in the history
To make experiments with translation rules easier, we turn
/apps/composum-ai/components/autotranslate/list.html into a
retranslation UI usable for content authors. That is, the experimenting
UI that was there is now moved to
/apps/composum-ai/components/autotranslate-experiments/list.html and
this UI is now reduced to operations that would be acceptable on
production as well and is unrestricted. Also, there is a new checkbox
that prints the additional instructions collected into that page for
checking everything works as expected.
  • Loading branch information
stoerr authored Oct 28, 2024
2 parents 76d7132 + c27fe21 commit f7bdb6b
Show file tree
Hide file tree
Showing 33 changed files with 809 additions and 235 deletions.
2 changes: 2 additions & 0 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ https://wcm.io/caconfig/editor/usage.html translation config drop down

!! Empty prompt text
!! http://localhost:5502/editor.html/content/xxx/com/en/about-us/going-forward.html "Explore the world..." RTE
PDF and markdown as possible datatypes for the content creation dialog
https://www.stoerr.net/outgoing/adaptto-speedwalking.txt als URL - Format geht verloren!!!!

The content creation dialog should know about the current text even if the page is the source!!!!

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.composum.ai.aem.core.impl.autotranslate;

import java.time.LocalDateTime;
import java.util.Map;

import javax.annotation.Nonnull;

import org.apache.sling.api.resource.PersistenceException;
Expand All @@ -12,6 +15,8 @@
*/
public interface AutoPageTranslateService {

Map<String, LocalDateTime> getRunningTranslations();

/**
* Implements the actual translation for one page or asset.
*/
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
public @interface AutoTranslateCaConfig {

@Property(label = "Additional Instructions", order = 1,
description = "Additional instructions for the automatic translation.",
property = {
"widgetType=textarea",
"textareaRows=8"
})
description = "Additional instructions for the automatic translation.")
String additionalInstructions();

@Property(label = "Rules for additional Instructions", order = 2,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.composum.ai.aem.core.impl.autotranslate;

import static com.composum.ai.aem.core.impl.autotranslate.AutoPageTranslateServiceImpl.MARKER_DEBUG_ADDITIONAL_INSTRUCTIONS;

import java.util.Collections;
import java.util.List;

import javax.annotation.Nonnull;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.LoginException;
Expand Down Expand Up @@ -41,14 +45,17 @@ public boolean isDisabled() {
|| autoTranslateConfigService == null || !autoTranslateConfigService.isPocUiEnabled();
}

@Nonnull
public List<AutoTranslateService.TranslationRun> getTranslationRuns() {
return autoTranslateService != null ? autoTranslateService.getTranslationRuns() : Collections.emptyList();
}

public boolean inProgress() {
List<AutoTranslateService.TranslationRun> runs = getTranslationRuns();
return runs.stream().filter(run -> run.isInProgress()).findAny().isPresent();
}

public AutoTranslateService.TranslationRun createRun() throws LoginException, PersistenceException {
if (isDisabled()) {
throw new IllegalStateException("AutoTranslateService is not available");
}
if (run == null) {
String path = request.getParameter("path");
if (path == null || path.isEmpty()) {
Expand All @@ -58,7 +65,17 @@ public AutoTranslateService.TranslationRun createRun() throws LoginException, Pe
boolean recursive = request.getParameter("recursive") != null;
boolean changed = request.getParameter("translateWhenChanged") != null;
String additionalInstructions = request.getParameter("additionalInstructions");
boolean debugaddinstructions = request.getParameter("debugaddinstructions") != null;
if (debugaddinstructions) {
additionalInstructions = StringUtils.trim(
StringUtils.defaultString(additionalInstructions) + "\n\n" +
MARKER_DEBUG_ADDITIONAL_INSTRUCTIONS
);
}
boolean breakInheritance = request.getParameter("breakInheritance") != null;
if (isDisabled() && breakInheritance) {
throw new IllegalStateException("Refusing to do breakInheritance on disabled experiments.");
}
AutoTranslateService.TranslationParameters parms = new AutoTranslateService.TranslationParameters();
String translationmodel = request.getParameter("translationmodel");
if ("standard".equals(translationmodel)) {
Expand All @@ -85,7 +102,7 @@ public String rollback() throws WCMException, PersistenceException {
String path = request.getParameter("path");
try {
if (isDisabled()) {
throw new IllegalStateException("AutoTranslateService is not available");
throw new IllegalStateException("Rollback only allowed in experimental mode.");
}
if (path == null || path.isEmpty()) {
throw new IllegalArgumentException("path parameter is required");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,13 @@ public TranslationParameters clone() {
}
}

enum TranslationStatus {
QUEUED, CANCELLING, RUNNING, CANCELLED, DONE_WITH_ERRORS, INTERRUPTED, ERROR, FINISHED;
}

abstract class TranslationRun {
public String id;
public String status;
public TranslationStatus status;
public String startTime;
public String stopTime;
public String user;
Expand All @@ -127,6 +131,15 @@ abstract class TranslationRun {

public abstract void rollback(@Nonnull ResourceResolver resourceResolver) throws PersistenceException, WCMException;

@Nonnull
public String statusString() {
return status != null ? status.name().toLowerCase() : "";
}

public boolean isInProgress() {
return status == TranslationStatus.QUEUED || status == TranslationStatus.RUNNING || status == TranslationStatus.CANCELLING;
}


@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.composum.ai.backend.base.service.GPTException;
import com.day.cq.wcm.api.WCMException;

/**
Expand Down Expand Up @@ -135,7 +136,7 @@ public TranslationRun startTranslation(
.map(r -> new TranslationPageImpl(r.getPath()))
.collect(Collectors.toList());
run.waituntil = System.currentTimeMillis() + 1000; // when triggered during live copy creation.
run.status = "queued";
run.status = TranslationStatus.QUEUED;
run.user = resourceResolver.getUserID();
stateService.getTranslationRuns().add(run);
run.future = getThreadPool().submit(() -> run.execute(processResolver));
Expand Down Expand Up @@ -188,7 +189,7 @@ public List<TranslationPage> getTranslatedPages() {
public void cancel() {
if (future != null) {
future.cancel(true);
status = "cancelling";
status = TranslationStatus.CANCELLING;
}
}

Expand All @@ -207,7 +208,7 @@ public synchronized void rollback(@Nonnull ResourceResolver resourceResolver) th
*/
public void execute(ResourceResolver callResourceResolver) {
try {
status = "running";
status = TranslationStatus.RUNNING;
if (System.currentTimeMillis() < waituntil) {
// delay a little since that is used during creating a livecopy, and that should be finished.
Thread.sleep(waituntil - System.currentTimeMillis());
Expand All @@ -222,7 +223,7 @@ public void execute(ResourceResolver callResourceResolver) {
interrupted = true;
}
if (interrupted) {
status = "cancelled";
status = TranslationStatus.CANCELLED;
page.status = "cancelled";
continue;
}
Expand All @@ -237,26 +238,31 @@ public void execute(ResourceResolver callResourceResolver) {
page.stats = stats;
page.status = stats.hasChanges() ? "done" : "unchanged";
}
} catch (GPTException.GPTUserNotificationException e) {
page.status = "cancelled - user notification";
this.messages.append(e.getMessage());
LOG.info("User notification during translation of " + page.pagePath + ": " + e.getMessage());
hasErrors = true; // not quite true but we don't want an 'OK, translation done'
} catch (Exception e) {
page.status = "error";
this.messages.append("Error translating ").append(page.pagePath).append(": ").append(e).append("\n");
LOG.error("Error translating " + page.pagePath, e);
hasErrors = true;
}
}
status = hasErrors ? "doneWithErrors" : interrupted ? "cancelled" : "done";
status = hasErrors ? TranslationStatus.DONE_WITH_ERRORS : interrupted ? TranslationStatus.CANCELLED : TranslationStatus.FINISHED;
} catch (InterruptedException e) {
LOG.error("Interruption during " + this, e);
Thread.currentThread().interrupt();
status = "interrupted";
status = TranslationStatus.INTERRUPTED;
} catch (Exception e) {
LOG.error("Error during " + this, e);
status = "error";
status = TranslationStatus.ERROR;
messages.append("Error: ").append(e).append("\n");
} finally {
stopTime = new Date().toString();
if (status == null) {
status = "finished";
status = TranslationStatus.FINISHED;
}
future = null;
callResourceResolver.close();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="sling:Folder">
</jcr:root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="sling:Folder"
sling:resourceType="composum-ai/components/autotranslate/list"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<%@ page import="com.composum.ai.aem.core.impl.autotranslate.AutoTranslateListModel" %>
<%@ page import="org.apache.sling.api.SlingHttpServletRequest" %>
<%@page session="false" pageEncoding="UTF-8" %>
<%-- Redirects to page displaying the run --%>
<%
try {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
AutoTranslateListModel model = slingRequest.adaptTo(AutoTranslateListModel.class);
String id = model.createRun().id;
response.sendRedirect("run.html/" + id);
} catch (Exception e) {
%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Error during translation</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body class="coral--light foundation-layout-util-maximized-alt">
<div class="foundation-layout-panel">
<div class="foundation-layout-panel-bodywrapper spectrum-ready">
<div class="foundation-layout-panel-body">
<div class="foundation-layout-panel-content foundation-layout-form foundation-layout-form-mode-edit">
<div class="cq-dialog-content-page">
<p>Error: <%= e.toString() %>
</p>
<pre>
<%
out.flush();
e.printStackTrace(response.getWriter());
%>
</pre>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
<%
}
%>
Loading

0 comments on commit f7bdb6b

Please sign in to comment.