Documentation

Introduction

Welcome to the LaravelGPT package! LaravelGPT is a powerful and flexible package designed to integrate OpenAI's language model GPT (Generative Pretrained Transformer) into your Laravel project seamlessly. LaravelGPT is specifically tailored for developers, data scientists, and AI enthusiasts who are seeking to leverage the power of GPT models within a Laravel environment.

With LaravelGPT, you can easily analyze text for various purposes such as sentiment analysis, language translation, text summarization, and more. The package introduces two main concepts: GPTAction and GPTChat, which are designed to streamline the interaction between your application and the GPT model. GPTAction is geared towards scenarios with a single input and task, while GPTChat is suitable for handling more complex, conversational interactions.

Whether you're developing a chatbot, an AI-powered content creation tool, or any other application that needs natural language processing capabilities, LaravelGPT is here to simplify the process. This documentation will guide you through the installation and usage of the LaravelGPT package, along with providing you examples to help get you started. Happy coding!

Just getting started?

If you are just getting started with the LaravelGPT package and want to get a feel for how it works, I recommend to check out the Basic Usage section.

Installation

You can install the package via composer:

composer require maltekuhr/laravel-gpt

Next you need to configure your OpenAI API Key and Organization ID. You can find both in the OpenAI Dashboardopen in new window.

OPENAI_ORGANIZATION=YOUR_ORGANIZATION_ID
OPENAI_API_KEY=YOUR_API_KEY

You are now ready to use LaravelGPT!

Publishing the Config File

You can publish the config file with:

php artisan vendor:publish --provider="MalteKuhr\LaravelGPT\Providers\GPTServiceProvider" --tag="config"

The published config file is located at config/laravel-gpt.php.

Basic Usage

In the following examples we are using LaravelGPT to determine the sentiment of a customer review. Both examples are delivering the same result, but the GPTChat example is more complex and provides more flexibility.

GPTAction

Introduction

GPTAction is a feature provided by LaravelGPT designed to handle scenarios where you need to perform a single task based on a single input. This construct is most suitable for straightforward tasks that don't require back-and-forth or conversation-like interactions with the model.

A classic use-case for GPTAction could be a sentiment analysis task, where the input is a customer review and the task is to determine the sentiment expressed in the review. In such a scenario, you define the task, and the function to execute once the model returns the sentiment.

Example

To create a new GPTAction class, you can use the following command. Adding the --clean option removes the explanatory comments. If the class name doesn't end with GPTAction, the package will automatically append it.

In this example, we're creating an action to determine the sentiment of a customer review:

php artisan make:gpt-action Sentiment

The GPTAction is where you define the task for the model. Start by defining the systemMessage(). This system message explains the task to the model. For more complex messages, it's recommended to use the BladePromptService. You can read more about it in the BladePromptService section. Although it's possible to omit the systemMessage() method, providing a system message helps guide the model.

Next, you define the function to be called by the model. Instead of being utilized for back-and-forth interactions, GPTAction focuses on singular tasks. Consequently, the response generated by this method will only be dispatched to the point of invocation, not back to the model itself. Inside this function, you can define any operations you want. In this example, we determine the sentiment of a customer request and save it in the customer object. To reduce the risk of model-induced errors, the customer object is directly integrated into the GPTAction through the constructor. This approach bypasses the need for the model to fill in the object as a parameter, thereby improving the accuracy and reliability of the process.

Finally, you define the rules() for the function. LaravelGPT uses these to generate the function documentation and to validate the function call. Sometimes, it can be helpful to provide more rules than parameters in your function. For example, if you have a complex task and you want the model to provide a more precise answer, you could add additional rules for explaining the result. The arguments in the documentation will follow the order of the array returned by the rules() method. Additional arguments will be validated but not passed to the function.

<?php

namespace App\GPT\Actions\Sentiment;

use MalteKuhr\LaravelGPT\GPTAction;
use Closure;

class SentimentGPTAction extends GPTAction
{
    public function __construct(
        protected Customer $customer,
    ) {}

    public function systemMessage(): ?string
    {
        return 'Determine the sentiment of the customer review.';
    }

    public function function(): Closure
    {
        return function (string $sentiment): mixed {
            $this->customer->sentiment = $sentiment;
            $this->customer->save();
            
            return [
                'sentiment' => $sentiment
            ];
        };
    }

    public function rules(): array
    {
        return [
            'sentiment' => 'required|string|in:POSITIVE,NEGATIVE,NEUTRAL'
        ];
    }
}

Finally, to call your GPTAction, create a new instance using the make() method, pass the arguments configured in your constructor (if any), and pass your message as a parameter into the send() function. Wait a few seconds and the task will be executed.

echo $customer->sentiment; // null

echo SentimentGPTAction::make($customer)->send('I really like this product.'); // ['sentiment' => 'POSITIVE']

echo $customer->sentiment; // POSITIVE

GPTChat

Introduction

GPTChat is tailored for tasks that require a conversational or iterative interaction with the model. This component is especially effective for complex tasks that involve multiple steps.

A typical use-case for GPTChat could be a customer support bot. In such a situation, you provide a system message that sets the task and maybe gives some context about the customer. You can also include several GPTFunctions that the model might call to gather more information about the customer, previous similar requests, or even current pricing details. Once you start the GPTChat, the model can either respond immediately or call one or more of the provided GPTFunctions for more information. LaravelGPT automatically handles these function calls, which allows for a seamless integration, making the use of functions feel like magic, rather than a complexity that you have to take care of.

Example

Creating a new GPTChat class is as simple as running the following command. The --clean option removes the explanatory comments, and if the class name doesn't end with GPTChat, the package will append it automatically.

php artisan make:gpt-chat CustomerSupport

It is a good practice to create a GPTChat for each specific use-case. In this context, CustomerSupportGPTChat instructs the model to handle customer support requests using the available GPTFunctions if needed, and will continue the conversation until the model provides a message rather than calling a function.

The systemMessage() outlines the task for the model. For more complex messages, it's advised to use BladePromptService. More details about it can be found in the BladePromptService section. Even though it's possible to remove the systemMessage() method, having one can help guide the model effectively.

The functions() method provides an array of GPTFunction instances. These functions can be called by the model to gather more information about the customer or answer the request. The functionCall() method can be used to force the model to respond with a message (return false) or call a specific function (e.g. return BillingDetailsGPTFunction::class). By default, the model decides the next step by itself.

class SentimentGPTChat extends GPTChat
{
    public function __construct(
        public Customer $customer,
        public Ticket $ticket
    ) {}

    public function systemMessage(): ?string
    {
        return 'You are a customer support agent for a software company and their software called "Awesome Software".';
    }

    public function functions(): ?array
    {
        return [
            new KnowledgeBaseSearchGPTFunction(),
            new BillingDetailsGPTFunction($this->customer)
        ];
    }

    public function functionCall(): string|bool|null
    {
        return null;
    }
}

Finally, you need to define your GPTFunctions. In this example, we will focus on KnowledgeBaseSearchGPTFunction, as it provides a good understanding of how to use GPTFunctions within a GPTChat.

Creating a new GPTFunction class is as straightforward as running the following command. This command also supports the --clean option and will append GPTFunction to the class name automatically if it's not included.

php artisan make:gpt-function KnowledgeBaseSearch

The example below shows KnowledgeBaseSearchGPTFunction. The function() method contains the function that the model will call. The rules() method is used to set the validation rules for the function calls, and most importantly, to generate the function's documentation. The description() method provides a description of the function to the model.

class KnowledgeBaseSearchGPTFunction extends GPTFunction
{   
    public function function(): Closure
    {        
        return function (string $query): mixed {
            $articles = KnowlegeBaseArticle::search($query)->take(3)->get();
            
            return [
                'results' => $articles->map(fn ($article) => [
                    'title' => $article->title,
                    'content' => $article->content
                ])
            )
        };
    }

    public function rules(): array
    {
        return [
            'query' => 'required|string|max:255',
        ];
    }

    public function description(): string
    {
        return 'Search the knowledge base for the given query. Returns the three most relevant articles.';
    }
}

Finally, you can put the CustomerSupportGPTChat class into action as follows:

$chat = CustomerSupportGPTChat::make($customer, $ticket);
$chat->addMessage('I have a problem with your software.');
$chat->send();

return $chat->latestMessage()->content;

TIP

This section of the documentation aims to explain the basic usage of LaravelGPT. For more detailed explanations of GPTChat and more advanced examples, please visit the Advanced Usage section.

Advanced Usage

Rules

LaravelGPT uses the validation rules defined in the rules() method of GPTAction and GPTFunction classes to generate the documentation for the model. The rules are also used to validate the function calls. The validation rules are converted into a JSON schema and passed to the model. The model uses this schema to validate the function calls.

Important

LaravelGPT will validate the function call with all rules defined in the rules() method. As of July 2023 LaravelGPT does not support all Laravel validation rules for conversion into the JSON schema provided to the model. If you experience poor results, please create an issue or a pull request. You can add support for custom and missing rules by extending the RuleConverter class and adding the converter to the laravel-gpt config file.

Custom Rule Converters

LaravelGPT enables seamless integration of custom rules. To initiate a custom rule converter, execute the following command. Note that the --clean option purges any explanatory comments, and if the class name doesn't include a RuleConverter suffix, LaravelGPT will append it automatically.

php artisan make:rule-converter Example

This command generates a new ExampleRuleConverter class under the App\GPT\RuleConverters namespace. The priority() method determines the execution order of the rule converters — the higher the value, the sooner the rule converter gets triggered. The handle() method is responsible for transforming the rule into a JSON schema. Here is an example of the ExampleRuleConverter class:

<?php

namespace App\GPT\RuleConverters;

use MalteKuhr\LaravelGPT\Services\JsonSchemaService\Converters\AbstractRuleConverter;

class ExampleRuleConverter extends AbstractRuleConverter
{
    public static function priority(): int
    {
        return 0;
    }

    public function handle(): void
    {
        // TODO: Implement handle() method.
    }
}

Rule Conversion Process

To convert a rule into a JSON schema, the rule must first be identified and applied to the field. This can be done by filtering the $this->rules array. You then need to convert the rules into a JSON Schema. It's recommended to familiarize yourself with the JSON Schemaopen in new window first. Once you've envisioned your desired outcome, you can manually adjust the $this->schema array or use one of the methods supplied by the AbstractRuleConverter class.

Available Methods
  • $this->addDescription(string $description): Appends a description to the current field. If a description already exists, the new description is added to it. To avoid appending the description, you can use the setField() method with a lower priority.

  • $this->setType(string $type, bool $override = false): Determines the type of the current field. If a type already exists and $override is set to false, the method will throw a FieldSetException.

  • $this->setField(string $field, $value, bool $override = false): Establishes the value of a given field. If a value already exists and $override is false, the method will throw a FieldSetException.

  • $this->getType(): Fetches the type of the current field.

  • $this->getField(string $field): Retrieves the value of a specified field.

Note

The rule converter runs for every item in the GPTFunction's or GPTActions rules() array. The $this->rules refer to the rules of the current field. The package employs explode() if your original rules are separated by |. The $this->field represents the name of the current field, such as name if your key was profile.key.

Registering Custom Rule Converters

Last but not least, you need to register your custom rule converter in the laravel-gpt.php config file. If you haven't published the config file yet, please follow the Instructions at the Publishing the Config File section.

Custom Description

We've introduced a custom validation rule for attaching descriptions to fields in the process of generating documentation with Laravel validation rules. You can easily apply the FieldDescription to a field's validation rules by using the static set() method. This method takes a string as an argument, which is then added as a description via the addDescription() method from the AbstractRuleConverter class.

public function rules(): array
{
    return [
        'id' => ['required', 'integer', FieldDescription::set('The ID of the user')],
    ];
}

In this example, the string 'The ID of the user' is provided to the set() method of FieldDescription, establishing it as the field's description.