Enum Choices¶
choice<E>() turns an enum into a Choice question: every constant is an option, and the answer's choice is
the constant itself.
// Any enum works; each constant's name is the option key, sent undescribed.
enum class Language { KOTLIN, JAVA, PYTHON, GO, OTHER }
object CodeLanguage : JevQuery() {
val language by choice<Language>("What programming language is this code written in?")
}
Exhaustive handling¶
Because the answer is an enum constant, a when over it is checked by the compiler:
val language = jev.ask(CodeLanguage, state = snippet)[CodeLanguage.language]
// choice is a Language, so `when` is exhaustive and the compiler checks every case.
val linter =
when (language.choice) {
Language.KOTLIN -> "ktlint"
Language.JAVA -> "checkstyle"
Language.PYTHON -> "ruff"
Language.GO -> "golangci-lint"
Language.OTHER -> null
}
// Probabilities are keyed by constant, in declaration order.
val kotlinOrJava = language.probability(Language.KOTLIN) + language.probability(Language.JAVA)
probabilities is keyed by constant, in declaration order, and ranked(), probability(...) and
topProbability work as they do for string options.
Descriptions¶
Implement JevOption to describe each option. The description is sent with the option key:
enum class Team(
override val description: String,
) : JevOption {
BILLING("Payments, invoicing, refunds"),
TECHNICAL("Bugs, outages, integrations"),
SALES("Pricing, upgrades, new accounts"),
}
Option keys¶
By default, the option key sent to the model, and matched in the answer, is the constant's name. Option names
are part of what the model reads, so they should describe the option. Override optionKey to send something
else:
// optionKey changes the key that is sent to the model (and matched in the answer).
enum class Plan(
override val description: String,
) : JevOption {
FREE("No paid plan"),
PRO("A paid plan for one person"),
ENTERPRISE("A company-wide contract"),
;
override val optionKey: String get() = name.lowercase() // the model sees "free", "pro", "enterprise"
}
Structured descriptions¶
Override entry to send structured JSON, such as a contrastive rubric, instead of a plain description:
// entry replaces the plain description with structured JSON, such as a contrastive rubric.
enum class ReturnTopic(
override val entry: JsonElement,
) : JevOption {
RETURN_POLICY(rubric("Whether and how an item can be returned", notFor = "A return already sent")),
RETURN_STATUS(rubric("Progress of a return already sent", notFor = "Whether an item can be returned")),
}
JevOption at a glance¶
| Member | Default | Purpose |
|---|---|---|
description |
null |
plain-text description of the option |
entry |
description as JSON, or null |
what's sent as the option's description; override for structured JSON |
optionKey |
null, meaning the constant's name |
the key sent to the model and matched in the answer |
Enums don't have to implement JevOption; without it, options are sent undescribed under their constant names.
In the inline DSL¶
choice<E>(id, instructions) works in inline queries too. Read the answer back with enumChoice<E>(id):
// Enum choices work in the inline DSL too; read them back with enumChoice<E>(id).
val result =
jev.query(state = message) {
choice<Plan>("plan", "Which plan is the customer on?")
choice<ReturnTopic>("topic", "Which returns topic is the customer asking about?")
}
val plan: Plan = result.enumChoice<Plan>("plan").choice
val topic: ReturnTopic = result.enumChoice<ReturnTopic>("topic").choice
If the server ever returns an option the enum doesn't define, reading the answer throws a
JevResponseValidationException.