
tri.promptfx.tools.PromptTemplateView.kt Maven / Gradle / Ivy
The newest version!
/*-
* #%L
* tri.promptfx:promptfx
* %%
* Copyright (C) 2023 - 2025 Johns Hopkins University Applied Physics Laboratory
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package tri.promptfx.tools
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView
import javafx.beans.property.SimpleStringProperty
import javafx.geometry.Pos
import javafx.scene.layout.Priority
import tornadofx.*
import tri.ai.pips.aitask
import tri.ai.prompt.AiPrompt
import tri.ai.prompt.trace.*
import tri.promptfx.AiPlanTaskView
import tri.promptfx.PromptFxModels
import tri.util.ui.NavigableWorkspaceViewImpl
import tri.util.ui.templatemenubutton
import tri.util.warning
import java.time.LocalDate
/** Plugin for the [PromptTemplateView]. */
class PromptTemplatePlugin : NavigableWorkspaceViewImpl("Tools", "Prompt Template", type = PromptTemplateView::class)
/** A view designed to help you test prompt templates. */
class PromptTemplateView : AiPlanTaskView("Prompt Template",
"Enter a prompt template and a list of values to fill it in with.") {
val template = SimpleStringProperty("")
private val fields = observableListOf>()
private val fieldMap = mutableMapOf()
init {
template.onChange { updateTemplateInputs(it!!) }
}
init {
input(vgrow = Priority.ALWAYS) {
toolbar {
text("Template:")
spacer()
templatemenubutton(template)
}
textarea(template) {
promptText = "Enter a prompt template, using syntax like {{field}} for fields to fill in."
hgrow = Priority.ALWAYS
prefRowCount = 20
isWrapText = true
prefWidth = 0.0
}
toolbar {
text("Inputs:")
}
listview(fields) {
vgrow = Priority.ALWAYS
cellFormat { field ->
graphic = hbox(10, Pos.TOP_CENTER) {
text(field.first)
val useText = field.second.ifBlank {
if (field.first == "today") LocalDate.now().toString() else ""
}
fieldMap[field.first] = useText
val area = textarea(useText) {
isWrapText = true
hgrow = Priority.ALWAYS
promptText = "Enter value for ${field.first}"
prefRowCount = 0
textProperty().onChange { fieldMap[field.first] = it!! }
}
// add button to toggle expanding the text area
button("", FontAwesomeIconView(FontAwesomeIcon.EXPAND)) {
action {
area.prefRowCount = when (area.prefRowCount) {
0 -> 5
5 -> 10
else -> 0
}
}
}
prefWidth = 0.0
}
}
}
}
addDefaultTextCompletionParameters(common)
}
override fun plan() = aitask("text-completion") {
val resp = AiPrompt(template.value).fill(fieldMap).let {
completionEngine.complete(it, tokens = common.maxTokens.value, temperature = common.temp.value, numResponses = common.numResponses.value)
}
resp.copy(promptInfo = AiPromptInfo(template.value, fieldMap.toMap()))
}.planner
/**
* Loads a prompt trace into the view.
* Will set the prompt, prompt inputs, model, and model parameters associated with the trace.
*/
fun importPromptTrace(prompt: AiPromptTraceSupport<*>) {
val promptInfo = prompt.prompt ?: AiPromptInfo("N/A")
val modelInfo = prompt.model ?: AiModelInfo("N/A")
template.set(promptInfo.prompt)
fields.setAll(promptInfo.promptParams.entries.map { it.key to it.value.toString() })
val model = PromptFxModels.textCompletionModels().find { it.modelId == modelInfo.modelId }
if (model != null) {
controller.completionEngine.set(model)
} else {
warning("Model ${modelInfo.modelId} not found.")
}
common.importModelParams(modelInfo.modelParams)
}
private fun updateTemplateInputs(template: String) {
// extract {{{.}}} and {{.}} delimited fields from new value
val nueFields = AiPrompt.fieldsInTemplate(template)
if (fields.toSet() != nueFields.toSet()) {
val fieldMapCopy = fieldMap.toMap()
fieldMap.clear()
fields.setAll(nueFields.map { it to (fieldMapCopy[it] ?: "") })
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy