NAME
Database::BI::Ask - Natural language to analysis spec (Phase 5.1)
SYNOPSIS
use Database::BI::Ask;
my $typed = Database::BI::Ask::infer_column_types(\@records, \@columns);
my $result = Database::BI::Ask::ask(
question => 'show me sales by region as a pie chart',
spec_key => 'table:sales',
label => 'sales',
columns => $typed,
ai_config => { provider => 'anthropic', api_key => $key, model => 'claude-haiku-5-5' },
);
# $result = { spec => {...}, url => '/pie?l=...&cat=region', valid => 1 }
DESCRIPTION
Translates a plain-English question into a Phase 3 analysis spec by calling the Anthropic Messages API. The model receives only column names and types -- never raw row data, file paths, or credentials.
The returned spec is validated before being returned to the caller: every column name in the encode section must appear in the supplied column list, and the kind must be a supported chart type. An invalid spec is returned as { error => 'ask_invalid_spec:...' } and never executed.
The feature is entirely absent (returns ask_unavailable) when no api_key is supplied, keeping the app functional with no AI configured.
FUNCTIONS
ask(%args)
Returns { spec, url, valid => 1 } on success, or { error => 'code' } on failure. Error codes: ask_no_question, ask_unavailable, ask_provider_error, ask_unparseable, ask_invalid_spec:col.
infer_column_types($records, $columns)
Infers each column's type ('number', 'date', 'string') from a sample of records. A column is 'number' when more than half its non-empty values pass Scalar::Util::looks_like_number. It is 'date' when more than half match YYYY-MM-DD or M/D/YYYY. Otherwise 'string'.
AUTHOR
Nigel Horne <njh@nigelhorne.com>
LICENCE AND COPYRIGHT
Copyright 2026 Nigel Horne.
Usage is subject to the GPL2 licence terms.