App-Greple-xlate
view release on metacpan or search on metacpan
lib/App/Greple/xlate/llm.pm view on Meta::CPAN
push @command, '-o', @$kv;
}
push @command, '--no-stream', '--no-log';
@command;
}
sub _llm_in_path {
grep { -x "$_/llm" } split /:/, $ENV{PATH} // '';
}
sub _not_found {
"llm: command not found.\n" .
"Install llm <https://llm.datasette.io/> with " .
"\"pip install llm\" or \"pipx install llm\".\n";
}
sub run_llm {
state $run = Command::Run->new;
my($param, $text) = @_;
##
## Check PATH before forking: Command::Run's forked child has no
## exit guard after a failed exec, so reaching that path would let
## the child escape into the caller's code.
##
_llm_in_path() or die _not_found();
my @command = llm_command($param, build_system($param));
warn Dumper \@command if opt('debug');
my $result = $run->command(@command)
->run(stdin => $text, stderr => 'capture');
if ($result->{result} != 0) {
die diagnose($param, $result);
}
print STDERR $result->{error} if $result->{error};
$result->{data};
}
##
## Called when the llm command fails: figure out why and return a
## message useful to the user.
##
sub diagnose {
my($param, $result) = @_;
my $stderr = $result->{error} // '';
if (! _llm_in_path()) {
return _not_found();
}
my $model = $param->{model};
my $models = Command::Run->new->command('llm', 'models')
->run(stderr => 'capture')->{data} // '';
if ($models !~ /\Q$model\E/) {
return "llm does not know model \"$model\".\n" .
"Upgrade llm (\"pip install -U llm\") or register the model " .
"in extra-openai-models.yaml.\n" .
($stderr ? "\n$stderr" : "");
}
( run in 1.983 second using v1.01-cache-2.11-cpan-9581c071862 )