ask

inline suspend fun <Answer> ChatModel.ask(prompt: String, system: String? = null, attempts: Int = 2): Answer

Sends prompt as a single user message and returns the answer as an instance of the @Serializable class Answer, for a node that needs a value from the model and not a text.

@Serializable
data class Verdict(
val category: Category,
@Description("One sentence that says why") val reason: String,
val urgent: Boolean = false,
)

node("classify", work = { email -> model.ask<Verdict>("Classify this support email: ${email.body}") }) { email, verdict ->
email.copy(category = verdict.category, urgent = verdict.urgent)
}

The model is told to reply with JSON that matches the schema of Answer, which is built from the class as the input schema of a Tool is: the text of a Description describes a property, and a property is required unless it has a default value or is nullable. This works with every ChatModel, because it only needs the model to follow the instruction.

An answer that cannot be read is sent back to the model with what was wrong, and the model is asked again, until it was asked attempts times. That covers an answer that is not JSON, a property that is missing or has the wrong type, and a require in the init of Answer that fails, so a require is a way to check an answer: its message goes to the model.

In a streamed run, the model's JSON is not reported as progress.

Parameters

prompt

what the model is asked.

system

instructions for the model.

attempts

how often the model is asked at most.

Throws

when a call fails, when the answer was cut off at the model's output limit, or when the model gave no answer that could be read in attempts attempts.

if Answer is not a class or has a property of a type that cannot be described, or attempts is less than 1.


inline suspend fun <Answer> ChatModel.ask(request: ChatRequest, attempts: Int = 2): TypedResponse<Answer>

Returns the model's next message for request as an instance of the @Serializable class Answer, with the message it was read from. Use it to ask for a value at the end of a conversation. See the overload with a prompt for how the model is asked.

val response = model.ask<Verdict>(ChatRequest(ticket.messages + ChatMessage.User("What is your verdict?")))

Throws

when a call fails, when the answer was cut off at the model's output limit, or when the model gave no answer that could be read in attempts attempts.

if Answer is not a class or has a property of a type that cannot be described, request has tools, or attempts is less than 1.


suspend fun <Answer> ChatModel.ask(serializer: KSerializer<Answer>, request: ChatRequest, attempts: Int = 2): TypedResponse<Answer>

Returns the model's next message for request as a value read with serializer. See the overload with a reified type.