Skip to content

Commit

Permalink
Prompt builder (#92)
Browse files Browse the repository at this point in the history
Co-authored-by: Raúl Raja Martínez <[email protected]>
Co-authored-by: Javi Pacheco <[email protected]>
  • Loading branch information
3 people authored May 24, 2023
1 parent db95ac4 commit bd7e3bc
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 243 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.xebia.functional.xef.prompt

open class PromptBuilder {
private val items = mutableListOf<Prompt>()

val emptyLine: String = ""

operator fun Prompt.unaryPlus() {
items.add(this)
}

operator fun String.unaryPlus() {
items.add(Prompt(this))
}

open protected fun preprocess(elements: List<Prompt>): List<Prompt> = elements

fun build(): Prompt = buildString { preprocess(items).forEach(this::append) }.let { Prompt(it) }
}

fun buildPrompt(block: PromptBuilder.() -> Unit): Prompt = PromptBuilder().apply { block() }.build()
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
package com.xebia.functional.xef.prompt

import arrow.core.fold
import kotlin.jvm.JvmInline

fun Prompt(examples: List<String>, suffix: String, prefix: String): Prompt =
Prompt(
"""|$prefix
|
|${examples.joinToString(separator = "\n")}
|
|$suffix"""
.trimMargin()
)

@JvmInline value class Prompt(val message: String)

fun String.prompt(): Prompt = Prompt(this)

fun Prompt.prepend(text: String) = Prompt(text + message)

operator fun Prompt.plus(other: Prompt): Prompt = Prompt(message + other.message)

operator fun Prompt.plus(text: String): Prompt = Prompt(message + text)

fun Prompt.append(text: String) = this + text

fun Prompt.format(variables: Map<String, String>): Prompt =
Prompt(variables.fold(message) { acc, (key, value) -> acc.replace("{$key}", value) })

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.xebia.functional.xef.prompt.templates

import com.xebia.functional.xef.prompt.Prompt
import com.xebia.functional.xef.prompt.PromptBuilder
import com.xebia.functional.xef.prompt.prompt

fun youAre(role: String, talkingTo: String): Prompt =
"You are a $role talking with a $talkingTo".prompt()

class StepsBuilder : PromptBuilder() {
override fun preprocess(elements: List<Prompt>): List<Prompt> =
elements.mapIndexed { ix, elt -> Prompt("${ix + 1} - ${elt.message}") }
}

fun steps(inside: PromptBuilder.() -> Unit): Prompt = StepsBuilder().apply { inside() }.build()

fun writeSequenceOf(content: String): Prompt =
"""
Write a sequence of $content in the following format:
Step 1 - ...
Step 2 - ...
...
Step N - ...
"""
.trimIndent()
.prompt()

fun writeListOf(content: String): Prompt =
"""
Write a list of $content in the following format:
1. ...
2. ...
n. ...
"""
.trimIndent()
.prompt()

fun code(code: String, delimiter: Delimiter?, name: String? = null): Prompt =
"""
${name ?: "" }
${delimiter?.start() ?: ""}
$code
${delimiter?.end() ?: ""}
"""
.trimIndent()
.prompt()

enum class Delimiter {
ThreeBackticks,
ThreeQuotes;

fun text(): String =
when (this) {
ThreeBackticks -> "triple backticks"
ThreeQuotes -> "triple quotes"
}

fun start() =
when (this) {
ThreeBackticks -> "```"
ThreeQuotes -> "\"\"\""
}

fun end() =
when (this) {
ThreeBackticks -> "```"
ThreeQuotes -> "\"\"\""
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package com.xebia.functional.xef.prompt

import arrow.core.raise.Raise
import com.xebia.functional.xef.io.DEFAULT
import okio.FileSystem
import okio.Path

/**
* Creates a PromptTemplate based on a Path
* Creates a Prompt based on a Path
*/
fun Raise<InvalidTemplate>.PromptTemplate(
fun Prompt(
path: Path,
fileSystem: FileSystem = FileSystem.DEFAULT
): PromptTemplate =
): Prompt =
fileSystem.read(path) {
PromptTemplate.either(readUtf8()).bind()
Prompt(readUtf8())
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.xebia.functional.xef.prompt

import arrow.core.raise.either
import io.kotest.assertions.arrow.core.shouldBeRight
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe
import okio.Path.Companion.toPath
import okio.fakefilesystem.FakeFileSystem

Expand All @@ -14,11 +13,10 @@ class PromptTemplateSpec : StringSpec({
val example = templates / "example.txt"
write(example) { writeUtf8("My name is {name} and I'm {age} years old") }
}

val variables = mapOf("name" to "Angela", "age" to "18")
val prompt = Prompt("templates/example.txt".toPath(), fileSystem)

either {
val prompt = PromptTemplate("templates/example.txt".toPath(), fileSystem)
prompt.format(variables)
} shouldBeRight Prompt("My name is Angela and I'm 18 years old")
prompt.format(variables) shouldBe Prompt("My name is Angela and I'm 18 years old")
}
})

0 comments on commit bd7e3bc

Please sign in to comment.