Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New PromptBuilder returning list of messages #326

Merged
merged 4 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import com.xebia.functional.xef.auto.PromptConfiguration
import com.xebia.functional.xef.llm.models.chat.*
import com.xebia.functional.xef.llm.models.functions.CFunction
import com.xebia.functional.xef.prompt.Prompt
import com.xebia.functional.xef.prompt.buildPrompt
import com.xebia.functional.xef.prompt.templates.assistant
import com.xebia.functional.xef.prompt.templates.user
import com.xebia.functional.xef.vectorstores.Memory
import io.ktor.util.date.*
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -83,6 +86,15 @@ interface Chat : LLM {
promptConfiguration: PromptConfiguration = PromptConfiguration.DEFAULTS
): List<String> = promptMessages(Prompt(question), scope, functions, promptConfiguration)

@AiDsl
suspend fun promptMessage(
prompt: Prompt,
scope: Conversation,
promptConfiguration: PromptConfiguration = PromptConfiguration.DEFAULTS
): String =
promptMessages(prompt, scope, emptyList(), promptConfiguration).firstOrNull()
?: throw AIError.NoResponse()

@AiDsl
suspend fun promptMessages(
prompt: Prompt,
Expand Down Expand Up @@ -160,7 +172,7 @@ interface Chat : LLM {

suspend fun String.toMessages(): List<Message> = Prompt(this).toMessages()

suspend fun Prompt.toMessages(): List<Message> = listOf(Message.userMessage { message })
suspend fun Prompt.toMessages(): List<Message> = buildPrompt { +user(message) }

private suspend fun addMemoriesAfterStream(
request: ChatCompletionRequest,
Expand Down Expand Up @@ -332,7 +344,7 @@ interface Chat : LLM {

val ctxTruncated: String = modelType.encoding.truncateText(ctx, maxContextTokens)

listOf(Message.assistantMessage { ctxTruncated })
buildPrompt { +assistant(ctxTruncated) }
} else {
emptyList()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package com.xebia.functional.xef.llm.models.chat

import kotlin.jvm.JvmStatic

data class Message(val role: Role, val content: String, val name: String) {
companion object {
suspend fun systemMessage(message: suspend () -> String) =
Message(role = Role.SYSTEM, content = message(), name = Role.SYSTEM.name)

suspend fun userMessage(message: suspend () -> String) =
Message(role = Role.USER, content = message(), name = Role.USER.name)

suspend fun assistantMessage(message: suspend () -> String) =
Message(role = Role.ASSISTANT, content = message(), name = Role.ASSISTANT.name)
@JvmStatic
fun apply(role: Role, content: String, name: String): Message = Message(role, content, name)
}
}

This file was deleted.

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

import com.xebia.functional.xef.llm.models.chat.Message
import com.xebia.functional.xef.llm.models.chat.Role

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

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

operator fun List<Message>.unaryPlus() {
items.addAll(this)
}

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

fun build(): List<Message> = preprocess(items)
}

fun String.message(role: Role): Message = Message(role, this, role.name)

fun buildPrompt(block: PromptBuilder.() -> Unit): List<Message> =
PromptBuilder().apply { block() }.build()
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.xebia.functional.xef.prompt.evaluator
import com.xebia.functional.xef.auto.Conversation
import com.xebia.functional.xef.auto.PromptConfiguration
import com.xebia.functional.xef.llm.Chat
import com.xebia.functional.xef.llm.models.chat.Message
import com.xebia.functional.xef.prompt.buildPrompt
import com.xebia.functional.xef.prompt.templates.system
import com.xebia.functional.xef.prompt.templates.user
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
Expand Down Expand Up @@ -162,12 +164,12 @@ ${scoreConfig.joinToString("\n") { printReturn(it) }}
val result: List<String> =
model.promptMessages(
messages =
listOf(
Message.systemMessage { message },
Message.userMessage { "Set Prompt = $prompt" },
Message.userMessage { "Set Response = $response" },
Message.userMessage { "Evaluate(Prompt, Response)" }
),
buildPrompt {
+system(message)
+user("Set Prompt = $prompt")
+user("Set Response = $response")
+user("Evaluate(Prompt, Response)")
},
scope = conversation,
promptConfiguration = promptConfiguration,
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import com.xebia.functional.xef.auto.Conversation
import com.xebia.functional.xef.auto.PromptConfiguration
import com.xebia.functional.xef.llm.ChatWithFunctions
import com.xebia.functional.xef.llm.models.chat.Message
import com.xebia.functional.xef.prompt.buildPrompt
import com.xebia.functional.xef.prompt.templates.assistant
import com.xebia.functional.xef.prompt.templates.system
import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging

Expand All @@ -19,16 +22,8 @@ class Expression(

private val generationKeys: MutableList<String> = mutableListOf()

suspend fun system(message: suspend () -> String) {
messages.add(Message.systemMessage(message))
}

suspend fun user(message: suspend () -> String) {
messages.add(Message.userMessage(message))
}

suspend fun assistant(message: suspend () -> String) {
messages.add(Message.assistantMessage(message))
fun addMessages(newMessages: List<Message>) {
messages.addAll(newMessages)
}

fun prompt(key: String): String {
Expand All @@ -40,14 +35,12 @@ class Expression(
promptConfiguration: PromptConfiguration = PromptConfiguration.DEFAULTS
): ExpressionResult {
block()
val prelude =
listOf(
Message.systemMessage { "You are an expert in replacing variables in templates" },
)
val instructionMessages =
listOf(
Message.assistantMessage { "I will replace all placeholders in the message" },
)
val prelude = buildPrompt { +system("You are an expert in replacing variables in templates") }

val instructionMessages = buildPrompt {
+assistant("I will replace all placeholders in the message")
}

val values: ReplacedValues =
model.prompt(
messages = prelude + messages + instructionMessages,
Expand Down

This file was deleted.

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

import com.xebia.functional.xef.prompt.Prompt
import com.xebia.functional.xef.llm.models.chat.Message
import com.xebia.functional.xef.llm.models.chat.Role
import com.xebia.functional.xef.prompt.PromptBuilder
import com.xebia.functional.xef.prompt.prompt
import com.xebia.functional.xef.prompt.message

fun youAre(role: String, talkingTo: String): Prompt =
"You are a $role talking with a $talkingTo".prompt()
fun system(context: String): Message = context.message(Role.SYSTEM)

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

fun user(context: String): Message = context.message(Role.USER)

fun youAre(act: String, talkingTo: String, role: Role = Role.ASSISTANT): Message =
"You are a $act talking with a $talkingTo".message(role)

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

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

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

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

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

enum class Delimiter {
ThreeBackticks,
Expand Down
Loading