The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

DWIM::Block - Use AI::Chat without having to write the infrastructure code

VERSION

This document describes DWIM::Block version 0.000002

SYNOPSIS

    use DWIM::Block;

    sub autoinflect ($text) {
        DWIM {
            Please inflect the following text so that its grammar is correct
            and its nouns and verbs agree in number and person.
            Please return only the inflected sentence, without any commentary:

            $text
        }
    }

    sub autoformat ($text, %opt) {
        $opt{width} //= 72;

        DWIM {
            Could you please reformat the following text quotation from an email,
            so that each line is no more than $opt{width} columns.
            Please preserve any leading email quoters and,
            if the plaintext contains a list of numbered points,
            ensure that the point numbers are sequential and remain outdented
            from the reformatted text of each point.
            Please return only the reformatted plaintext, without any commentary:

            $text
        }
    }

    dwim carp ($message) {
        Carp::carp(
            DWIM { Please convert the following text to a haiku: $message }
        );
    }


    # And then these "just work" (assuming ChatGPT actually understands your requests)...

    carp "Bad argument to method left()";

    say autoinflect "When you has did 6 impossible thing before breakfast...";

    say autoformat $wide_text, width => 42;


    # Now choose a more powerful model to generate better haiku...

    local $ENV{'DWIM_MODEL'} = 'gpt-4-turbo';

    carp "Bad argument to method left()";

DESCRIPTION

This module makes it easy to build code that sends a request to the OpenAI API and then returns the response.

Instead of writing:

    sub autoinflect ($text) {
        use AI::Chat;

        state $GPT = AI::Chat->new(
            key   => $ENV{'DWIM_API_KEY'} // $ENV{'OPENAI_API_KEY'} // die "Can't find API key",
            model => 'gpt-4-turbo'
        );

        my $REQUEST = <<~"END_REQUEST"
            Please inflect the following text so that its grammar is correct
            and its nouns and verbs agree in number and person.
            Please return only the inflected sentence, without any commentary:

            $text
        END_REQUEST

        return $GPT->prompt($REQUEST);
    }

...you simply replace all the code needed to drive AI::Chat with a single DWIM block containing the actual request you want to send. Like so:

    sub autoinflect ($text) {
        DWIM {
            Please inflect the following text so that its grammar is correct
            and its nouns and verbs agree in number and person.
            Please return only the inflected sentence, without any commentary:

            $text
        }
    }

This automatically adds back in all the necessary boilerplate code to drive Chat::AI.

Note that the contents of the DWIM block behave exactly like a double-quoted string, which is then passed to AI::Chat::prompt(). This means that you can put Perl variables inside the block and they will be interpolated into the double-quoted string. For instance, note the use of $text in the comment in the preceding example.

Capturing the result of the query

Unlike regular Perl blocks, you can also use a DWIM block as part of a larger expression (as you would a do block). For example:

    dwim from_JSON ($JSON_data) {

        return eval DWIM { Please convert the following JSON object to a Perl hashref: JSON_data };

    }

Note that, if the query fails for any reason, the result of the DWIM block may be undef.

The module decides whether to treat a DWIM as an control block or a do block, by examining its syntactic location. If a DWIM is specified at the beginning of a statement, it is treated as a control block (like an if or for block), and does not require a semicolon after it. If it is not in a location where a control block could appear, it is treated as a special form of do block, and the expression containing it does require a semicolon (or a closing block delimiter) after it.

DIAGNOSTICS

Can't find API key

The module requires an OpenAI API key to allow it to connect with the AI server. This key must be provided in an environment variable, which may be named either DWIM_API_KEY or OPENAI_API_KEY.

You specified a DWIM block, but it could not find either of those environment variables.

Set up the variable in your shell or IDE. For example, in your shell config file:

    # In your .bashrc or .zshrc file:
    export DWIM_API_KEY=sk-proj-y0ur0p3n41Pr0j3c74P1k3y6035H3r3TH150n35N07R34l

    # In your .cshrc file:
    setenv DWIM_API_KEY sk-proj-y0ur0p3n41Pr0j3c74P1k3y6035H3r3TH150n35N07R34l

    # In your .env file:
    DWIM_API_KEY=sk-proj-y0ur0p3n41Pr0j3c74P1k3y6035H3r3TH150n35N07R34l

CONFIGURATION AND ENVIRONMENT

DWIM::Block requires no configuration files.

The module requires one of the following environment variables to be set to a string representing a valid API key for the model you are using:

    $ENV{'DWIM_API_KEY'}

    $ENV{'OPENAI_API_KEY'}

If both are set, then $ENV{'DWIM_API_KEY'} is always used.

The module also looks for one of the following environment variables, with which you can specify the specific model to be used:

    $ENV{'DWIM_MODEL'}

    $ENV{'OPENAI_MODEL'}

If both are set, then $ENV{'DWIM_MODEL'} is always used. If neither is set, then AI::Chat selects the model for you automatically.

DEPENDENCIES

This module requires the Filter::Simple, PPR, and AI::Chat modules.

INCOMPATIBILITIES

None reported.

BUGS AND LIMITATIONS

No bugs have been reported.

What a DWIM can be made to accomplish is limited primarily by your imagination.

Please report any bugs or feature requests to bug-dwim-block@rt.cpan.org, or through the web interface at http://rt.cpan.org.

AUTHOR

Damian Conway <DCONWAY@CPAN.org>

LICENCE AND COPYRIGHT

Copyright (c) 2024, Damian Conway <DCONWAY@CPAN.org>. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.