optimizations
This commit is contained in:
@@ -5,9 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Artwork;
|
||||
use App\Models\Category;
|
||||
use App\Services\Vision\ArtworkVisionImageUrl;
|
||||
use App\Services\Vision\VectorGatewayClient;
|
||||
use App\Services\Vision\VectorService;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
final class IndexArtworkVectorsCommand extends Command
|
||||
@@ -17,15 +15,16 @@ final class IndexArtworkVectorsCommand extends Command
|
||||
{--after-id=0 : Resume after this artwork id}
|
||||
{--batch=100 : Batch size per iteration}
|
||||
{--limit=0 : Maximum artworks to process in this run}
|
||||
{--embedded-only : Re-upsert only artworks that already have local embeddings}
|
||||
{--public-only : Index only public, approved, published artworks}
|
||||
{--dry-run : Preview requests without sending them}';
|
||||
|
||||
protected $description = 'Send artwork image URLs to the vector gateway for indexing';
|
||||
|
||||
public function handle(VectorGatewayClient $client, ArtworkVisionImageUrl $imageUrl): int
|
||||
public function handle(VectorService $vectors): int
|
||||
{
|
||||
$dryRun = (bool) $this->option('dry-run');
|
||||
if (! $dryRun && ! $client->isConfigured()) {
|
||||
if (! $dryRun && ! $vectors->isConfigured()) {
|
||||
$this->error('Vision vector gateway is not configured. Set VISION_VECTOR_GATEWAY_URL and VISION_VECTOR_GATEWAY_API_KEY.');
|
||||
return self::FAILURE;
|
||||
}
|
||||
@@ -36,6 +35,7 @@ final class IndexArtworkVectorsCommand extends Command
|
||||
$limit = max(0, (int) $this->option('limit'));
|
||||
$publicOnly = (bool) $this->option('public-only');
|
||||
$nextId = $startId > 0 ? $startId : max(1, $afterId + 1);
|
||||
$embeddedOnly = (bool) $this->option('embedded-only');
|
||||
|
||||
$processed = 0;
|
||||
$indexed = 0;
|
||||
@@ -52,12 +52,13 @@ final class IndexArtworkVectorsCommand extends Command
|
||||
}
|
||||
|
||||
$this->info(sprintf(
|
||||
'Starting vector index: start_id=%d after_id=%d next_id=%d batch=%d limit=%s public_only=%s dry_run=%s',
|
||||
'Starting vector index: start_id=%d after_id=%d next_id=%d batch=%d limit=%s embedded_only=%s public_only=%s dry_run=%s',
|
||||
$startId,
|
||||
$afterId,
|
||||
$nextId,
|
||||
$batch,
|
||||
$limit > 0 ? (string) $limit : 'all',
|
||||
$embeddedOnly ? 'yes' : 'no',
|
||||
$publicOnly ? 'yes' : 'no',
|
||||
$dryRun ? 'yes' : 'no'
|
||||
));
|
||||
@@ -77,6 +78,10 @@ final class IndexArtworkVectorsCommand extends Command
|
||||
->orderBy('id')
|
||||
->limit($take);
|
||||
|
||||
if ($embeddedOnly) {
|
||||
$query->whereHas('embeddings');
|
||||
}
|
||||
|
||||
if ($publicOnly) {
|
||||
$query->public()->published();
|
||||
}
|
||||
@@ -99,21 +104,21 @@ final class IndexArtworkVectorsCommand extends Command
|
||||
$lastId = (int) $artwork->id;
|
||||
$nextId = $lastId + 1;
|
||||
|
||||
$url = $imageUrl->fromArtwork($artwork);
|
||||
if ($url === null) {
|
||||
try {
|
||||
$payload = $vectors->payloadForArtwork($artwork);
|
||||
} catch (\Throwable $e) {
|
||||
$skipped++;
|
||||
$this->warn("Skipped artwork {$artwork->id}: no vision image URL could be generated.");
|
||||
$this->warn("Skipped artwork {$artwork->id}: {$e->getMessage()}");
|
||||
continue;
|
||||
}
|
||||
|
||||
$metadata = $this->metadataForArtwork($artwork);
|
||||
$this->line(sprintf(
|
||||
'Processing artwork=%d hash=%s thumb_ext=%s url=%s metadata=%s',
|
||||
(int) $artwork->id,
|
||||
(string) ($artwork->hash ?? ''),
|
||||
(string) ($artwork->thumb_ext ?? ''),
|
||||
$url,
|
||||
$this->json($metadata)
|
||||
$payload['url'],
|
||||
$this->json($payload['metadata'])
|
||||
));
|
||||
|
||||
if ($dryRun) {
|
||||
@@ -128,7 +133,7 @@ final class IndexArtworkVectorsCommand extends Command
|
||||
}
|
||||
|
||||
try {
|
||||
$client->upsertByUrl($url, (int) $artwork->id, $metadata);
|
||||
$vectors->upsertArtwork($artwork);
|
||||
$indexed++;
|
||||
$this->info(sprintf(
|
||||
'Indexed artwork %d successfully. totals: processed=%d indexed=%d skipped=%d failed=%d',
|
||||
@@ -159,26 +164,4 @@ final class IndexArtworkVectorsCommand extends Command
|
||||
|
||||
return is_string($json) ? $json : '{}';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{content_type: string, category: string, user_id: string}
|
||||
*/
|
||||
private function metadataForArtwork(Artwork $artwork): array
|
||||
{
|
||||
$category = $this->primaryCategory($artwork);
|
||||
|
||||
return [
|
||||
'content_type' => (string) ($category?->contentType?->name ?? ''),
|
||||
'category' => (string) ($category?->name ?? ''),
|
||||
'user_id' => (string) ($artwork->user_id ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
private function primaryCategory(Artwork $artwork): ?Category
|
||||
{
|
||||
/** @var Category|null $category */
|
||||
$category = $artwork->categories->sortBy('sort_order')->first();
|
||||
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user