Files
futurewalker/app/Jobs/Tasks/WriteWithAITask.php

141 lines
4.4 KiB
PHP

<?php
namespace App\Jobs\Tasks;
use App\Helpers\FirstParty\OpenAI\OpenAI;
use App\Jobs\FillPostMetadataJob;
use App\Models\Post;
use App\Models\SerpUrl;
use App\Models\SerpUrlResearch;
use App\Models\ServiceCostUsage;
use Exception;
use Mis3085\Tiktoken\Facades\Tiktoken;
class WriteWithAITask
{
public static function handle(int $serp_url_id)
{
$serp_url = SerpUrl::find($serp_url_id);
if (is_null($serp_url)) {
return;
}
$serp_url_researches = SerpUrlResearch::where('serp_url_id', $serp_url->id)->where('content', '!=', 'EMPTY CONTENT')->whereNotNull('content')->get();
$user_prompt = '';
$total_tokens = 0;
foreach ($serp_url_researches as $serp_url_research) {
$sentences = self::markdownToSentences($serp_url_research->content);
//dump($sentences);
foreach ($sentences as $key => $sentence) {
if ($key == 0) {
$user_prompt .= "ARTICLE:\n";
}
$current_tokens = Tiktoken::count($sentence);
if ($current_tokens + $total_tokens > 4096) {
break 2;
} else {
$user_prompt .= $sentence."\n";
$total_tokens += $current_tokens;
}
}
$user_prompt .= "\n\n";
}
//dd($user_prompt);
$ai_writeup_response = OpenAI::writeArticle($user_prompt, 1536, 30);
//dd($ai_writeup_response);
if ((isset($ai_writeup_response->output)) && (! is_empty($ai_writeup_response->output))) {
$output = self::extractRemoveFirstHeading($ai_writeup_response->output);
$service_cost_usage = new ServiceCostUsage;
$service_cost_usage->cost = $ai_writeup_response->cost;
$service_cost_usage->name = 'openai-writeArticle';
$service_cost_usage->reference_1 = 'serp_url';
$service_cost_usage->reference_2 = strval($serp_url->id);
$service_cost_usage->output = $ai_writeup_response;
$service_cost_usage->save();
$post = Post::where('serp_url_id', $serp_url->id)->first();
if (is_null($post)) {
$post = new Post;
$post->serp_url_id = $serp_url->id;
}
if (! is_empty($output->title)) {
$post->title = $output->title;
} else {
if (! is_null($serp_url->suggestion_data)) {
if (isset($serp_url->suggestion_data->article_headings)) {
if (count($serp_url->suggestion_data->article_headings) > 0) {
$post->title = $serp_url->suggestion_data?->article_headings[0];
}
}
}
}
if (is_empty($post->title)) {
$post->title = $serp_url->title;
}
$post->slug = str_slug($post->title);
$post->body = $output->content;
$post->bites = null;
$post->metadata = null;
if ($post->save()) {
FillPostMetadataJob::dispatch($post->id)->onQueue('default')->onConnection('default');
}
} else {
throw new Exception('OpenAI failed to write');
}
}
private static function markdownToSentences($markdownContent)
{
// Split the content on punctuation followed by a space or end of string
$pattern = '/(?<=[.!?])\s+|\z/';
// Split the content into sentences
$sentences = preg_split($pattern, $markdownContent, -1, PREG_SPLIT_NO_EMPTY);
// Return the array of sentences
return $sentences;
}
private static function extractRemoveFirstHeading($markdownContent)
{
// Pattern to match the first markdown heading of any level
$pattern = '/^(#+)\s*(.+)$/m';
// Try to find the first heading
if (preg_match($pattern, $markdownContent, $matches)) {
$title = $matches[2]; // The first heading becomes the title
// Remove the first heading from the content
$updatedContent = preg_replace($pattern, '', $markdownContent, 1);
return (object) ['title' => $title, 'content' => trim($updatedContent)];
}
// Return original content if no heading found
return (object) ['title' => '', 'content' => $markdownContent];
}
}