parameter für Modelle eingeführt, Beschreibung aktualisiert

This commit is contained in:
2025-08-06 09:08:07 +02:00
parent 4a45738b9b
commit 57f3dbc402
16 changed files with 581 additions and 34 deletions

View File

@@ -11,5 +11,5 @@ interface ApiPluginInterface
public function disable(): bool;
public function getStatus(string $imageUUID): array;
public function getProgress(string $imageUUID): array;
public function processImageStyleChange(string $imagePath, string $prompt, string $modelId, ?string $parameters = null): array;
public function processImageStyleChange(\App\Models\Image $image, \App\Models\Style $style): array;
}

View File

@@ -82,16 +82,16 @@ class ComfyUi implements ApiPluginInterface
return $response->json();
}
public function processImageStyleChange(string $imagePath, string $prompt, string $modelId, ?string $parameters = null): array
public function processImageStyleChange(\App\Models\Image $image, \App\Models\Style $style): array
{
$this->logInfo('Starting ComfyUI style change process.', ['image_path' => $imagePath]);
$this->logInfo('Starting ComfyUI style change process.', ['image_id' => $image->id, 'style_id' => $style->id]);
// 1. Upload image to ComfyUI
$uploadResponse = $this->uploadImage($imagePath);
$uploadResponse = $this->uploadImage(public_path('storage/' . $image->path));
$filename = $uploadResponse['name'];
// 2. Construct the prompt
$promptData = $this->constructPrompt($prompt, $filename, $modelId, $parameters);
$promptData = $this->constructPrompt($style, $filename);
// 3. Queue the prompt
$queueResponse = $this->queuePrompt($promptData);
@@ -119,18 +119,39 @@ class ComfyUi implements ApiPluginInterface
return $response->json();
}
private function constructPrompt(string $prompt, string $filename, string $modelId, ?string $parameters): array
private function constructPrompt(\App\Models\Style $style, string $filename): array
{
if (empty($parameters)) {
$modelParams = $style->aiModel->parameters ?? [];
$styleParams = $style->parameters ?? [];
if (empty($modelParams) && empty($styleParams)) {
throw new \Exception('ComfyUI workflow (parameters) is missing.');
}
$workflow = $parameters;
$workflow = str_replace('__PROMPT__', $prompt, $workflow);
$workflow = str_replace('__FILENAME__', $filename, $workflow);
$workflow = str_replace('__MODEL_ID__', $modelId, $workflow);
// Use array_replace_recursive for a deep merge
$mergedParams = array_replace_recursive($modelParams, $styleParams);
$workflow = json_encode($mergedParams);
return json_decode($workflow, true);
// Properly escape the values for JSON injection
$prompt = substr(json_encode($style->prompt, JSON_UNESCAPED_SLASHES), 1, -1);
$filename_escaped = substr(json_encode($filename, JSON_UNESCAPED_SLASHES), 1, -1);
$modelId_escaped = substr(json_encode($style->aiModel->model_id, JSON_UNESCAPED_SLASHES), 1, -1);
$workflow = str_replace('__PROMPT__', $prompt, $workflow);
$workflow = str_replace('__FILENAME__', $filename_escaped, $workflow);
$workflow = str_replace('__MODEL_ID__', $modelId_escaped, $workflow);
$decodedWorkflow = json_decode($workflow, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->logError('Failed to decode workflow JSON after placeholder replacement.', [
'json_error' => json_last_error_msg(),
'workflow_string' => $workflow
]);
throw new \Exception('Failed to construct valid ComfyUI workflow JSON: ' . json_last_error_msg());
}
return $decodedWorkflow;
}
private function queuePrompt(array $promptData): array

View File

@@ -71,10 +71,10 @@ class RunwareAi implements ApiPluginInterface
return ['progress' => 0];
}
public function processImageStyleChange(string $imagePath, string $prompt, string $modelId, ?string $parameters = null): array
public function processImageStyleChange(\App\Models\Image $image, \App\Models\Style $style): array
{
// Step 1: Upload the original image
$uploadResult = $this->upload($imagePath);
$uploadResult = $this->upload(public_path('storage/' . $image->path));
if (!isset($uploadResult['data'][0]['imageUUID'])) {
throw new \Exception('Image upload to AI service failed or returned no UUID.');
@@ -82,7 +82,7 @@ class RunwareAi implements ApiPluginInterface
$seedImageUUID = $uploadResult['data'][0]['imageUUID'];
// Step 2: Request style change using the uploaded image's UUID
$result = $this->styleChangeRequest($prompt, $seedImageUUID, $modelId, $parameters);
$result = $this->styleChangeRequest($style, $seedImageUUID);
if (!isset($result['base64Data'])) {
throw new \Exception('AI service did not return base64 image data.');
@@ -127,9 +127,9 @@ class RunwareAi implements ApiPluginInterface
}
}
private function styleChangeRequest(string $prompt, string $seedImageUUID, string $modelId, ?string $parameters = null): array
private function styleChangeRequest(\App\Models\Style $style, string $seedImageUUID): array
{
$this->logInfo('Attempting style change request to RunwareAI.', ['prompt' => $prompt, 'seed_image_uuid' => $seedImageUUID]);
$this->logInfo('Attempting style change request to RunwareAI.', ['style_id' => $style->id, 'seed_image_uuid' => $seedImageUUID]);
if (!$this->apiProvider->api_url || !$this->apiProvider->token) {
$this->logError('RunwareAI API URL or Token not configured for style change.', ['provider_name' => $this->apiProvider->name]);
throw new \Exception('RunwareAI API URL or Token not configured.');
@@ -139,17 +139,20 @@ class RunwareAi implements ApiPluginInterface
$token = $this->apiProvider->token;
$taskUUID = (string) Str::uuid();
$modelParams = $style->aiModel->parameters ?? [];
$styleParams = $style->parameters ?? [];
$mergedParams = array_replace_recursive($modelParams, $styleParams);
$data = [
'taskType' => 'imageInference',
'taskUUID' => $taskUUID,
'positivePrompt' => $prompt,
'positivePrompt' => $style->prompt,
'seedImage' => $seedImageUUID,
'outputType' => 'base64Data',
'model' => $modelId,
'model' => $style->aiModel->model_id,
];
$decodedParameters = json_decode($parameters, true) ?? [];
foreach ($decodedParameters as $key => $value) {
foreach ($mergedParams as $key => $value) {
$data[$key] = $value;
}

View File

@@ -47,6 +47,13 @@ class AiModelResource extends Resource
->preload()
->searchable(false)
->label(__('filament.resource.ai_model.form.api_providers')),
Forms\Components\Textarea::make('parameters')
->label(__('filament.resource.ai_model.form.parameters'))
->nullable()
->rows(15)
->json()
->helperText(__('filament.resource.ai_model.form.parameters_help'))
->formatStateUsing(fn (?array $state): ?string => $state ? json_encode($state, JSON_PRETTY_PRINT) : null),
]);
}

View File

@@ -56,7 +56,8 @@ class StyleResource extends Resource
->nullable()
->rows(15)
->json()
->helperText(__('filament.resource.style.form.parameters_help')),
->helperText(__('filament.resource.style.form.parameters_help'))
->formatStateUsing(fn (?array $state): ?string => $state ? json_encode($state, JSON_PRETTY_PRINT) : null),
Select::make('ai_model_id')
->relationship('aiModel', 'name')
->label(__('filament.resource.style.form.ai_model'))

View File

@@ -154,12 +154,7 @@ class ImageController extends Controller
}
$plugin = PluginLoader::getPlugin($apiProvider->plugin, $apiProvider);
$result = $plugin->processImageStyleChange(
public_path('storage/' . $image->path),
$style->prompt,
$style->aiModel->model_id,
$style->parameters
);
$result = $plugin->processImageStyleChange($image, $style);
// Update the image model with the ComfyUI prompt_id and style_id
$image->comfyui_prompt_id = $result['prompt_id'];

View File

@@ -13,6 +13,11 @@ class AiModel extends Model
'name',
'model_id',
'model_type',
'parameters',
];
protected $casts = [
'parameters' => 'array',
];
public function apiProviders()

View File

@@ -21,6 +21,7 @@ class Style extends Model
protected $casts = [
'enabled' => 'boolean',
'parameters' => 'array',
];
public function aiModel()