outl1ne / nova-openai

3 stars 1 forks source link

Add prompt templating functionality #14

Open Oskar-V opened 6 months ago

Oskar-V commented 6 months ago

Function:

Messages could have a built-in content substitution functionality to make it easier to use message templates ie:

// Example 1
$user_message = "Hi my name is Bob"
$template = "User question: [user_message]
Reply with a valid JSON object in with the following format:
{
\"prompt\": \"[user_message]\"
\"answer\": _your_answer_
\"something_else\": _random_number_
}"

// Examle 2
$assistant_data = [
"name" => "Bob",
"age" => "25",
"gender" => "Male"
]
$system_template = "You're a [age] year old human [gender] named [name] and you're talking to another human about..."

Current overwrite example:


public function user(string $content, ?string $name = null, ?array $substitutions = null): self
{
    $message = [
        'role' => 'user',
        'content' => $content,
    ];
        # If any substitutions were provided swap them into the user message
    $message = $this->substitute($message, $substitutions);

    $message = $this->addOptionalProperty($message, 'name', $name);
    $this->messages[] = $message;

    return $this;
}

$messages = (new Messages)
    ->system($system_message_template, null, $system_substitutions)
    ->user($user_message_template, null, $user_substitutions);
allantatter commented 6 months ago

sprintf function might do the trick for you: https://www.php.net/manual/en/function.sprintf.php

$systemPrompt = sprintf("Hello
You're a %d year old human %s named %s and you're talking to another human about...", 25, 'female', 'Oskar');
OpenAI::chat()->create(
    model: 'gpt-3.5-turbo',
    messages: (new Messages)->system($systemPrompt)->user('Hello!'),
);
Oskar-V commented 6 months ago

The need is to replace concrete key-value pairs in a text, where the key itself exists in the initial template text in random positions which change and can't be known ahead of time. Hence can't use sprintf or other simple text replacements.

// Example helper function to solve the problem
public static function substitute(string $message, ?array $substitutions): string
{
    if ($substitutions === null) return $message
    return str_replace(
        array_map(fn ($val) => "[{$val}]", array_keys($substitutions)),
        array_map(fn ($val) => is_array($val) ? implode($val) : $val, array_values($substitutions)),
        $message
    );
}

This example is a decoupled version of the substitute function used in the initial issue description

Ideally the built in helper would support turning more complex elements into proper text representations then the current implementation which is able to support up to 2d arrays of key-value substitution pairs.