Andreas Ludvigsson

Bridging Code and Commerce

Using AI for Article Writing with Laravel and ChatGPT

Using AI for Article Writing with Laravel and ChatGPT

TLDR: This article explains how to use Laravel and ChatGPT, an AI language model developed by OpenAI, to create an “AI Article Writer.” The code provided shows how to use an Artisan Command in Laravel to automate the process of generating articles. The script uses the OpenAI library to interact with the ChatGPT API and generate an image description, an article outline, and the body of the article based on user input. The generated content is then written to a .txt file. Overall, this script simplifies the process of generating articles using AI and Laravel.

In today’s post, we’re delving into the fascinating world of AI-powered text generation, specifically focusing on how Laravel, a popular PHP framework, and ChatGPT, a state-of-the-art language model developed by OpenAI, can be combined to create an efficient “AI Article Writer”.

The code uses an Artisan Command, Artisan commands come in handy when you need to automate repetitive and complex tasks. In our context, the artisan command is used to automate the task of generating articles. When invoked, it uses OpenAI’s ChatGPT to generate an article based on the input title and description.

By defining a custom Artisan command, we essentially provide a means to trigger the entire process of article generation from the command line. This not only hugely simplifies the process; it also makes the application more robust and capable.

Lets get started!

First off, lets create a new command. I called it GenerateArticle — You do this by running php artisan make:command GenerateArticleCommand.

For our command — this is the following code<?php

namespace App\Console\Commands;

use ErrorException;
use Illuminate\Console\Command;
use OpenAI;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Illuminate\Support\Str;

class GenerateArticleCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = ‘generate:article {title} {description}’;

/**
* The console command description.
*
* @var string
*/
protected $description = ‘Generate article’;

private function callApi($client, $params, $maxRetries = 5)
{
$success = false;
$response = null;
$retries = 0;

do {
try {
$response = $client->chat()->create($params);
$success = true;
} catch (OpenAI\Exceptions\ErrorException $e) {
$retries++;
if ($retries > $maxRetries) {
$this->error(‘API call failed after maximum retries.’);
throw $e;
}
$this->error(‘API call failed. Retrying… (attempt ‘ . $retries . ‘)’);
sleep(5); // You can adjust the sleep duration if needed
}
} while (!$success);

return $response;
}

/**
* Execute the console command.
* @throws ErrorException
*/
public function handle()
{
$yourApiKey = getenv(‘OPENAPI_KEY’);
$client = OpenAI::client($yourApiKey);

$title = $this->argument(‘title’);

$description = $this->argument(‘description’);
$adPlaceholder = “<p><!– Insert Ad Here –></p>”;

// Generate main image description for the article
$response = $this->callApi($client, [
‘model’ => ‘gpt-3.5-turbo’,
‘messages’ => [
[
“role” => “user”,
“content” => “Suggest a relevant image description for the main image in the article about $title.”,
],
],
]);
$mainImageDescription = $response->choices[0]->message->content;

$response = $this->callApi($client, [
‘model’ => ‘gpt-3.5-turbo’,
‘messages’ => [
[‘role’ => ‘system’, ‘content’ => “You are a professional freelance copy writer. You are writing an article about $title with the purpose $description”],
[‘role’ => ‘user’, ‘content’ =>
“As an experienced copywriter, generate a comprehensive, SEO-optimized blog post outline for the keyword $title.
Only write the outline, no content. Also, dont include the outline for the keyword $title
Use appropriate headers and subheaders to make the outline easy to read and understand. Return it as Structured JSON data. Always follow this JSON format: {\”0\”:{\”Section Title\”:\”\”,\”Subheaders\”:{}}} “
],
],
]);

// get the generated outline from the response and explode it into sections
$outline = ”;
if (count($response->choices) > 0) {
$outline = $response->choices[0]->message->content;
}

$outline = json_decode($outline, true);

$filename = Str::slug($title) . ‘.txt’;
$file = fopen(public_path($filename), ‘w’);
fwrite($file, “<h1>$title</h1>”);
fwrite($file, “[Main Image: $mainImageDescription]”);

$writtenSubHeaders = [];
foreach ($outline as $section) {
$sectionTitle = $section[‘Section Title’];
if ($sectionTitle != $title) {
fwrite($file, “<h2>$sectionTitle</h2>”);
$this->info(“Generating $sectionTitle…”);
$subheaders = $section[‘Subheaders’];
if (empty($subheaders)) {
$this->info(“Generating paragraphs for $sectionTitle…”);
$response = $this->callApi($client, [
‘model’ => ‘gpt-3.5-turbo’,
‘messages’ => [
[‘role’ => ‘system’, ‘content’ => “You are a professional freelance copy writer. You are writing an article about $title with the purpose $description”],
[“role” => “user”,
“content” => “Write paragraphs about $sectionTitle for an article about $title with the purpose of $description. Surround the paragraphs in <p> tags.”]
],
]);

$paragraphs = $response->choices[0]->message->content;
fwrite($file, $paragraphs);
} else {
$previousContent = ”;
foreach ($subheaders as $subheader) {
$this->info(“Generating paragraphs for $subheader…”);
fwrite($file, “<h3>$subheader</h3>”);

$implodedSubHeaders = implode(‘, ‘, $writtenSubHeaders);
$response = $this->callApi($client, [
‘model’ => ‘gpt-3.5-turbo’,
‘messages’ => [
[‘role’ => ‘system’, ‘content’ => “You are a professional freelance copy writer. You are writing an article about $title with the purpose $description”],
[“role” => “user”,
“content” => “In the previous section, we discussed $previousContent Now, let’s write paragraphs about $sectionTitle $subheader for an article about $title with the purpose $description. Surround the paragraphs in <p> tags. We have already written about $implodedSubHeaders. Please make sure the content flows smoothly and doesn’t repeat the topics covered in those subheaders.”]
],
]);
$paragraphs = $response->choices[0]->message->content;
fwrite($file, $paragraphs);
$writtenSubHeaders[] = $subheader;
$previousContent = “$subheader: ” . strip_tags($paragraphs);

// Add ad placeholder

}
}
}
}

fclose($file);
}

}

So what does it do?

Namespace and Dependencies: The script declares a namespace and imports necessary modules/libraries for the script to work flawlessly. This includes the OpenAI library, Laravel’s Command interface, and others.

The Class and Its Description: The GenerateArticleCommand class extends Laravel’s Command class, which allows us to define a new console command. The $signature string is the actual command that you’ll type in the console. The $description is a brief explanation of what the command does.

Method Definitions:

  1. callApi: This method tries calling the OpenAI API, catches errors if they occur, and retries if necessary. It ensures that the API calls you make are successful.
  2. handle: This is the main method of the class and is automatically called when you run the console command. It takes two arguments, title and description, to guide the article generation process.

Inside the handle Method:

API Key and OpenAI Client: The OpenAI API key is fetched from an environment variable, and the OpenAI client is initialized, which will allow us to interact with the OpenAI API.

Image Description Generation: The code uses the OpenAI client to create a Chat model. It sends a prompt to the API, asking it to suggest a relevant image description for the article about the provided title.

Creating the Article Outline: The code then prompts the API to create an outline for the article. It sets the system role to give context that you are a professional copywriter writing an article with a specified purpose and then gives the user role prompt to generate an outline based on the article’s title.

Writing the Article: Having created an outline, the code then loops through each section and subheader in the outline to generate the article’s body. It continually checks if there’s a subheader to write about. If there’s no subheader, it prompts the API to write paragraphs about the section. If there’s a subheader, it goes through each one, making sure the content flows smoothly and doesn’t repeat the topics covered in those subheaders already.

File Writing: Finally, the code writes the generated content to a .txt file with a filename derived from the title of the article.

Conclusion: Essentially, this script is using OpenAI’s ChatGPT to generate an image description, outline, and the body of an article based on a user-given title and description. It handles the article generation process seamlessly and efficiently, making the task of creating multiple articles from the command line a lot easier.

To run the command — You simply type php artisan generate:article “title” “description” and tada — you will have an AI-written article that is HTML-formatted.

Leave a Reply

Your email address will not be published. Required fields are marked *