JSONTask

NAME

LLM::Data::Inference::JSONTask - Task that parses JSON output with schema checks

SYNOPSIS


use LLM::Data::Inference::JSONTask;

# Single backend (legacy)
my $task = LLM::Data::Inference::JSONTask.new(
    backend        => $backend,
    user-prompt    => '...',
    required-keys  => <name age>,
    validator      => -> %h { %h<age> > 0 },
);
my %parsed = $task.execute;

# Model-chain fallback — on malformed JSON / missing keys / validator
# failure, the underlying Task advances to the next backend.
my $task2 = LLM::Data::Inference::JSONTask.new(
    backends       => [$primary, $fallback],
    user-prompt    => '...',
    required-keys  => <name age>,
);

DESCRIPTION

Thin composition over LLM::Data::Inference::Task that plugs in a JSON parser + key-presence + custom-validator pipeline. All fallback and retry semantics come from the underlying Task — see its Pod for the full bucket classification. :parse-retries threads through for same-backend re-rolls on malformed output; :truncation-policy threads through too and, left at its default, resolves to 'fail' here — a JSON task always has a parser, and a completion cut off by max_tokens can never parse, so the chain advances at once and throws X::LLM::Data::Inference::Truncated (an Exhausted subclass) if every backend truncates; :is-cancelled threads through for cooperative cancellation (the Task throws X::LLM::Data::Inference::Cancelled and aborts any in-flight response as soon as the hook reports True); :on-exhausted threads through unchanged and fires exactly once, immediately before the chain throws X::LLM::Data::Inference::Exhausted (or one of its subclasses — Truncated above, or TimedOut when the chain ran out of time) — see Task's Pod for the full payload shape and the type precedence.

:retry-feedback threads through as well, and this is the class it was built for: it makes those :parse-retries re-rolls informed, appending one extra user turn that quotes the rejection — a JSON syntax error, a missing @.required-keys entry, or whatever message &.validator died with. A semantic rejection ("quote 2 does not appear verbatim in the passage") is otherwise re-produced verbatim on every blind re-roll, so the item burns its whole budget failing identically; with feedback the second attempt is a correction pass. Each re-roll replaces the previous feedback, and only re-rolls against the same backend are informed — see Task's "Retry feedback" Pod section for the full rules.

Accepts either :$backend (single) or :@backends (chain); both forms thread through to the inner Task unchanged.

JSON extraction

The extractor tolerates the chatter real models wrap around their answer: < <think>…</think> > reasoning blocks and markdown code fences are stripped, then a string-aware balanced-bracket scan collects every complete top-level JSON structure and picks the longest one that actually parses (models that plan out loud often emit a small throwaway object before the real answer). Only when no complete structure parses does it fall back to the historical first-bracket → last-bracket slice — so truncated completions still fail with the established error messages.

LLM::Data::Inference v0.10.0

Structured LLM task layer with retry, JSON parsing, and query-based routing

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

LLM::Chat:ver<0.10.0+>:auth<zef:apogee>Roaring::Tags:ver<0.2.3+>:auth<zef:apogee>CRoaring:ver<0.2.3+>:auth<zef:apogee>JSON::Fast:ver<0.19>:auth<cpan:TIMOTIMO>

Test Dependencies

Provides

  • LLM::Data::Inference
  • LLM::Data::Inference::Exceptions
  • LLM::Data::Inference::JSONTask
  • LLM::Data::Inference::PromptBuilder
  • LLM::Data::Inference::Router
  • LLM::Data::Inference::Task

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.