承接 outl1ne/nova-openai 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

outl1ne/nova-openai

Composer 安装命令:

composer require outl1ne/nova-openai

包简介

OpenAI SDK for a Laravel application that also stores OpenAI communication and presents it in a Laravel Nova admin panel.

README 文档

README

OpenAI SDK for a Laravel application that also stores OpenAI communication and presents it in a Laravel Nova admin panel.

This is currently an unstable package, breaking changes are to be expected. The main objective at the moment is to make it easier to include it as a dependency in our own client projects. This way we can make it more mature and have a v1 release when we feel it suits our needs in practice. This is why we haven't implemented all OpenAI endpoints yet and will add them one-by-one when they are actually needed.

If you need any features to be implemented or bump its priority in our backlog then feel free to make an inquiry via email at info@outl1ne.com.

Screenshots

Screenshot

Requirements

  • php: >=8.1
  • laravel/nova: ^4.0

Installation

# Install nova-openai
composer require outl1ne/nova-openai

# Run migrations
php artisan migrate

# Publish config file (optional)
php artisan vendor:publish --tag=nova-openai-config

Register the tool with Nova in the tools() method of the NovaServiceProvider:

// in app/Providers/NovaServiceProvider.php

public function tools()
{
    return [
        \Outl1ne\NovaOpenAI\NovaOpenAI::make(),
    ];
}

Usage

Assistants

$assistant = OpenAI::assistants()->create(
  'gpt-3.5-turbo',
  'Allan\'s assistant',
  'For testing purposes of nova-openai package.',
  'You are a kindergarten teacher. When asked a questions, anwser shortly and as a young child could understand.'
);
$assistantModified = OpenAI::assistants()->modify($assistant->id, null, 'Allan\'s assistant!');
$deletedAssistant = OpenAI::assistants()->delete($assistant->id);
// dd($assistant->response->json(), $assistantModified->response->json(), $deletedAssistant->response->json());

Attaching, listing and deleting files.

$assistant = OpenAI::assistants()->create(
    'gpt-3.5-turbo',
    'Allan\'s assistant',
    'For testing purposes of nova-openai package.',
    'You are a kindergarten teacher. When asked a questions, anwser shortly and as a young child could understand.',
    [
        [
            'type' => 'retrieval',
        ],
    ],
);
$file = OpenAI::files()->upload(
    file_get_contents('files/file.txt'),
    'file.txt',
    'assistants',
);
$assistantFile = OpenAI::assistants()->files()->create($assistant->id, $file->id);
$assistantFiles = OpenAI::assistants()->files()->list($assistant->id);
$deletedAssistantFile = OpenAI::assistants()->files()->delete($assistant->id, $file->id);

// Cleanup
$deletedAssistant = OpenAI::assistants()->delete($assistant->id);
$deletedFile = OpenAI::files()->delete($file->id);
// dd(
//     $assistantFile->response->json(),
//     $assistantFiles->response->json(),
//     $deletedAssistantFile->response->json(),
// );

Chat

$response = OpenAI::chat()->create(
    model: 'gpt-3.5-turbo',
    messages: Messages::make()->system('You are a helpful assistant.')->user('Hello!'),
)->json();

Enable JSON response formatting:

$response = OpenAI::chat()->create(
    model: 'gpt-3.5-turbo',
    messages: Messages::make()->system('You are a helpful assistant.')->user('Suggest me tasty fruits as JSON array of fruits.'),
    responseFormat: ResponseFormat::make()->json(),
)->json();

JSON Structured Outputs example:

$response = OpenAI::chat()->create(
    model: 'gpt-4o-mini',
    messages: Messages::make()->system('You are a helpful assistant.')->user('Suggest me 10 tasty fruits.'),
    responseFormat: ResponseFormat::make()->jsonSchema(
        JsonObject::make()
            ->property('fruits', JsonArray::make()->items(JsonString::make()))
            ->property('number_of_fruits_in_response', JsonInteger::make())
            ->property('number_of_fruits_in_response_divided_by_three', JsonNumber::make())
            ->property('is_number_of_fruits_in_response_even', JsonBoolean::make())
            ->property('fruit_most_occurring_color', JsonEnum::make()->enums(['red', 'green', 'blue']))
            ->property(
                'random_integer_or_string_max_one_character',
                JsonAnyOf::make()
                    ->schema(JsonInteger::make())
                    ->schema(JsonString::make())
            ),
    ),
)->json();

With raw JSON schema:

$response = OpenAI::chat()->create(
    model: 'gpt-4o-mini',
    messages: Messages::make()->system('You are a helpful assistant.')->user('Suggest me tasty fruits.'),
    responseFormat: ResponseFormat::make()->jsonSchema([
        'name' => 'response',
        'strict' => true,
        'schema' => [
            'type' => 'object',
            'properties' => [
                'fruits' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'string',
                    ],
                ],
            ],
            'additionalProperties' => false,
            'required' => ['fruits'],
        ],
    ]),
)->json();

Streaming

$response = OpenAI::chat()->stream(function (string $newChunk, string $message) {
    echo $newChunk;
})->create(
    model: 'gpt-3.5-turbo',
    messages: Messages::make()->system('You are a helpful assistant.')->user('Hello!'),
);

Embeddings

$response = OpenAI::embeddings()->create(
    'text-embedding-3-small',
    'The food was delicious and the waiter...'
);
// dd($response->embedding);

If you are storing the embedding vectors already somewhere else in your application then you might want to disable storing it within this package via passing a callback function with storing(fn ($model) => $model) method.

$response = OpenAI::embeddings()->storing(function ($model) {
    $model->output = null;
    return $model;
})->create(
    'text-embedding-3-small',
    'The food was delicious and the waiter...'
);

Files

Uploading file, retrieving it and deleting it afterwards.

$file = OpenAI::files()->upload(
    file_get_contents('files/file.txt'),
    'file.txt',
    'assistants',
);
$files = OpenAI::files()->list();
$file2 = OpenAI::files()->retrieve($file->id);
$deletedFile = OpenAI::files()->delete($file->id);
// dd($file->response->json(), $file2->response->json(), $deletedFile->response->json());

Retrieving a file content.

$fileContent = OpenAI::files()->retrieveContent($file->id);

Vector Stores

$filePath = __DIR__ . '/../test.txt';
$file = OpenAI::files()->upload(
    file_get_contents($filePath),
    basename($filePath),
    'assistants',
);

$vectorStore = OpenAI::vectorStores()->create([$file->id]);
$vectorStores = OpenAI::vectorStores()->list();
$vectorStoreRetrieved = OpenAI::vectorStores()->retrieve($vectorStore->id);
$vectorStoreModified = OpenAI::vectorStores()->modify($vectorStore->id, 'Modified vector store');
$vectorStoreDeleted = OpenAI::vectorStores()->delete($vectorStore->id);

Threads

$assistant = OpenAI::assistants()->create(
    'gpt-3.5-turbo',
    'Allan',
    'nova-openai testimiseks',
    'You are a kindergarten teacher. When asked a questions, anwser shortly and as a young child could understand.'
);
$thread = OpenAI::threads()
    ->create(Messages::make()->user('What is your purpose in one short sentence?'));
$message = OpenAI::threads()->messages()
    ->create($thread->id, ThreadMessage::user('How does AI work? Explain it in simple terms in one sentence.'));
$response = OpenAI::threads()->run()->execute($thread->id, $assistant->id)->wait()->json();

// cleanup
$deletedThread = OpenAI::threads()->delete($thread->id);
$deletedAssistant = OpenAI::assistants()->delete($assistant->id);
// dd(
//     $assistant->response->json(),
//     $thread->response->json(),
//     $message->response->json(),
//     $run->response->json(),
//     $messages->response->json(),
//     $deletedThread->response->json(),
//     $deletedAssistant->response->json(),
// );

Images

$images = OpenAI::images()->generate(
  prompt: 'Cute Otter',
  model: 'gpt-image-1',
  size: '1024x1024',
);

$edited = OpenAI::images()->edit(
  prompt: 'Add glasses to the otter',
  model: 'gpt-image-1',
  size: '1024x1024',
  image: fopen(storage_path("cute_otter.jpg"), "r"),
);

Testing

You can use the OpenAIRequest factory to create a request for testing purposes.

$mockOpenAIChat = Mockery::mock(Chat::class);
$mockOpenAIChat->shouldReceive('create')->andReturn((object) [
    'choices' => [
        [
            'message' => [
                'content' => 'Mocked response'
            ]
        ]
    ],
    'request' => OpenAIRequest::factory()->create()
]);
OpenAI::shouldReceive('chat')->andReturn($mockOpenAIChat);

Contributing

composer install
testbench workbench:build
testbench serve

outl1ne/nova-openai 适用场景与选型建议

outl1ne/nova-openai 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 4.96k 次下载、GitHub Stars 达 6, 最近一次更新时间为 2024 年 02 月 22 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「nova」 「laravel」 「openai」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 outl1ne/nova-openai 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 outl1ne/nova-openai 我们能提供哪些服务?
定制开发 / 二次开发

基于 outl1ne/nova-openai 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 4.96k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 6
  • 点击次数: 13
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 6
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-02-22