Files
jobifygarden/app/Console/Commands/CurateJobs.php
T

145 lines
5.1 KiB
PHP
Raw Normal View History

2026-04-04 20:37:35 +03:00
<?php
namespace App\Console\Commands;
use App\Models\Job;
use App\Models\Tag;
use Illuminate\Console\Attributes\Description;
use Illuminate\Console\Attributes\Signature;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
#[Signature('jobs:curate {--batch=50}')]
#[Description('Curate jobs by fetching tags from an external API')]
class CurateJobs extends Command
{
2026-05-01 23:33:15 +03:00
protected $signature = 'jobs:curate {--batch=50}';
protected $description = 'Curate jobs by fetching tags from an external API';
2026-04-04 20:37:35 +03:00
/**
* Execute the console command.
*/
public function handle(): int
{
$batchSize = (int) $this->option('batch');
//$apiUrl = $this->option('api-url');
$apiUrl = 'https://olm.c0rrup7.net/api/generate';
2026-04-04 20:37:35 +03:00
if (empty($apiUrl)) {
$this->error('API URL is required. Use --api-url option to provide the endpoint.');
return self::FAILURE;
}
2026-05-02 01:40:46 +03:00
$log = Log::channel('jobs_curate');
2026-04-04 20:37:35 +03:00
$this->info('Starting job curation...');
2026-05-02 01:40:46 +03:00
$log->info('Starting job curation batch', ['batch_size' => $batchSize]);
2026-04-04 20:37:35 +03:00
$this->newLine();
// Fetch uncurated jobs
$uncuratedJobs = Job::uncurated()
->limit($batchSize)
->get();
if ($uncuratedJobs->isEmpty()) {
$this->info('No uncurated jobs found.');
return self::SUCCESS;
}
$this->info("Found {$uncuratedJobs->count()} uncurated jobs.");
$this->newLine();
$curatedCount = 0;
$failedCount = 0;
$progressBar = $this->output->createProgressBar($uncuratedJobs->count());
$progressBar->start();
foreach ($uncuratedJobs as $job) {
try {
$body = 'This is the content of a job ad, you need to read it and extract the relevant tags from it. Respond only with the tags in JSON format, NO OTHER TEXT BEFORE OR AFTER THE JSON.';
2026-04-04 20:37:35 +03:00
$body .= 'Title: '. htmlentities($job->title);
$body .= 'Description: '. htmlentities($job->description);
$body .= 'RETURN ONLY VALID JSON, NO TEXT BEFORE OR AFTER THE JSON!';
2026-04-04 20:37:35 +03:00
// Make POST request to API with job name and description
2026-05-02 01:25:32 +03:00
$response = Http::timeout(300)
2026-04-04 20:37:35 +03:00
->withHeaders([
'Accept' => 'application/json',
'CF-Access-Client-Id' => '8c4cc272c7f08f8d7911a28eb5d7db44.access',
'CF-Access-Client-Secret' => 'adeeed2f75236053953cc9dd898c7756bab5e00f7d0901bf7d488b6db8aba336',
2026-04-04 20:37:35 +03:00
])
->post($apiUrl, [
2026-05-02 02:49:38 +03:00
'model' => 'granite4.1:3b',
2026-04-04 20:37:35 +03:00
'stream' => false,
'prompt' => $body,
]);
2026-05-02 01:40:46 +03:00
2026-04-04 20:37:35 +03:00
if ($response->successful()) {
$responseArray = $response->json();
$responseTagsJson = $responseArray['response'];
2026-05-02 01:40:46 +03:00
$log->info("Curated job id: {$job->id} Result: {$responseTagsJson}");
$tags = json_decode($responseTagsJson, true);
2026-05-02 01:25:32 +03:00
if (empty($tags) || $tags === null) {
continue;
}
2026-05-02 02:49:38 +03:00
//$tags = array_flip($tags);
2026-04-04 20:37:35 +03:00
if (is_array($tags) && !empty($tags)) {
$tagIds = [];
2026-05-02 02:49:38 +03:00
if (isset($tags['tags'])) {
$tags = $tags['tags'];
}
2026-04-04 20:37:35 +03:00
foreach ($tags as $tagName) {
// Find or create tag
$tag = Tag::firstOrCreate(
['name' => $tagName]
);
$tagIds[] = $tag->id;
}
// Sync tags with the job
$job->tags()->sync($tagIds);
// Mark job as curated
$job->update(['is_curated' => true]);
$curatedCount++;
} else {
// Mark as curated even if no tags returned
$job->update(['is_curated' => true]);
$curatedCount++;
}
} else {
$failedCount++;
2026-05-02 01:40:46 +03:00
$log->warning("Failed to curate job #{$job->id}: API returned {$response->status()} -> {$response->body()}");
2026-04-04 20:37:35 +03:00
}
} catch (\Exception $e) {
$failedCount++;
2026-05-02 02:49:38 +03:00
$log->error("Error curating job #{$job->id}: {$e->getMessage()} {$e->getTraceAsString()}");
2026-04-04 20:37:35 +03:00
}
$progressBar->advance();
}
$progressBar->finish();
$this->newLine(2);
$this->info("Successfully curated {$curatedCount} jobs.");
2026-05-02 01:40:46 +03:00
$log->info("Curation complete", ['curated' => $curatedCount, 'failed' => $failedCount]);
2026-04-04 20:37:35 +03:00
if ($failedCount > 0) {
$this->warn("Failed to curate {$failedCount} jobs. Check logs for details.");
}
return self::SUCCESS;
}
}