fi.evolver.ai.vaadin.component.form.ChatPromptForm Maven / Gradle / Ivy
package fi.evolver.ai.vaadin.component.form;
import java.io.Serial;
import java.util.*;
import org.vaadin.lineawesome.LineAwesomeIcon;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.details.Details;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.theme.lumo.LumoUtility;
import fi.evolver.ai.spring.chat.function.FunctionSpec;
import fi.evolver.ai.spring.chat.prompt.ChatPrompt;
import fi.evolver.ai.vaadin.entity.HasValueGetterSetter;
import fi.evolver.utils.string.StringUtils;
public class ChatPromptForm extends VerticalLayout implements HasValueGetterSetter {
@Serial
private static final long serialVersionUID = 1L;
private final TextField modelInput = new TextField();
private final PromptMessagesForm messagesForm = new PromptMessagesForm();
private final KeyValueMapForm parametersForm = new KeyValueMapForm();
private final VerticalLayout functionCallsContent = new VerticalLayout();
private final List functionCallInputs = new ArrayList<>();
private List stopList = new ArrayList<>();
private Map logitBias = new HashMap<>();
private ChatPrompt value;
public ChatPromptForm() {
setWidthFull();
addFields();
}
@Override
public void setValue(ChatPrompt prompt) {
value = prompt;
modelInput.setValue(prompt.model().name());
messagesForm.setValue(prompt.messages());
parametersForm.setValue(prompt.parameters());
setFunctionInputsValue(prompt.functions(), prompt.requiredFunction());
stopList = prompt.stopList();
logitBias = prompt.logitBias();
}
@Override
public ChatPrompt getValue() {
if (value == null)
return null;
ChatPrompt.Builder result = ChatPrompt.builder(value.model().withName(modelInput.getValue()));
if (messagesForm != null)
result.addAll(messagesForm.getValue());
if (parametersForm != null)
for (Map.Entry param : parametersForm.getValue().entrySet())
if (StringUtils.hasText(param.getKey()))
result.setParameter(param.getKey(), param.getValue());
for (FunctionCallInput functionCallInput : functionCallInputs)
result.add(functionCallInput.getFunction(), functionCallInput.getIsRequired());
result.addStopList(stopList);
result.addLogitBias(logitBias);
return result.build();
}
private void addFields() {
modelInput.setLabel(getTranslation("component.form.chatPrompt.model"));
modelInput.setWidthFull();
add(modelInput);
Details messageDetails = new Details(getTranslation("component.form.chatPrompt.messages"), messagesForm);
messageDetails.setWidthFull();
add(messageDetails);
Details parametersDetails = new Details(getTranslation("component.form.chatPrompt.parameters"), parametersForm);
parametersDetails.setWidthFull();
add(parametersDetails);
Details functionCallDetails = new Details(getTranslation("component.form.chatPrompt.functions"), functionCallsContent);
functionCallDetails.setWidthFull();
functionCallsContent.setWidthFull();
add(functionCallDetails);
}
private void setFunctionInputsValue(List> functions, Optional> requiredFunction) {
functionCallsContent.removeAll();
if (functions.size() == 0) {
functionCallsContent.add(new Paragraph(getTranslation("component.form.chatPrompt.functions.none")));
return;
}
for (FunctionSpec function : functions) {
FunctionCallInput FunctionCallInput = new FunctionCallInput(function, requiredFunction.filter(function::equals).isPresent());
functionCallInputs.add(FunctionCallInput);
functionCallsContent.add(FunctionCallInput);
FunctionCallInput.addRemoveHandler(() -> {
functionCallInputs.remove(FunctionCallInput);
functionCallsContent.remove(FunctionCallInput);
});
}
}
private static class FunctionCallInput extends HorizontalLayout {
private final Span functionName = new Span();
private final Checkbox isRequired = new Checkbox();
private final FunctionSpec functionSpec;
private Runnable onRemove;
public FunctionCallInput(FunctionSpec func, boolean required) {
functionSpec = func;
setWidthFull();
addClassName(LumoUtility.AlignItems.CENTER);
functionName.setWidth("65%");
functionName.setText(func.getFunctionName());
add(functionName);
Div div = new Div();
div.setWidth("35%");
div.addClassNames(LumoUtility.Display.FLEX, LumoUtility.JustifyContent.BETWEEN, LumoUtility.AlignItems.CENTER);
add(div);
isRequired.setLabel(getTranslation("component.form.chatPrompt.functions.isRequired"));
isRequired.setValue(required);
div.add(isRequired);
Button removeBtn = new Button(LineAwesomeIcon.TRASH_ALT.create());
removeBtn.addClickListener(e -> {
if (onRemove != null)
onRemove.run();
});
div.add(removeBtn);
}
public void addRemoveHandler(Runnable onRemove) {
this.onRemove = onRemove;
}
public FunctionSpec getFunction() {
return functionSpec;
}
public boolean getIsRequired() {
return isRequired.getValue();
}
}
}