-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Expression Language for LLM driven template replacements (#298)
* Expression Language for LLM driven template replacements * Prompt adjustments * Prompt adjustments and better structure for building final prompt based on messages
- Loading branch information
Showing
15 changed files
with
289 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 12 additions & 1 deletion
13
core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/chat/Message.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
package com.xebia.functional.xef.llm.models.chat | ||
|
||
data class Message(val role: Role, val content: String, val name: String) | ||
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) | ||
} | ||
} |
100 changes: 100 additions & 0 deletions
100
core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/expressions/Expression.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package com.xebia.functional.xef.prompt.expressions | ||
|
||
import com.xebia.functional.xef.auto.CoreAIScope | ||
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.llm.models.chat.Role | ||
import com.xebia.functional.xef.prompt.experts.ExpertSystem | ||
import io.github.oshai.kotlinlogging.KLogger | ||
import io.github.oshai.kotlinlogging.KotlinLogging | ||
|
||
class Expression( | ||
private val scope: CoreAIScope, | ||
private val model: ChatWithFunctions, | ||
val block: suspend Expression.() -> Unit | ||
) { | ||
|
||
private val logger: KLogger = KotlinLogging.logger {} | ||
|
||
private val messages: MutableList<Message> = mutableListOf() | ||
|
||
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 prompt(key: String): String { | ||
generationKeys.add(key) | ||
return "{{$key}}" | ||
} | ||
|
||
suspend fun run( | ||
promptConfiguration: PromptConfiguration = PromptConfiguration.DEFAULTS | ||
): ExpressionResult { | ||
block() | ||
val instructionMessage = | ||
Message( | ||
role = Role.USER, | ||
content = | ||
ExpertSystem( | ||
system = "You are an expert in replacing variables in templates", | ||
query = | ||
""" | ||
|I want to replace the following variables in the following template: | ||
|<template> | ||
|${messages.joinToString("\n") { it.content }} | ||
|</template> | ||
|The variables are: | ||
|${generationKeys.joinToString("\n") { it }} | ||
""" | ||
.trimMargin(), | ||
instructions = | ||
listOf( | ||
"Create a `ReplacedValues` object with the `replacements` where the keys are the variable names and the values are the values to replace them with.", | ||
) | ||
) | ||
.message, | ||
name = Role.USER.name | ||
) | ||
val values: ReplacedValues = | ||
model.prompt( | ||
messages = messages + instructionMessage, | ||
context = scope.context, | ||
serializer = ReplacedValues.serializer(), | ||
conversationId = scope.conversationId, | ||
promptConfiguration = promptConfiguration | ||
) | ||
logger.info { "replaced: ${values.replacements.joinToString { it.key }}" } | ||
val replacedTemplate = | ||
messages.fold("") { acc, message -> | ||
val replacedMessage = | ||
generationKeys.fold(message.content) { acc, key -> | ||
acc.replace( | ||
"{{$key}}", | ||
values.replacements.firstOrNull { it.key == key }?.value ?: "{{$key}}" | ||
) | ||
} | ||
acc + replacedMessage + "\n" | ||
} | ||
return ExpressionResult(messages = messages, result = replacedTemplate, values = values) | ||
} | ||
|
||
companion object { | ||
suspend fun run( | ||
scope: CoreAIScope, | ||
model: ChatWithFunctions, | ||
block: suspend Expression.() -> Unit | ||
): ExpressionResult = Expression(scope, model, block).run() | ||
|
||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/expressions/ExpressionResult.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.xebia.functional.xef.prompt.expressions | ||
|
||
import com.xebia.functional.xef.llm.models.chat.Message | ||
|
||
data class ExpressionResult( | ||
val messages: List<Message>, | ||
val result: String, | ||
val values: ReplacedValues, | ||
) |
10 changes: 10 additions & 0 deletions
10
core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/expressions/ReplacedValues.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.xebia.functional.xef.prompt.expressions | ||
|
||
import com.xebia.functional.xef.auto.Description | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ReplacedValues( | ||
@Description(["The values that are generated for the template"]) | ||
val replacements: List<Replacement> | ||
) |
12 changes: 12 additions & 0 deletions
12
core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/expressions/Replacement.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.xef.prompt.expressions | ||
|
||
import com.xebia.functional.xef.auto.Description | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Replacement( | ||
@Description(["The key originally in {{key}} format that was going to get replaced"]) | ||
val key: String, | ||
@Description(["The Assistant generated value that the `key` should be replaced with"]) | ||
val value: String | ||
) |
Oops, something went wrong.