PHP code example of moe-mizrak / laravel-prompt-alchemist

1. Go to this page and download the library: Download moe-mizrak/laravel-prompt-alchemist library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

moe-mizrak / laravel-prompt-alchemist example snippets


return [
    'env_variables' => [
        'api_key'       => env('OPENROUTER_API_KEY'),
        'api_endpoint'  => env('OPENROUTER_API_ENDPOINT', 'https://openrouter.ai/api/v1/'),
        'default_model' => 'Your selection of the default model',
    ],

    'functions_yml_path' => 'Path to the functions yml file',

    'schemas' => [
        'function_payload_schema_path' => 'Path to the function payload schema yml file',
        'function_results_schema_path' => 'Path to the function results schema yml file',
    ],

    'instructions' => [
        'prompt_function_instructions'  => 'Instructions for the LLM about how to make use of provided functions, prompt and function_payload_schema in order to get the desired response',
        'function_results_instructions' => 'Instructions for the LLM about how to make use of provided function_results, prompt and function_results_schema in order to get the desired response',
        'generate_prompt_function_instructions' => 'Instructions for generating specific/customised prompt_function_instructions',
    ],

    'function_signature_mapping' => 'Function signature mapping data (FunctionSignatureMappingData)',
];

'functions_yml_path' => __DIR__ . '/../resources/functions.yml', // functions.yml is located under resources folder in this example.

$class = Example::class;

$functionDataA = new FunctionData([
    'function_name' => 'getFinancialData',
    'parameters' => [
        new ParameterData([
            'name' => 'userId',
            'type' => 'int',
            ' => true,
            'description' => 'The starting date for the timeframe (inclusive).',
            'example' => '2023-01-01'
        ]),
        new ParameterData([
           'name' => 'endDate',
           'type' => 'string',
           'unctionDataB = new FunctionData([
    'function_name' => 'categorizeTransactions',
    'parameters' => [
        new ParameterData([
            'name' => 'transactions',
            'type' => 'array',
            'ion may also 

'function_payload_schema_path' => __DIR__ . '/../resources/schemas/function_payload_schema.yml', // function_payload_schema.yml is located under resources/schemas folder in this example.

$prompt = 'Can tell me Mr. Boolean Bob credit score?';
$model = config('laravel-prompt-alchemist.env_variables.default_model'); // Check https://openrouter.ai/docs/models for supported models
$content = LaravelPromptAlchemist::preparePromptFunctionPayload($prompt); // Prepare payload for the request.

$messageData = new MessageData([
    'content' => json_encode($content),
    'role'    => RoleType::USER,
]);

$chatData = new ChatData([
    'messages' => [
        $messageData,
    ],
    'model'       => $model,
    'temperature' => 0.1, // Set temperature low to get better result. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.
]);

// Send OpenRouter request
$response = LaravelOpenRouter::chatRequest($chatData);

// $response = LaravelOpenRouter::chatRequest($chatData);
$responseContentData = str_replace("\n", "", (Arr::get($response->choices[0], 'message.content'))); // Get content from the response.
$llmReturnedFunctions = json_decode($responseContentData, true); // Functions returned from LLM.

// Foreach $llmReturnedFunctions and get each function to validate:
$llmReturnedFunction = [ // Sample LLM returned function
    "function_name" => "getFinancialData",
    "parameters" => [
        [ "name" => "userId", "type" => "int"],
        [ "name" => "startDate", "type" => "string"],
        [ "name" => "endDate", "type" => "string"],
    ],
    'class_name' => 'MoeMizrak\LaravelPromptAlchemist\Tests\Example'
];

// Formed LLM returned function data (FunctionData).
$llmReturnedFunctionData = LaravelPromptAlchemist::formLlmReturnedFunctionData($llmReturnedFunction);

$isValid = LaravelOpenRouter::validateFunctionSignature($llmReturnedFunctionData);

// Create parameter values, you just need parameter name and its value in correct type (int, string, array, object ...)
$parameters = [
    new ParameterData([
        'name' => 'userId',
        'value' => 99, // int userId
    ]),
    new ParameterData([
        'name' => 'startDate',
        'value' => '2023-06-01', // string startDate
    ]),
    new ParameterData([
        'name' => 'endDate',
        'value' => '2023-07-01', // string endDate
    ]),
];

if (true === $isValid) {
    // Set parameter values.
    $llmReturnedFunctionData->setParameterValues($parameters);
}

$functionResultData = LaravelPromptAlchemist::callFunction($llmReturnedFunctionData);

output:

FunctionResultData([
    'function_name' => 'getFinancialData',
    'result'        => (object) [
        'totalAmount' => 1000.0,
        'transactions' => [
            ['amount' => 100, 'date' => '2023-01-01', 'description' => 'Groceries'],
            ['amount' => 200, 'date' => '2023-01-02', 'description' => 'Utilities'],
        ],
        'message' => 'Retrieved financial data for user 99 from 2023-06-01 to 2023-07-01'
     ],
])

$prompt = 'Can tell me Mr. Boolean Bob credit score?';
$model = config('laravel-prompt-alchemist.env_variables.default_model'); // Check https://openrouter.ai/docs/models for supported models
$functionResults = [
    new FunctionResultData([
        'function_name' => 'getFinancialData',
        'result' => [
            'totalAmount' => 122,
            'transactions' => [
                [
                    'amount'      => 12,
                    'date'        => '2023-02-02',
                    'description' => 'food',
                ],
            ]
        ]
    ]),
    new FunctionResultData([
        'function_name' => 'getCreditScore',
        'result' => [
            'creditScore' => 0.8,
            'summary' => 'reliable',
        ]
    ]),
    ...
];
// Prepare function results payload for the request.
$content = LaravelPromptAlchemist::prepareFunctionResultsPayload($prompt, $functionResults);

$messageData = new MessageData([
    'content' => json_encode($content),
    'role'    => RoleType::USER,
]);

$chatData = new ChatData([
    'messages' => [
        $messageData,
    ],
    'model'       => $model,
    'temperature' => 0.1, // Set temperature low to get better result. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.
]);

// Send OpenRouter request for function results
$response = LaravelOpenRouter::chatRequest($chatData);

$class = Example::class; // Or you can give fully qualified class name string as $class = 'MoeMizrak\LaravelPromptAlchemist\Tests\Example'

// Function descriptions that will be used to generate function list (functions.yml) 
$functionDataA = new FunctionData([
    'function_name' => 'getFinancialData',
    'parameters' => [
        new ParameterData([
            'name' => 'userId',
            'type' => 'int',
            '
           'type' => 'string',
           'unctionDataB = new FunctionData([
    'function_name' => 'categorizeTransactions',
    'parameters' => [
        new ParameterData([
            'name' => 'transactions',
            'type' => 'array',
            'ion may also 

$class = Example::class; // Or you can give fully qualified class name string as $class = 'MoeMizrak\LaravelPromptAlchemist\Tests\Example'
// Name of the functions that will be added to the list - functions that will be used for Tool Use (Function Calling)
$functions = [
    'getFinancialData',
    'categorizeTransactions',
];
$fileName = __DIR__ . '/../resources/functions.yml'; // Path and the name of the file that function list will be generated
// Call generateFunctionList for automated function list generation in given $fileName (Creates file in this path if not existed).
LaravelPromptAlchemist::generateFunctionList($class, $functions, $fileName);

/**
 * This public function is intended for testing purposes. It accepts a string and int parameters and returns a string.
 * It has additional parameter descriptions and detailed docblock.
 *
 * @param string $stringParam This is the string param description
 * @param int $intParam This is the int param description
 *
 * @return string This is the return value description
 */
public function detailedDocBlockFunction(string $stringParam, int $intParam = 2): string
{
    return 'detailed docblock function return value ' . $stringParam . ' ' . $intParam;
}

function noExtraInfoProvidedFunction($stringParam, $intParam)
{
    return 'missing parameter and docblock function return value ' . $stringParam . ' ' . $intParam;
}

/**
 * This public function is intended for testing purposes.
 * It has missing parameter descriptions and missing type-hint.
 *
 * @return string This is the return value description
 */
public function functionWithSomeMissingDocBlockAndMissingTypeHint($stringParam, $intParam): string
{
    return 'missing parameter docblock function return value ' . $stringParam . ' ' . $intParam;
}

'function_signature_mapping' => new FunctionSignatureMappingData([
    'function_name' => new MappingData([
        'path' => 'function_name',
        'type' => 'string',
    ]),
    'function_description' => new MappingData([
        'path' => 'description',
        'type' => 'string',
    ]),
    'function_visibility' => new MappingData([
        'path' => 'visibility',
        'type' => 'string',
    ]),
    'function_return_type' => new MappingData([
        'path' => 'return.type',
        'type' => 'string',
    ]),
    'function_return_description' => new MappingData([
        'path' => 'return.description',
        'type' => 'string',
    ]),
    'function_return_example' => new MappingData([
        'path' => 'return.example',
        'type' => 'mixed',
    ]),
    'parameters' => new MappingData([
        'path' => 'parameters', // could be arguments, parameter_definitions, input_schema.properties, parameters.properties
        'type' => 'array',
    ]),
    'parameter_name' => new MappingData([
        'path' => 'parameters[].name', // since parameters field is array, '[]' states the index key which will be resolved in the package as 'parameters.0.name' for the first array and so on.
        'type' => 'string',
    ]),
    'parameter_type' => new MappingData([
        'path' => 'parameters[].type',
        'type' => 'string',
    ]),
    'parameter_

'function_signature_mapping' => new FunctionSignatureMappingData([
    'function_name' => new MappingData([
        'path' => 'function',
        'type' => 'string',
    ]),
    'function_description' => new MappingData([
        'path' => 'description',
        'type' => 'string',
    ]),
    'function_visibility' => new MappingData([
        'path' => 'visibility',
        'type' => 'string',
    ]),
    'function_return_type' => new MappingData([
        'path' => 'return.type',
        'type' => 'string',
    ]),
    'function_return_description' => new MappingData([
        'path' => 'return.description',
        'type' => 'string',
    ]),
    'function_return_example' => new MappingData([
        'path' => 'return.example',
        'type' => 'mixed',
    ]),
    'input_schema_type' => new MappingData([
        'path' => 'input_schema.type',
        'type' => 'string',
    ]),
    'parameters' => new MappingData([
        'path' => 'input_schema.properties',
        'type' => 'array',
    ]),
    'parameter_name' => new MappingData([
        'path' => 'input_schema.properties[].name', // since properties field is array, '[]' states the index key which will be resolved in the package as 'properties.0.name' for the first array and so on.
        'type' => 'string',
    ]),
    'parameter_type' => new MappingData([
        'path' => 'input_schema.properties[].type',
        'type' => 'string',
    ]),
    'parameter_

LaravelPromptAlchemist::generateInstructions();

'schemas' => [
    'function_payload_schema_path' => __DIR__ . '/../resources/schemas/function_payload_schema.yml',
]

'schemas' => [
    'function_results_schema_path' => __DIR__ . '/../resources/schemas/function_results_schema.yml',
]

$prompt = 'Can tell me Mr. Boolean Bob credit score?';

LaravelPromptAlchemist::preparePromptFunctionPayload($prompt);

[
  "prompt" => "Can tell me Mr. Boolean Bob credit score?",
  "instructions" => "You are an AI assistant that strictly follows instructions and provides responses in a specific format.\n
    Your task is to analyze a given prompt and identify the l information, explanations, or values beyond what is specified in the schema. Adhere to the following instructions:\n
    1. Read the provided \"prompt\" and the list of available \"functions\".\n
    2. Identify which function(s) from the \"functions\" list ...",
  "functions" => [
    [
        "function_name" => "getFinancialData",
        "parameters" => [
            ["name" => "userId", "type" => "int"],
            ["name" => "startDate", "type" => "string"],
            ["name" => "endDate", "type" => "string"]
        ],
        "visibility" => "public",
        "description" => "Retrieves financial data for a specific user and timeframe.",
        "return" => [
            "type" => "object",
            "description" => "An object containing details like totalAmount, transactions (array), and other relevant financial data."
        ],
        "class_name" => "MoeMizrak\LaravelPromptAlchemist\Tests\Example"
    ],
    [
        "function_name" => "getCreditScore",
        "parameters" => [
            ["name" => "userId", "type" => "int"]
        ],
        "visibility" => "public",
        "description" => "Retrieves the current credit score for a specific user.",
        "return" => [
            "type" => "object",
            "description" => "An object containing the credit score, credit report summary, and any relevant notes."
        ],
        "class_name" => "MoeMizrak\LaravelPromptAlchemist\Tests\Example"
    ],
    ...
  ],
  "function_payload_schema" => [
    [
        "function_name" => "getFinancialData",
        "parameters" => [
            ["name" => "userId", "type" => "int"],
            ["name" => "startDate", "type" => "string"],
            ["name" => "endDate", "type" => "string"]
        ],
        "class_name" => "MoeMizrak\LaravelPromptAlchemist\Tests\ExampleA"
    ],
    [
        "function_name" => "getCreditScore",
        "parameters" => [
            ["name" => "userId", "type" => "int"]
        ],
        "class_name" => "MoeMizrak\LaravelPromptAlchemist\Tests\ExampleD"
    ],
    ...
  ]
]

$prompt = 'Can tell me Mr. Boolean Bob credit score?';
$model = config('laravel-prompt-alchemist.env_variables.default_model'); // Check https://openrouter.ai/docs/models for supported models
$content = LaravelPromptAlchemist::preparePromptFunctionPayload($prompt);

$messageData = new MessageData([
    'content' => json_encode($content),
    'role'    => RoleType::USER,
]);

$chatData = new ChatData([
    'messages' => [
        $messageData,
    ],
    'model'       => $model,
    'temperature' => 0.1, // Set temperature low to get better result. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.
]);

// Send OpenRouter request
$response = LaravelOpenRouter::chatRequest($chatData);

output:

ResponseData([
    'id' => 'gen-YFd68mMgTkrfHVvkdemwYxdGSfZA',
    'model' => 'mistralai/mistral-7b-instruct:free',
    'object' => 'chat.completion',
    'created' => 1719251736,
    'choices' => [
        0 => [
            'index' => 0,
            'message' => [
                'role' => 'assistant',
                'content' => '["function_name":"getFinancialData", "parameters":[{"name":"userId","type":"int"},{"name":"startDate","type":"string"},{"name":"endDate","type":"string"}],"function_name":"categorizeTransactions", "parameters":[{"name":"transactions","type":"array"}],"function_name":"getTopCategories", "parameters":[{"name":"transactions","type":"array"}]]',
            ],
            'finish_reason' => 'stop',
        ]
    ],
    'usage' => UsageData([
        'prompt_tokens' => 1657,
        'completion_tokens' => 97,
        'total_tokens' => 1754,
    ])    
]);

// $response = LaravelOpenRouter::chatRequest($chatData); as shown in  [Send Tool Use (Function Calling) Request to OpenRouter] section
$responseContentData = str_replace("\n", "", (Arr::get($response->choices[0], 'message.content'))); // Get content from the response.
$llmReturnedFunctions = json_decode($responseContentData, true); // Functions returned from LLM.

// Foreach $llmReturnedFunctions and get each function to validate:
$llmReturnedFunction = [ // Sample LLM returned function
    "function_name" => "getFinancialData",
    "parameters" => [
        [ "name" => "userId", "type" => "int"],
        [ "name" => "startDate", "type" => "string"],
        [ "name" => "endDate", "type" => "string"],
    ],
    'class_name' => 'MoeMizrak\LaravelPromptAlchemist\Tests\Example'
];

// Form LLM returned function data (FunctionData).
$llmReturnedFunctionData = $this->request->formLlmReturnedFunctionData($llmReturnedFunction);

// Add parameter values if exists, only name and value of the parameter are set.
$parameters = [
    new ParameterData([
        'name' => 'userId',
        'value' => 99,
    ]),
    new ParameterData([
        'name' => 'startDate',
        'value' => '2023-06-01',
    ]),
    new ParameterData([
        'name' => 'endDate',
        'value' => '2023-07-01',
    ]),
];
// Set parameter values in $llmReturnedFunctionData DTO
$llmReturnedFunctionData->setParameterValues($parameters);

$isValid = LaravelOpenRouter::validateFunctionSignature($llmReturnedFunctionData); // $isValid is bool or ErrorData

output:

ErrorData([
    'code' => 400,
    'message' => 'Function invalidFunctionName does not exist in class MoeMizrak\LaravelPromptAlchemist\Tests\Example'
]);

$functionResult = LaravelPromptAlchemist::callFunction($llmReturnedFunctionData);

output:

FunctionResultData([
    'function_name' => 'getFinancialData',
    'result' => [
        'totalAmount' => 122,
        'transactions' => [
            [
                'amount'      => 12,
                'date'        => '2023-02-02',
                'description' => 'food',
            ],
        ]
    ]
]),

$prompt = 'Can tell me Mr. Boolean Bob credit score?';

$functionResults = [
    new FunctionResultData([
        'function_name' => 'getFinancialData',
        'result' => [
            'totalAmount' => 122,
            'transactions' => [
                [
                    'amount'      => 12,
                    'date'        => '2023-02-02',
                    'description' => 'food',
                ],
            ]
        ]
    ]),
    new FunctionResultData([
        'function_name' => 'getCreditScore',
        'result' => [
            'creditScore' => 0.8,
            'summary' => 'reliable',
        ]
    ]),
    ...
];

LaravelPromptAlchemist::prepareFunctionResultsPayload($prompt, $functionResults);

[
  "prompt" => "Can tell me Mr. Boolean Bob credit score?",
  "instructions" => "You will strictly follow the instructions:\n
    - Understand the provided prompt and answer the prompt using the function_results (needed info is provided in function_results). If function_results are not sufficient enough, then your answer will be \"Please provide more information about [missing information]\"\n
    - Respond based on the function_results_schema sample provided (Do not add any extra info, exactly the same format provided in function_results_schema).\n
    - Format the response as an array following  ...",
  "function_results" => [
    [
        "function_name" => "getFinancialData",
        "result" => [
            "totalAmount" => 122,
            "transactions" => [
                [
                "amount" => 12,
                "date" => "2023-02-02",
                "description" => "food"
                ]
            ]
        ]
    ],
    [
        "function_name" => "getCreditScore",
        "result" => [
            "creditScore" => 0.8,
            "summary" => "reliable"
        ]
    ]
    ...
  ],
  "function_results_schema" => [
    [
        "function_name" => "getFinancialData",
        "result" => [
            [
                "name" => "transactions",
                "type" => "array",
                "value" => [
                    [
                        "amount" => null,
                        "date" => "2023-02-02",
                        "description" => "shoes"
                    ]
                ]
            ],
            [
                "name" => "totalAmount",
                "type" => "int",
                "value" => 1234
            ]
      ]
    ],
    [
        "function_name" => "getCreditScore",
        "result" => [
            [
                "name" => "creditScore",
                "type" => "float",
                "value" => 0.5
            ],
            [
                "name" => "summary",
                "type" => "string",
                "value" => "reliable"
            ]
        ]
    ]
    ...
  ]
]

$prompt = 'Can tell me Mr. Boolean Bob credit score?';
$functionResults = [
    new FunctionResultData([
        'function_name' => 'getFinancialData',
        'result' => [
            'totalAmount' => 122,
            'transactions' => [
                [
                    'amount'      => 12,
                    'date'        => '2023-02-02',
                    'description' => 'food',
                ],
            ]
        ]
    ]),
    new FunctionResultData([
        'function_name' => 'getCreditScore',
        'result' => [
            'creditScore' => 0.8,
            'summary' => 'reliable',
        ]
    ]),
    ...
];
$content = LaravelPromptAlchemist::prepareFunctionResultsPayload($prompt, $functionResults);
$model = config('laravel-prompt-alchemist.env_variables.default_model'); // Check https://openrouter.ai/docs/models for supported models

$messageData = new MessageData([
    'content' => json_encode($content),
    'role'    => RoleType::USER,
]);

$chatData = new ChatData([
    'messages' => [
        $messageData,
    ],
    'model'       => $model,
    'temperature' => 0.1, // Set temperature low to get better result. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.
]);

// Send OpenRouter request
$response = LaravelOpenRouter::chatRequest($chatData);

output:

ResponseData([
    'id' => 'gen-YFd68mMgTkrfHVvkdemwYxdGSfZA',
    'model' => 'mistralai/mistral-7b-instruct:free',
    'object' => 'chat.completion',
    'created' => 1719440793,
    'choices' => [
        0 => [
            'index' => 0,
            'message' => [
                'role' => 'assistant',
                'content' => '[{"name": "creditScore", "type": "float", "value": 0.8}, {"name": "summary", "type": "string", "value": "reliable"}]',
            ],
            'finish_reason' => 'stop',
        ]
    ],
    'usage' => UsageData([
        'prompt_tokens' => 657,
        'completion_tokens' => 69,
        'total_tokens' => 726,
    ])    
]);

public function __construct(protected PromptAlchemistRequest $promptAlchemistRequest) {}

// generateFunctionList request.
$this->promptAlchemistRequest->generateFunctionList($class, $functions, $fileName);

// Generate instructions request.
$this->promptAlchemistRequest->generateInstructions();

// Prepare prompt function payload request.
$this->promptAlchemistRequest->preparePromptFunctionPayload($prompt);

// Forms LLM returned function into the FunctionData.
$this->promptAlchemistRequest->formLlmReturnedFunctionData($llmReturnedFunction);

// Validate function signature returned by the LLM request.
$this->promptAlchemistRequest->validateFunctionSignature($llmReturnedFunctionData); // $isValid is bool or ErrorData

// Make an actual function call.
$this->promptAlchemistRequest->callFunction($llmReturnedFunctionData);

// Prepare function results payload request.
$this->promptAlchemistRequest->prepareFunctionResultsPayload($prompt, $functionResults);
bash
php artisan vendor:publish --tag=laravel-prompt-alchemist