Added command allowing to describe images with AI
This commit is contained in:
parent
13107972d4
commit
2667f3d11c
87
app/Console/Commands/Bundle/DescribeAttachments.php
Normal file
87
app/Console/Commands/Bundle/DescribeAttachments.php
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Bundle;
|
||||||
|
|
||||||
|
use App\Classes\AttachmentsManager;
|
||||||
|
use App\Classes\Bundle;
|
||||||
|
use App\Console\Commands\Bundle\Traits\ReadsBundles;
|
||||||
|
use App\Console\Commands\Bundle\Traits\SelectsDisks;
|
||||||
|
use App\Services\Ollama;
|
||||||
|
use App\Services\Translator;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Intervention\Image\Laravel\Facades\Image;
|
||||||
|
|
||||||
|
use function Laravel\Prompts\confirm;
|
||||||
|
use function Laravel\Prompts\progress;
|
||||||
|
use function Laravel\Prompts\textarea;
|
||||||
|
|
||||||
|
class DescribeAttachments extends Command
|
||||||
|
{
|
||||||
|
use ReadsBundles;
|
||||||
|
use SelectsDisks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Add description to attachments';
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->signature = 'bundle:describe-attachments
|
||||||
|
{ --r|recursive : Also upgrade sub-bundles }
|
||||||
|
{ --source-disk= : Use specified content disk - Defaults to <info>' . env('CONTENT_DISK') . '</info> }
|
||||||
|
{ path? : Path to a specific bundle to upgrade - Default to <info>/</info> }
|
||||||
|
';
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$this->selectDisk()
|
||||||
|
->selectBundles()
|
||||||
|
->perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function perform()
|
||||||
|
{
|
||||||
|
progress('Updating bundles...', $this->bundles, function (Bundle $bundle, $progress) {
|
||||||
|
$this->handleBundle($bundle, $progress);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleBundle(Bundle $bundle, $progress)
|
||||||
|
{
|
||||||
|
$attachmentsManager = $bundle->attachments(AttachmentsManager::Images);
|
||||||
|
|
||||||
|
foreach ($attachmentsManager->manager()->get('files') ?? [] as $ref => $data) {
|
||||||
|
if (!empty($data['alt'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$altSelected = false;
|
||||||
|
$fullPath = $attachmentsManager->getAttachmentFullPath($ref);
|
||||||
|
$content = $this->sourceDisk->get($fullPath);
|
||||||
|
$content = Image::read($content)->toJpeg();
|
||||||
|
$base64 = base64_encode($content);
|
||||||
|
|
||||||
|
while (!$altSelected) {
|
||||||
|
$sentence = Ollama::describeImage([$base64]);
|
||||||
|
$translated = Translator::translate($sentence);
|
||||||
|
$alt = textarea(sprintf('Image description for %s', $fullPath), '', $translated);
|
||||||
|
|
||||||
|
if (confirm('Use this text as the `alt` attribute for image?', true, 'Yes', 'No', false, null, $alt)) {
|
||||||
|
$attachmentsManager->manager()->set(sprintf('files.%s.alt', $ref), $alt);
|
||||||
|
$attachmentsManager->manager()->save();
|
||||||
|
|
||||||
|
$altSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
app/Services/Ollama.php
Normal file
24
app/Services/Ollama.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
|
class Ollama
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Provides a description for specified image(s) using the llava model
|
||||||
|
* with ollama
|
||||||
|
*/
|
||||||
|
public static function describeImage(array $base64JpegImages)
|
||||||
|
{
|
||||||
|
$result = Http::throw()->timeout(240)->post(sprintf('%s/api/generate', env('OLLAMA_HOST')), [
|
||||||
|
'model' => 'llava',
|
||||||
|
'prompt' => 'Describe this image in a sentence or two',
|
||||||
|
'stream' => false,
|
||||||
|
'images' => $base64JpegImages,
|
||||||
|
])->json();
|
||||||
|
|
||||||
|
return $result['response'];
|
||||||
|
}
|
||||||
|
}
|
22
app/Services/Translator.php
Normal file
22
app/Services/Translator.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
|
class Translator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Provides a translation for specified text
|
||||||
|
*/
|
||||||
|
public static function translate(string $sentence, ?string $sourceLang = 'en', ?string $targetLang = 'fr')
|
||||||
|
{
|
||||||
|
$response = Http::asForm()->post(sprintf('%s/translate', env('TRANSLATOR_URL')), [
|
||||||
|
'q' => $sentence,
|
||||||
|
'source' => $sourceLang,
|
||||||
|
'target' => $targetLang,
|
||||||
|
])->json();
|
||||||
|
|
||||||
|
return $response['translatedText'];
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ services:
|
||||||
- selenium
|
- selenium
|
||||||
- nu-validator
|
- nu-validator
|
||||||
- base_laravel.test
|
- base_laravel.test
|
||||||
|
- libretranslate
|
||||||
pgsql:
|
pgsql:
|
||||||
image: 'postgres:15'
|
image: 'postgres:15'
|
||||||
ports:
|
ports:
|
||||||
|
@ -88,6 +89,16 @@ services:
|
||||||
- sail
|
- sail
|
||||||
nu-validator:
|
nu-validator:
|
||||||
image: ghcr.io/validator/validator:latest
|
image: ghcr.io/validator/validator:latest
|
||||||
|
extra_hosts:
|
||||||
|
- 'host.docker.internal:host-gateway'
|
||||||
|
networks:
|
||||||
|
- sail
|
||||||
|
libretranslate:
|
||||||
|
image: libretranslate/libretranslate
|
||||||
|
extra_hosts:
|
||||||
|
- 'host.docker.internal:host-gateway'
|
||||||
|
environment:
|
||||||
|
- DBUS_SESSION_BUS_ADDRESS=/dev/null
|
||||||
networks:
|
networks:
|
||||||
- sail
|
- sail
|
||||||
networks:
|
networks:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user