org.llm4s.schema

Members list

Type members

Classlikes

@Experimental
trait SchemaOf[A]

The JSON schema of A, derived from the type itself so that it cannot drift from it.

The JSON schema of A, derived from the type itself so that it cannot drift from it.

case class Invoice(vendor: String, amount: Double, lines: List[String], note: Option[String]) derives SchemaOf

SchemaOf[Invoice].toJsonSchema()    // the schema `completeStructured` sends

The schema describes what uPickle's derived ReadWriter reads and writes (field names, Option as the value or null, an enum as its case name, a BigDecimal as a string), so a reply that matches the schema reads back into A. The module's tests check that round trip for every supported shape.

Supported: String, Int, Long, Double, Float, Boolean, BigDecimal, BigInt; Option; List, Seq, Vector and Set of a supported type; case classes whose fields are supported; enums and sealed hierarchies of singletons (as a string with the case names, or a case's @upickle.implicits.key). Not supported, and refused at compile time with a message naming the type: Map (core's ObjectSchema has a fixed set of properties and cannot describe map values), recursive types and sealed hierarchies with fields (both need a JSON Schema construct, $ref and oneOf, that core's schema model lacks), Option directly inside Option and tuples (uPickle writes both as JSON arrays), and named tuples. Other types need a given SchemaOf of their own: see SchemaOf.string and SchemaOf.stringEnum. A hand-written given is used as it is, so it can also describe a type the derivation would refuse.

A recursion that runs through hand-written givens which themselves call SchemaOf.derived (for mutually recursive P and Q, given SchemaOf[P] = SchemaOf.derived[P] and given SchemaOf[Q] = SchemaOf.derived[Q]) cannot be seen at compile time, because the check does not look inside a hand-written given. Building that schema (schema, definition, toJsonSchema) throws an IllegalStateException naming the recursive type instead, on first use; it never hangs.

A generic case class may be nested in itself at most 16 deep: W[W[...[Int]]] with 16 Ws is described, with 17 it is taken for a recursion. Spelled out in a field's type, the deeper nesting is refused at compile time; reached through the generic derives SchemaOf instance (SchemaOf[W[...[Int]]]) it is refused when the schema is built, with the same IllegalStateException.

Type parameters

A

the described type

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
@Experimental
object SchemaOf

Attributes

Companion
trait
Supertypes
class Object
trait Matchable
class Any
Self type
SchemaOf.type
@Experimental
final class description(val text: String) extends StaticAnnotation

The description the model sees for a derived schema: on a case class parameter it describes the field, on a case class, enum or sealed trait it describes the type.

The description the model sees for a derived schema: on a case class parameter it describes the field, on a case class, enum or sealed trait it describes the type.

The text must be a string literal (@description("Total amount")), because the annotation is read at compile time and a macro cannot evaluate an expression. Without it, a field is described by its name and a type by its name.

@description("An invoice extracted from text")
case class Invoice(
 @description("Name of the vendor or supplier") vendor: String,
 amount: Double
) derives SchemaOf

Attributes

Supertypes
trait StaticAnnotation
class Annotation
class Object
trait Matchable
class Any

Extensions

Extensions

extension (client: LLMClient)
def completeStructuredOf[A](conversation: Conversation, options: CompletionOptions)(using schemaOf: SchemaOf[A], reader: Reader[A]): Result[A]

org.llm4s.llmconnect.LLMClient.completeStructured with the schema derived from A instead of written by hand: client.completeStructuredOf[Invoice](conversation).

org.llm4s.llmconnect.LLMClient.completeStructured with the schema derived from A instead of written by hand: client.completeStructuredOf[Invoice](conversation).

A must be a case class (the model answers with a JSON object). Any other derived type, such as an enum, is refused with a Left, since completeStructured takes an object schema. So is a schema that cannot be built, such as a recursion through a hand-written given that derives its type, which SchemaOf.definition throws for: the model is not called.

Type parameters

A

the type to extract; needs a SchemaOf (derives SchemaOf) and a uPickle reader

Value parameters

conversation

the conversation to send

options

completion options, as for completeStructured

Attributes