primary_keyword_type; if ($primary_keyword_type == 'action') { $meme_media = self::getMemeMediaByKeywords($meme->action_keywords, $tolerance, 'action_keywords'); if (is_null($meme_media)) { $keywords = array_merge($meme->emotion_keywords, $meme->misc_keywords, $meme->keywords); $meme_media = self::getMemeMediaByKeywords($keywords, $tolerance); } } else if ($primary_keyword_type == 'emotion') { $meme_media = self::getMemeMediaByKeywords($meme->emotion_keywords, $tolerance, 'emotion_keywords'); if (is_null($meme_media)) { $keywords = array_merge($meme->action_keywords, $meme->misc_keywords, $meme->keywords); $meme_media = self::getMemeMediaByKeywords($keywords, $tolerance); } } else if ($primary_keyword_type == 'misc') { $meme_media = self::getMemeMediaByKeywords($meme->misc_keywords, $tolerance, 'misc_keywords'); if (is_null($meme_media)) { $keywords = array_merge($meme->action_keywords, $meme->emotion_keywords, $meme->keywords); $meme_media = self::getMemeMediaByKeywords($keywords, $tolerance); } } if (is_null($meme_media)) { $meme_media = MemeMedia::query()->inRandomOrder()->first(); } return $meme_media; } public static function generateMemeByCategory(Category $category) { $meme_output = self::generateMemeOutputByCategory($category); $meme = null; if ($meme_output->success) { $meme = Meme::create([ 'type' => self::TYPE_SINGLE_CAPTION_MEME_BACKGROUND, 'prompt' => $meme_output->prompt, 'category_id' => $category->id, 'caption' => $meme_output->caption, 'meme_keywords' => $meme_output->keywords, 'background' => $meme_output->background, 'keywords' => $meme_output->keywords, 'is_system' => true, 'status' => self::STATUS_PENDING, 'primary_keyword_type' => $meme_output->primary_keyword_type, 'action_keywords' => $meme_output->action_keywords, 'emotion_keywords' => $meme_output->emotion_keywords, 'misc_keywords' => $meme_output->misc_keywords, ]); $meme->attachTags($meme_output->keywords, 'meme'); } if (! is_null($meme) && $meme->status == self::STATUS_PENDING) { // populate meme_id $meme->meme_id = self::getSuitableMemeMedia($meme)->id; $meme->background_id = self::generateBackgroundMediaWithRunware($meme_output->background)->id; if ( //!is_null($meme->meme_id) && ! is_null($meme->background_id) ) { $meme->status = self::STATUS_COMPLETED; } $meme->save(); } return $meme; } public static function generateMemeOutputByCategory(Category $category) { $retries = 3; $attempt = 0; $random_keyword = Str::lower($category->name); if (! is_null($category->parent_id)) { $random_keyword = $category->parent->name . ' - ' . $random_keyword; } if (! is_null($category->meme_angles)) { $random_keyword .= ' - ' . collect($category->meme_angles)->random(); } elseif (! is_null($category->keywords)) { $random_keyword .= ' - ' . collect($category->keywords)->random(); } $prompt = "Write me 1 meme about {$random_keyword}"; // RETRY MECHANISM START do { $attempt++; $meme_response = OpenAI::getSingleMemeGenerator($prompt); $meme_output = json_decode(OpenAI::getOpenAIOutput($meme_response)); $output_is_valid = false; if (! is_null($meme_output)) { if ( isset($meme_output->caption) && isset($meme_output->background) && isset($meme_output->keywords) && isset($meme_output->primary_keyword_type) && isset($meme_output->action_keywords) && isset($meme_output->emotion_keywords) ) { $output_is_valid = true; } } // If output is valid or we've exhausted all retries, break the loop if ($output_is_valid || $attempt >= $retries) { break; } // Optional: Add a small delay between retries to avoid rate limiting // sleep(1); } while ($attempt < $retries); // RETRY MECHANISM END if ($output_is_valid) { $meme_output->success = true; $meme_output->prompt = $prompt; $meme_output->category = $category; $meme_output->attempts = $attempt; // Optional: track how many attempts it took } else { $meme_output = (object) [ 'success' => false, 'attempts' => $attempt, // Optional: track how many attempts were made 'error' => 'Failed to generate valid meme after ' . $retries . ' attempts', ]; } return $meme_output; } public static function generateBackgroundMediaWithRunware($prompt) { $media_width = 1024; $media_height = 1024; $aspect_ratio = AspectRatio::get($media_width, $media_height); $runware_output_url = RunwareAI::generateSchnellImage(Str::uuid(), $prompt, $media_width, $media_height); $media = MediaEngine::addMedia( 'system-i', 'image', 'system_uploaded', 'replicate', null, $runware_output_url, 'download' ); $background_media = BackgroundMedia::create([ 'media_uuid' => $media->uuid, 'media_url' => MediaEngine::getMediaCloudUrl($media), 'prompt' => $prompt, 'status' => 'completed', 'aspect_ratio' => $aspect_ratio, 'media_width' => $media_width, 'media_height' => $media_height, ]); return $background_media; } public static function getMemeMediaByKeywords(array $keywords, int $tolerance = 10, ?string $tag = null) { $meme_embedding = CloudflareAI::getVectorEmbeddingBgeSmall(implode(' ', $keywords)); $meme_medias = MemeMediaEmbedding::query() ->when(!is_empty($tag), function ($query) use ($tag) { return $query->where('tag', $tag); }) ->nearestNeighbors('embedding', $meme_embedding, Distance::L2) ->take($tolerance) ->get(); if ($meme_medias->count() > 0) { $meme_media = $meme_medias->random()->meme_media; } return $meme_media; } }