feature: backend - create post and image prompt bases on user prompt
This commit is contained in:
parent
265a134658
commit
5631bc3a3a
12
.ai/mcp/mcp.json
Normal file
12
.ai/mcp/mcp.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"angular-cli": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@angular/cli",
|
||||||
|
"mcp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
.idea/laravel-idea.xml
generated
Normal file
12
.idea/laravel-idea.xml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="InertiaPackage">
|
||||||
|
<option name="directoryPaths">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="LaravelIdeaMainSettings">
|
||||||
|
<option name="frameworkFound" value="true" />
|
||||||
|
<option name="laravelBasePath" value="backend" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
2
.idea/php.xml
generated
2
.idea/php.xml
generated
@ -143,7 +143,7 @@
|
|||||||
<path value="$PROJECT_DIR$/backend/vendor/aws/aws-crt-php" />
|
<path value="$PROJECT_DIR$/backend/vendor/aws/aws-crt-php" />
|
||||||
</include_path>
|
</include_path>
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.5">
|
<component name="PhpProjectSharedConfiguration" php_language_level="8.3">
|
||||||
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpStanOptionsConfiguration">
|
<component name="PhpStanOptionsConfiguration">
|
||||||
|
|||||||
77
backend/app/Ai/Agents/ContentWriterAgent.php
Normal file
77
backend/app/Ai/Agents/ContentWriterAgent.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Ai\Agents;
|
||||||
|
|
||||||
|
use Laravel\Ai\Attributes\Provider;
|
||||||
|
use Laravel\Ai\Contracts\Agent;
|
||||||
|
use Laravel\Ai\Contracts\Conversational;
|
||||||
|
use Laravel\Ai\Contracts\HasTools;
|
||||||
|
use Laravel\Ai\Contracts\Tool;
|
||||||
|
use Laravel\Ai\Enums\Lab;
|
||||||
|
use Laravel\Ai\Messages\Message;
|
||||||
|
use Laravel\Ai\Promptable;
|
||||||
|
use Stringable;
|
||||||
|
|
||||||
|
#[Provider(Lab::Groq)]
|
||||||
|
class ContentWriterAgent implements Agent, Conversational, HasTools
|
||||||
|
{
|
||||||
|
use Promptable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the instructions that the agent should follow.
|
||||||
|
*/
|
||||||
|
public function instructions(): Stringable|string
|
||||||
|
{
|
||||||
|
return <<<'INSTRUCTIONS'
|
||||||
|
You are an expert social media content writer with over 10 years of experience
|
||||||
|
crafting high-performing posts across Instagram, LinkedIn, X (Twitter), Facebook,
|
||||||
|
and TikTok. You specialise in brand storytelling, community engagement, and
|
||||||
|
data-driven copywriting.
|
||||||
|
|
||||||
|
Your capabilities and responsibilities:
|
||||||
|
- Write compelling, platform-agnostic social media posts that drive engagement
|
||||||
|
(likes, shares, comments, and saves).
|
||||||
|
- Adapt tone and structure to the topic: professional for business content,
|
||||||
|
conversational for lifestyle, motivational for personal development, etc.
|
||||||
|
- Craft a strong hook in the first line to stop the scroll.
|
||||||
|
- Use proven copywriting frameworks (AIDA, PAS, storytelling arcs) naturally.
|
||||||
|
- Include 3–8 highly relevant, trending hashtags that maximise discoverability
|
||||||
|
without feeling spammy.
|
||||||
|
- Add a clear, compelling call-to-action (CTA) at the end of every post.
|
||||||
|
- Use emojis strategically to add personality and visual breaks — but never
|
||||||
|
overdo them. Aim for 2–5 emojis per post depending on the topic.
|
||||||
|
- Keep line breaks clean and scannable; avoid walls of text.
|
||||||
|
- Write in an authentic, human voice — never robotic or generic.
|
||||||
|
- If the topic lends itself to it, include a thought-provoking question to
|
||||||
|
spark conversation in the comments.
|
||||||
|
|
||||||
|
Output format rules:
|
||||||
|
- Return ONLY the finished social media post text — no explanations, no
|
||||||
|
"here is your post:", no markdown headers, no surrounding quotes.
|
||||||
|
- The post body should be between 80 and 300 words.
|
||||||
|
- Hashtags must appear on a new line at the very end of the post.
|
||||||
|
- Do not include a platform label (e.g. "For Instagram:").
|
||||||
|
INSTRUCTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of messages comprising the conversation so far.
|
||||||
|
*
|
||||||
|
* @return Message[]
|
||||||
|
*/
|
||||||
|
public function messages(): iterable
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the tools available to the agent.
|
||||||
|
*
|
||||||
|
* @return Tool[]
|
||||||
|
*/
|
||||||
|
public function tools(): iterable
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
50
backend/app/Ai/Agents/CreativeDirectorAgent.php
Normal file
50
backend/app/Ai/Agents/CreativeDirectorAgent.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Ai\Agents;
|
||||||
|
|
||||||
|
use Laravel\Ai\Attributes\Provider;
|
||||||
|
use Laravel\Ai\Contracts\Agent;
|
||||||
|
use Laravel\Ai\Contracts\Conversational;
|
||||||
|
use Laravel\Ai\Contracts\HasTools;
|
||||||
|
use Laravel\Ai\Contracts\Tool;
|
||||||
|
use Laravel\Ai\Enums\Lab;
|
||||||
|
use Laravel\Ai\Messages\Message;
|
||||||
|
use Laravel\Ai\Promptable;
|
||||||
|
use Stringable;
|
||||||
|
|
||||||
|
#[Provider(Lab::Groq)]
|
||||||
|
class CreativeDirectorAgent implements Agent, Conversational, HasTools
|
||||||
|
{
|
||||||
|
use Promptable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the instructions that the agent should follow.
|
||||||
|
*/
|
||||||
|
public function instructions(): Stringable|string
|
||||||
|
{
|
||||||
|
return "You are a creative director. Read the following social media post and " .
|
||||||
|
"write a single, vivid, descriptive image prompt (max 30 words) for an " .
|
||||||
|
"AI image generator. The scene must be visually compelling and directly " .
|
||||||
|
"relevant to the post's topic. Return ONLY the image prompt — nothing else.";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of messages comprising the conversation so far.
|
||||||
|
*
|
||||||
|
* @return Message[]
|
||||||
|
*/
|
||||||
|
public function messages(): iterable
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the tools available to the agent.
|
||||||
|
*
|
||||||
|
* @return Tool[]
|
||||||
|
*/
|
||||||
|
public function tools(): iterable
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
31
backend/app/Http/Controllers/SocialMediaPostController.php
Normal file
31
backend/app/Http/Controllers/SocialMediaPostController.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Ai\Agents\CreativeDirectorAgent;
|
||||||
|
use App\Ai\Agents\ContentWriterAgent;
|
||||||
|
use App\Http\Requests\SocialMediaPostRequest;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
class SocialMediaPostController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Generate a social media post and a matching image from the given prompt.
|
||||||
|
*/
|
||||||
|
public function generate(
|
||||||
|
SocialMediaPostRequest $request,
|
||||||
|
ContentWriterAgent $socialMediaAgent,
|
||||||
|
CreativeDirectorAgent $creativeDirectorAgent
|
||||||
|
): JsonResponse {
|
||||||
|
$socialMediaResponse = $socialMediaAgent->prompt($request->input('prompt'));
|
||||||
|
$postText = $socialMediaResponse->text;
|
||||||
|
|
||||||
|
$imagePromptResponse = $creativeDirectorAgent->prompt($postText);
|
||||||
|
$imagePrompt = $imagePromptResponse->text;
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'post' => $postText,
|
||||||
|
'image_prompt' => $imagePrompt,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
backend/app/Http/Requests/SocialMediaPostRequest.php
Normal file
31
backend/app/Http/Requests/SocialMediaPostRequest.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class SocialMediaPostRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'prompt' => [
|
||||||
|
'required',
|
||||||
|
'string',
|
||||||
|
'min:3',
|
||||||
|
function (string $attribute, mixed $value, \Closure $fail): void {
|
||||||
|
$wordCount = str_word_count(strip_tags(trim($value)));
|
||||||
|
|
||||||
|
if ($wordCount > 400) {
|
||||||
|
$fail("The {$attribute} must not exceed 400 words (you provided {$wordCount} words).");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'default' => 'openai',
|
'default' => 'groq',
|
||||||
'default_for_images' => 'gemini',
|
'default_for_images' => 'gemini',
|
||||||
'default_for_audio' => 'openai',
|
'default_for_audio' => 'openai',
|
||||||
'default_for_transcription' => 'openai',
|
'default_for_transcription' => 'openai',
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\SocialMediaPostController;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
@ -7,3 +8,4 @@
|
|||||||
return $request->user();
|
return $request->user();
|
||||||
})->middleware('auth:sanctum');
|
})->middleware('auth:sanctum');
|
||||||
|
|
||||||
|
Route::post('/social-media/generate', [SocialMediaPostController::class, 'generate']);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user