在 Laravel 中使用 OpenAI
发布于 作者 Steve McDougall
人工智能是炒作还是我们应该考虑的东西?随着 OpenAI 包的发布,我们可以深入研究人工智能驱动的 Laravel 应用程序
那么,OpenAI 是什么?我们可以用它做什么?这主要与自然语言处理有关。我们向它传递一些文本,它可以以许多惊人的方式回应。从完整的文本示例到代码示例,以及你需要的任何东西。主要的限制是你的想象力和它目前的能力。
Nuno 在一段时间前发布了 OpenAI PHP 客户端 - 但我们能用它做什么?我经常发现使用这项技术最具挑战性的部分是理解你能用它做什么。
浏览 OpenAI 示例时,我发现了许多对我和一般使用非常有效的示例。让我们来了解一下“从产品描述生成广告”的模型。我选择这个是因为我们经常从用户那里获取文本输入,然后出于各种原因必须输出它。想象一下,你正在运营一家在线商店,需要为你的商品获取产品描述,并且想添加一些杀手级的“广告”风格的文本来鼓励人们点击产品。
让我们开始吧。
我不会带你一步一步地完成设置 OpenAI PHP 客户端的安装过程。你阅读到这里,我假设我不需要教你这一部分。但是,我会介绍如何使用这个包,这可能与其他教程不同。
我会做的第一件事是将 OpenAI Client 类绑定到我的容器,这样我就不需要使用门面或实例化客户端。
final class AppServiceProvider extends ServiceProvider{ public function register(): void { $this->app->singleton( abstract: Client::class, concrete: fn () => OpenAI::client( apiToken: strval(config('openai.api_key')), ), ); }}
现在,无论何时尝试将 OpenAI Client 类注入构造函数或其他任何地方,它都会为我预先设置。
我们的用例是当我们保存带有描述的产品时。我们想要自动生成产品的广告文本。实际上,发生这种情况的最佳位置是 Job。我们可以在模型本身的创建过程中调度它。
我不会介绍模型的创建,因为我想确保我从本教程中获取所有要点。
当我们调度后台作业时,我们会将想要序列化的内容传递到构造函数中,然后在 handle 方法中,我们可以从 DI 容器中解析实例。
让我们看看如果我们简单地处理它会是什么样子。
final class GenerateAdFromProduct implements ShouldQueue{ use Dispatchable; use InteractsWithQueue; use Queueable; use SerializesModels; public function __construct( public readonly string $text, public readonly int $product, ) {} public function handle(Client $client): void { $response = $client->completions()->create([ 'model' => 'text-davinci-003', 'prompt' => $this->text, 'temperature' => 0.5, 'max_tokens' => 100, 'top_p' => 1.0, 'frequency_penalty' => 0.0, 'presence_penalty' => 0.0, ]); DB::transaction(fn () => Product::query()->find( id: $this->product, ))->update(['ai_description' => $response['choices'][0]['text']]); }}
这使用了示例页面中描述的设置,没有深入研究。当然,如果你在生产环境中执行此操作,我强烈建议你更仔细地查看这些设置。
我们能改进它吗?当然可以 - 我是 Steve,我有自己的想法……让我们更进一步。
我们在这里做什么?我们使用预定义的模型从 OpenAI 生成并返回响应。我们正在使用的设置是在示例中预定义的。当然,它们可以进行调整,但我们可以用它来更进一步。
我们的第一步是模型本身。OpenAI 目前只支持有限的几个可用模型 - 这可能会在某个时候改变,但现在不会。让我们为有效负载的模型部分创建一个 Enum
enum Model: string{ case ADA = 'text-ada-001'; case BABBAGE = 'text-babbage-001'; case CURIE = 'text-curie-001'; case DAVINCI = 'text-davinci-003';}
第一步完成。现在让我们看看 OpenAI 客户端请求。
$client->completions()->create([ 'model' => Model::DAVINCI->value, 'prompt' => $this->text, 'temperature' => 0.5, 'max_tokens' => 100, 'top_p' => 1.0, 'frequency_penalty' => 0.0, 'presence_penalty' => 0.0,]);
相当不错。其余设置特定于模型和结果,从我从文档中了解到的情况来看,这是我试图实现的。因此,这是有目的地设置的,以便我能够从另一个文本主体中获得广告文本。对我来说,这是一个广告转换器。它将你提供的所有提示转换为广告。因此,考虑到这一点,让我们创建一个专门的类来创建它。
final class AdvertisementTransformer{ public static function transform(string $prompt): array { return [ 'model' => Model::DAVINCI->value, 'prompt' => $prompt, 'temperature' => 0.5, 'max_tokens' => 100, 'top_p' => 1.0, 'frequency_penalty' => 0.0, 'presence_penalty' => 0.0, ]; }}
我们将创建完成的逻辑提取到一个专门的类中,这样可以让我们轻松地重复使用它。现在让我们回到 OpenAI 客户端请求
$client->completions()->create( parameters: AdvertisementTransformer::transform( prompt: $this->text, ),);
对我来说,这至少是干净且易于理解的。查看它,我正在将文本从作业传递给一个转换器,该转换器将转换为广告文本生成器所需的参数。
此操作的输出将是以下内容
{ "object": "text_completion", "created": 1672769063, "model": "text-davinci-003", "choices": [ { "text": "Are you a #Laravel developer looking to stay up-to-date with the latest news and updates? Look no further than Laravel News! With over 10K users daily, you'll be able to stay informed and learn from the official news outlet for the Laravel ecosystem. #LaravelNews #Developers #Ecosystem", "index": 0, "logprobs": null, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 82, "completion_tokens": 72, "total_tokens": 154 }}
如你所见,我们有一个 choices 数组,每个数组都包含一个 text 键。要检索它,我们只需要像往常一样在 PHP 中访问它即可
$response = $client->completions()->create( parameters: AdvertisementTransformer::transform( prompt: $this->text, ),); DB::transaction(fn () => Product::query()->find( id: $this->product,))->update(['ai_description' => $response['choices'][0]['text']]);
现在你需要做的就是创建你可能在应用程序中使用的标准转换器,将参数调整到你确信对你有用为止,你就可以继续进行其他操作了。
技术作家,就职于 Laravel News,开发倡导者,就职于 Treblle。API 专家,资深 PHP/Laravel 工程师。 YouTube 直播主.