Start with ordinary text
Sketches works with the same loaded CausalLanguageModel as the rest of Reckoning. Unconstrained generation remains available when you just want text:
String result = Sketches.generator(model)
.raw("Say something");
Match a pattern
Use a regular expression when the response has a small, precise shape:
String ticket = Sketches.generator(model)
.regex("[A-Z]{2}-[0-9]{4}")
.generate("Create a ticket number");
Choose from known answers
For classification or routing, give the model the complete set of allowed choices:
String sentiment = Sketches.generator(model)
.choice(List.of("Positive", "Negative", "Neutral"))
.generate("I really enjoyed the movie from start to finish");
Return a Java type
Define the shape once as a Java record. Sketches derives the JSON constraint, guides generation, and deserializes the result back into the type:
record Review(String sentiment, int score) {}
Review review = Sketches.generator(model)
.json(Review.class)
.generate("Back to the Future is the best movie, besides Back to the Future II");
Review[Positive, 9]Use generic result types
Jackson’s TypeReference keeps collections and nested generic results typed. This prompt names three reviews, so the result is a list with exactly three records:
List<Review> reviews = Sketches.generator(model)
.json(new TypeReference<List<Review>>() {})
.generate("""
Return exactly three Review records, one for each review:
1. I really enjoyed this one.
2. This movie was scary.
3. I laughed until I cried.
""");
[Review[Positive, 9], Review[Negative, 6], Review[Positive, 8]]Failures are explicit
If the model returns invalid JSON or generation fails, Sketches raises SketchesGenerationException instead of silently returning an unusable object.
SketchesGenerationException
"Generated output was not valid JSON for Review"
The point: Sketches is not a parser bolted onto the end of generation. The constraint is applied while the model chooses each token.