-
Notifications
You must be signed in to change notification settings - Fork 16
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
Message Prompts #30
Message Prompts #30
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR looks good @realdavidvega but I had a couple of thoughts to streamline the types a bit more, and make things a bit more functional inspired to maximise reusability.
Looking at this PR I had a few thoughts:
- We could parameterise
PromptTemplate
overA
, and the current implementation would be forString
, and we can implementFunctorK
ormapK
to mapA
to a new type.
interface PromptTemplate<A> {
val inputKeys: List<String>
suspend fun format(variables: Map<String, String>): A
fun <B> mapK(transform: (A) -> B): PromptTemplate<B> = object : PromptTemplate<B> {
override val inputKeys: List<String> = this@PromptTemplate.inputKeys
override suspend fun format(variables: Map<String, String>): B =
transform(this@PromptTemplate.format(variables))
}
companion object {
operator fun invoke(config: Config): PromptTemplate<String> = object : PromptTemplate<String> {
...
}
}
- So the newly defined types would all be
PromptTemplate
but for different types, this would allow us to define more generic code usingPromptTemplate
instead of different types if needed. New smart-constructors defined inPromptTemplate.Companion
.
fun human(promptTemplate: PromptTemplate<String>): PromptTemplate<HumanMessage> =
promptTemplate.mapK(::HumanMessage)
fun ai(promptTemplate: PromptTemplate<String>): PromptTemplate<AIMessage> =
promptTemplate.mapK(::AIMessage)
fun system(promptTemplate: PromptTemplate<String>): PromptTemplate<SystemMessage> =
promptTemplate.mapK(::SystemMessage)
fun chat(promptTemplate: PromptTemplate<String>, role: String): PromptTemplate<ChatMessage> =
promptTemplate.mapK { ChatMessage(it, role) }
nit: we can clean-up Message
model a bit.
enum class Type {
human, ai, system, chat
}
@Serializable
sealed class Message {
abstract val content: String
fun type(): Type =
when (this) {
is HumanMessage -> Type.human
is AIMessage -> Type.ai
is SystemMessage -> Type.system
is ChatMessage -> Type.chat
}
}
data class HumanMessage(override val content: String) : Message()
data class AIMessage(override val content: String) : Message()
data class SystemMessage(override val content: String) : Message()
data class ChatMessage(override val content: String, val role: String) : Message()
I think that's a great idea @nomisRev, and it makes more sense. So our |
Great suggestions, @nomisRev! The code looks really neat |
This is great, thanks @realdavidvega @nomisRev 💯 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, thank you @realdavidvega 🙌
This PR brings
HumanMessagePromptTemplate
,SystemMessagePromptTemplate
,AIMessagePromptTemplate
andChatMessagePromptTemplate
with it's respective tests.Ready to review @nomisRev @Yawolf @juanpedromoreno @franciscodr Thanks!