Использование ChatGPT "Function Calling" в Laravel
Недавно OpenAI выпустила обновление для ChatGPT, внедрив новые функции, которые позволяют разработчикам описывать функции языковой модели – gpt-4-0613
и gpt-3.5-turbo-0613
. Эти возможности позволяют генерировать объекты JSON с аргументами для запуска этих функций на основе ввода пользователя.
Давайте рассмотрим пример использования этой новой функциональности. Ее можно применять для получения информации о IP-адресе, предыдущих заказах, содержании FAQ, прогнозе погоды или любой другой нужной информации.
Для демонстрации принципа работы мы воспользуемся библиотекой openai-php/client
. Прежде всего, создадим команду Artisan с помощью следующей команды:
php artisan make:command ChatFunction
Затем обновите класс ChatFunction
следующим образом:
namespace App\Console\Commands;
use Illuminate\Console\Command;
use OpenAI\Client;
class ChatFunction extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:chat-function';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Invoke a chat function with OpenAI language model.';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$client = new Client(config('openai.api_key'));
$response = $client->chat()->create([
'model' => 'gpt-3.5-turbo-0613',
'messages' => [
[
'role' => 'user',
'content' => 'What do you know about IP address 12.175.87.227?',
],
],
]);
$answer = $response->choices[0]->message->content;
$this->info("OpenAI response: $answer");
}
}
Если мы попросим ИИ предоставить информацию о конкретном IP-адресе, он может ответить примерно так: “Извините, но я не могу предоставить информацию о конкретных IP-адресах.”
Чтобы исправить это, давайте укажем функцию в нашем запросе.
namespace App\Console\Commands;
use Illuminate\Console\Command;
class ChatFunction extends Command
{
public function handle()
{
$client = \OpenAI::factory()
->withApiKey(config('openai.api_key'))
->make();
$response = $client->chat()->create([
'model' => 'gpt-3.5-turbo-0613',
'messages' => [
[
'role' => 'user',
'content' => 'What do you know about IP 12.175.87.227 ?',
],
],
'functions' => [
[
'name' => 'about_ip',
'description' => 'Get information about the IP address',
'parameters' => [
'type' => 'object',
'properties' => [
'ip' => [
'type' => 'string',
'description' => 'IP address v4',
],
],
'required' => ['ip'],
],
],
],
]);
// Теперь у нас есть предложение вызвать функцию с нашей стороны и есть аргументы:
$name = $response->choices[0]->message->functionCall->name; // about_ip
$arguments = $response->choices[0]->message->functionCall->arguments; // {\n "ip": "12.175.87.227" }
}
}
Теперь у нас есть подготовленные данные, такие как название функции для вызова и ее аргументы. Я считаю, что отличным решением для выполнения подобных задач является использование пакета Sajya, который упрощает работу с JSON-RPC как в консоли, так и в виде API.
Поэтому давайте создадим простой класс, используя этот пакет:
php artisan make:procedure AboutIp
Теперь давайте добавим в нее полезное действие:
namespace App\Http\Procedures;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Sajya\Server\Procedure;
class AboutIp extends Procedure
{
/**
* The name of the procedure that is used for referencing.
*
* @var string
*/
public static string $name = 'about';
/**
* Execute the procedure.
*
* @param string $ip
* @return Collection
*/
public function ip(string $ip): Collection
{
return Http::get('http://ip-api.com/json/' . $ip)->collect();
}
}
Эта процедура “about_ip” будет просто принимать IP-адрес, получать информацию из другого API и возвращать ее пользователю.
Давайте вернемся к команде консоли и добавим метод для создания и вызова удаленного вызова процедур (RPC):
protected function callRPC(string $method, ?string $params = null): ?string
{
$app = new App([
\App\Http\Procedures\AboutIp::class,
], '_');
$response = $app->terminate(json_encode([
'jsonrpc' => '2.0',
'method' => $method,
'params' => json_decode($params, true),
'id' => 1,
]));
return json_encode($response, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
Если мы просто вызовем процедуру по ее имени и аргументам, мы не получим человеческий ответ. Для этого нам потребуется обратиться к ChatGPT:
public function handle()
{
$client = \OpenAI::factory()
->withApiKey(config('openai.api_key'))
->make();
$response = $client->chat()->create([
'model' => 'gpt-3.5-turbo-0613',
'messages' => [
[
'role' => 'user',
'content' => 'What do you know about IP 12.175.87.227 ?',
],
],
'functions' => [
[
'name' => 'about_ip',
'description' => 'Get information about the IP address',
'parameters' => [
'type' => 'object',
'properties' => [
'ip' => [
'type' => 'string',
'description' => 'IP address v4',
],
],
'required' => ['ip'],
],
],
],
]);
// Теперь у нас есть предложение вызвать функцию с нашей стороны и есть аргументы:
$name = $response->choices[0]->message->functionCall->name; // about_ip
$arguments = $response->choices[0]->message->functionCall->arguments; // {\n "ip": "12.175.87.227" }
$functionResult = $this->callRPC($name, $arguments);
// Опять же, мы обращаемся к ChatGPT, но на этот раз мы добавляем ответ от функции:
$response = $client->chat()->create([
'model' => 'gpt-3.5-turbo-0613',
'messages' => [
['role' => 'user', 'content' => 'What do you know about IP 12.175.87.227 ?'],
['role' => 'function', 'name' => $name, 'content' => $functionResult],
],
'functions' => [
[
'name' => 'about_ip',
'description' => 'Get information about the IP address',
'parameters' => [
'type' => 'object',
'properties' => [
'ip' => [
'type' => 'string',
'description' => 'IP address v4',
],
],
'required' => ['ip'],
],
],
],
]);
$response->choices[0]->message->content;
// IP-адрес 12.175.87.227 находится в городе Сан-Диего, Калифорния, Соединенные Штаты.
// Почтовый индекс - 92110.
// Координаты широты и долготы составляют 32.7616 и -117.2058 соответственно.
// Часовой пояс этого местоположения - America/Los_Angeles.
// Интернет-провайдер (ISP) - AT&T Services, Inc.
// Организация, связанная с этим IP-адресом - Coffman Specialties.
// Номер автономной системы (AS) - AS7018 AT&T Services, Inc.
}
Теперь мы получили человеческий ответ и использовали “возможности” ChatGPT для обогащения фактической информации.