211 lines
6.1 KiB
PHP
Executable File
211 lines
6.1 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\AiModel;
|
|
use App\Models\AiProvider;
|
|
use App\Models\PromptGeneration;
|
|
use App\Models\PromptProject;
|
|
use App\Models\User;
|
|
use App\Services\Ai\AiServiceFactory;
|
|
use App\Services\Ai\AiServiceInterface;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use Illuminate\Support\Facades\Log;
|
|
use RuntimeException;
|
|
|
|
class PromptGenerationService
|
|
{
|
|
/**
|
|
* @param AiServiceFactory $factory
|
|
*/
|
|
public function __construct(private AiServiceFactory $factory)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Generate a prompt based on a prompt project.
|
|
*
|
|
* @param array<string, mixed> $data
|
|
* @return PromptGeneration
|
|
*/
|
|
public function generate(array $data): PromptGeneration
|
|
{
|
|
$project = $data['project'] ?? null;
|
|
$user = $data['user'] ?? null;
|
|
|
|
if (!$project instanceof PromptProject) {
|
|
throw new InvalidArgumentException('Prompt project is required.');
|
|
}
|
|
|
|
if (!$user instanceof User) {
|
|
$user = auth()->user();
|
|
}
|
|
|
|
if (!$user instanceof User) {
|
|
throw new InvalidArgumentException('User is required.');
|
|
}
|
|
|
|
$provider = $data['provider_id'] ?? $project->provider_id;
|
|
$model = $data['model_id'] ?? $project->model_id;
|
|
|
|
if (!$provider instanceof AiProvider) {
|
|
$provider = AiProvider::findOrFail((int) $provider);
|
|
}
|
|
|
|
if (!$model instanceof AiModel) {
|
|
$model = AiModel::findOrFail((int) $model);
|
|
}
|
|
|
|
$promptText = $this->buildPrompt($project);
|
|
|
|
$aiData = [
|
|
'prompt' => $promptText,
|
|
'temperature' => (float) ($data['temperature'] ?? $project->temperature ?? 0.7),
|
|
'max_tokens' => (int) ($data['max_tokens'] ?? $project->max_tokens ?? 1024),
|
|
'model' => $model->slug,
|
|
'api_key' => $provider->api_key,
|
|
'base_url' => $provider->base_url,
|
|
];
|
|
|
|
$startTime = microtime(true);
|
|
|
|
try {
|
|
$service = $this->factory->make($provider);
|
|
$result = $service->generatePrompt($aiData);
|
|
} catch (GuzzleException|RuntimeException $e) {
|
|
Log::error('Prompt generation failed: ' . $e->getMessage());
|
|
|
|
return PromptGeneration::create([
|
|
'project_id' => $project->id,
|
|
'user_id' => $user->id,
|
|
'provider_id' => $provider->id,
|
|
'model_id' => $model->id,
|
|
'generated_prompt' => $promptText,
|
|
'input_data' => $aiData,
|
|
'output_data' => ['error' => $e->getMessage()],
|
|
'tokens_used' => null,
|
|
'generation_time' => round(microtime(true) - $startTime, 3),
|
|
'status' => 'failed',
|
|
]);
|
|
}
|
|
|
|
$generation = PromptGeneration::create([
|
|
'project_id' => $project->id,
|
|
'user_id' => $user->id,
|
|
'provider_id' => $provider->id,
|
|
'model_id' => $model->id,
|
|
'generated_prompt' => $promptText,
|
|
'input_data' => $aiData,
|
|
'output_data' => $result,
|
|
'tokens_used' => $result['tokens_used'] ?? null,
|
|
'generation_time' => round(microtime(true) - $startTime, 3),
|
|
'status' => 'completed',
|
|
]);
|
|
|
|
return $generation;
|
|
}
|
|
|
|
/**
|
|
* Build the prompt text from project data.
|
|
*
|
|
* @param PromptProject $project
|
|
* @return string
|
|
*/
|
|
private function buildPrompt(PromptProject $project): string
|
|
{
|
|
$parts = [];
|
|
|
|
if ($project->company_name) {
|
|
$parts[] = "Company Name: " . $project->company_name;
|
|
}
|
|
|
|
if ($project->company_address) {
|
|
$parts[] = "Company Address: " . $project->company_address;
|
|
}
|
|
|
|
if ($project->company_whatsapp) {
|
|
$parts[] = "Company WhatsApp: " . $project->company_whatsapp;
|
|
}
|
|
|
|
if ($project->company_website) {
|
|
$parts[] = "Company Website: " . $project->company_website;
|
|
}
|
|
|
|
if ($project->company_social_media) {
|
|
$parts[] = "Company Social Media: " . $project->company_social_media;
|
|
}
|
|
|
|
if ($project->company_business_activities) {
|
|
$parts[] = "Company Business Activities: " . $project->company_business_activities;
|
|
}
|
|
|
|
if ($project->company_services_products) {
|
|
$parts[] = "Company Services/Products: " . $project->company_services_products;
|
|
}
|
|
|
|
if ($project->objective) {
|
|
$parts[] = "Objective: " . $project->objective;
|
|
}
|
|
|
|
if ($project->context) {
|
|
$parts[] = "Context: " . $project->context;
|
|
}
|
|
|
|
if ($project->persona) {
|
|
$parts[] = "Persona/Role: " . $project->persona;
|
|
}
|
|
|
|
if ($project->tone) {
|
|
$parts[] = "Tone/Style: " . $project->tone;
|
|
}
|
|
|
|
if ($project->constraints) {
|
|
$parts[] = "Constraints: " . $project->constraints;
|
|
}
|
|
|
|
if ($project->output_format) {
|
|
$parts[] = "Output Format: " . $project->output_format;
|
|
}
|
|
|
|
if (!empty($project->examples)) {
|
|
$parts[] = "Examples:\n" . json_encode($project->examples, JSON_PRETTY_PRINT);
|
|
}
|
|
|
|
if (!empty($project->variables)) {
|
|
$parts[] = "Variables: " . json_encode($project->variables, JSON_PRETTY_PRINT);
|
|
}
|
|
|
|
return implode("\n\n", $parts);
|
|
}
|
|
|
|
/**
|
|
* Display a listing of prompt generations.
|
|
*
|
|
* @return \Illuminate\Contracts\Pagination\Paginator
|
|
*/
|
|
public function index(): \Illuminate\Contracts\Pagination\Paginator
|
|
{
|
|
$user = auth()->user();
|
|
|
|
$query = PromptGeneration::query()
|
|
->with(['project', 'user', 'provider', 'model'])
|
|
->latest();
|
|
|
|
if (!$user || $user->role !== 'superadmin') {
|
|
$query->where('user_id', auth()->id());
|
|
}
|
|
|
|
return $query->paginate(15);
|
|
}
|
|
|
|
/**
|
|
* Delete the specified prompt generation.
|
|
*/
|
|
public function destroy(PromptGeneration $generation): void
|
|
{
|
|
$generation->delete();
|
|
}
|
|
}
|