tabelle ai_model_api_provider entfernt
This commit is contained in:
2
PRP.md
2
PRP.md
@@ -258,8 +258,6 @@ Key tables and their relevant columns:
|
||||
- `created_at`: `timestamp null`
|
||||
- `updated_at`: `timestamp null`
|
||||
|
||||
- **`ai_model_api_provider`** (Pivot table for many-to-many relationship)
|
||||
- `ai_model_id`: `bigint unsigned` (FK to `ai_models.id`)
|
||||
- `api_provider_id`: `bigint unsigned` (FK to `api_providers.id`)
|
||||
|
||||
- **`settings`**
|
||||
|
||||
@@ -12,6 +12,7 @@ interface ApiPluginInterface
|
||||
public function getStatus(string $imageUUID): array;
|
||||
public function getProgress(string $imageUUID): array;
|
||||
public function processImageStyleChange(\App\Models\Image $image, \App\Models\Style $style): array;
|
||||
public function getStyledImage(string $promptId): string;
|
||||
public function testConnection(array $data): bool;
|
||||
public function searchModels(string $searchTerm): array;
|
||||
}
|
||||
@@ -260,4 +260,9 @@ class ComfyUi implements ApiPluginInterface
|
||||
$this->logInfo('ComfyUI does not support model search. Returning empty list.', ['searchTerm' => $searchTerm]);
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getStyledImage(string $promptId): string
|
||||
{
|
||||
return $this->waitForResult($promptId);
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,11 @@ class RunwareAi implements ApiPluginInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getStyledImage(string $promptId): string
|
||||
{
|
||||
throw new \Exception('RunwareAi does not support fetching styled images by prompt ID.');
|
||||
}
|
||||
|
||||
public function getStatus(string $imageUUID): array
|
||||
{
|
||||
$this->logDebug('Getting status for image.', ['image_uuid' => $imageUUID]);
|
||||
@@ -248,7 +253,7 @@ class RunwareAi implements ApiPluginInterface
|
||||
'positivePrompt' => $style->prompt,
|
||||
'seedImage' => $seedImageUUID,
|
||||
'outputType' => 'base64Data',
|
||||
'model' => $style->aiModel->model_id,
|
||||
'model' => $style->aiModel->model_id
|
||||
];
|
||||
|
||||
foreach ($mergedParams as $key => $value) {
|
||||
|
||||
@@ -32,10 +32,9 @@ class AiModelResource extends Resource
|
||||
->schema([
|
||||
Forms\Components\Section::make()
|
||||
->schema([
|
||||
Select::make('apiProviders')
|
||||
->label(__('filament.resource.ai_model.form.api_providers'))
|
||||
->relationship('apiProviders', 'name')
|
||||
->multiple()
|
||||
Select::make('api_provider_id')
|
||||
->label(__('filament.resource.ai_model.form.api_provider'))
|
||||
->relationship('primaryApiProvider', 'name')
|
||||
->live()
|
||||
->afterStateUpdated(function (callable $set) {
|
||||
$set('model_search_result', null);
|
||||
@@ -44,24 +43,21 @@ class AiModelResource extends Resource
|
||||
->label(__('filament.resource.ai_model.form.search_model'))
|
||||
->searchable()
|
||||
->live()
|
||||
->hidden(fn (callable $get) => !static::canSearchModelsWithAnyProvider($get('apiProviders')))
|
||||
->hidden(fn (callable $get) => !static::canSearchModels($get('api_provider_id')))
|
||||
->getSearchResultsUsing(function (string $search, callable $get) {
|
||||
$apiProviderIds = $get('apiProviders');
|
||||
if (empty($apiProviderIds)) {
|
||||
$apiProviderId = $get('api_provider_id');
|
||||
if (!$apiProviderId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Try each API provider until we find one that works
|
||||
foreach ($apiProviderIds as $apiProviderId) {
|
||||
$pluginInstance = static::getPluginInstance($apiProviderId);
|
||||
if ($pluginInstance && method_exists($pluginInstance, 'searchModels')) {
|
||||
$models = $pluginInstance->searchModels($search);
|
||||
$options = [];
|
||||
foreach ($models as $model) {
|
||||
$options[json_encode(['name' => $model['name'], 'id' => $model['id'], 'type' => $model['type'] ?? null, 'api_provider_id' => $apiProviderId])] = $model['name'] . ' (' . $model['id'] . ')';
|
||||
}
|
||||
return $options;
|
||||
$pluginInstance = static::getPluginInstance($apiProviderId);
|
||||
if ($pluginInstance && method_exists($pluginInstance, 'searchModels')) {
|
||||
$models = $pluginInstance->searchModels($search);
|
||||
$options = [];
|
||||
foreach ($models as $model) {
|
||||
$options[json_encode(['name' => $model['name'], 'id' => $model['id'], 'type' => $model['type'] ?? null, 'api_provider_id' => $apiProviderId])] = $model['name'] . ' (' . $model['id'] . ')';
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
return [];
|
||||
})
|
||||
@@ -176,7 +172,7 @@ class AiModelResource extends Resource
|
||||
Tables\Columns\IconColumn::make('enabled')
|
||||
->label(__('filament.resource.ai_model.table.enabled'))
|
||||
->boolean(),
|
||||
TextColumn::make('apiProviders.name')->label(__('filament.resource.ai_model.table.api_providers'))->searchable()->sortable()->limit(50),
|
||||
TextColumn::make('primaryApiProvider.name')->label(__('filament.resource.ai_model.table.api_provider'))->searchable()->sortable()->limit(50),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
|
||||
@@ -138,23 +138,19 @@ class ImageController extends Controller
|
||||
|
||||
if ($request->style_id) {
|
||||
$style = Style::with(['aiModel' => function ($query) {
|
||||
$query->where('enabled', true)->with(['primaryApiProvider', 'apiProviders' => function ($query) {
|
||||
$query->where('enabled', true);
|
||||
}]);
|
||||
$query->where('enabled', true)->with('primaryApiProvider');
|
||||
}])->find($request->style_id);
|
||||
} else {
|
||||
// Attempt to get default style from settings
|
||||
$defaultStyleSetting = \App\Models\Setting::where('key', 'default_style_id')->first();
|
||||
if ($defaultStyleSetting && $defaultStyleSetting->value) {
|
||||
$style = Style::with(['aiModel' => function ($query) {
|
||||
$query->where('enabled', true)->with(['primaryApiProvider', 'apiProviders' => function ($query) {
|
||||
$query->where('enabled', true);
|
||||
}]);
|
||||
$query->where('enabled', true)->with('primaryApiProvider');
|
||||
}])->find($defaultStyleSetting->value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$style || !$style->aiModel || $style->aiModel->apiProviders->isEmpty()) {
|
||||
if (!$style || !$style->aiModel || !$style->aiModel->primaryApiProvider) {
|
||||
\Illuminate\Support\Facades\Log::warning('Style or provider not found', [
|
||||
'style' => $style ? $style->toArray() : null,
|
||||
'ai_model' => $style && $style->aiModel ? $style->aiModel->toArray() : null
|
||||
@@ -163,16 +159,8 @@ class ImageController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
// Use the primary API provider for this AI model if available
|
||||
// Use the primary API provider for this AI model
|
||||
$apiProvider = $style->aiModel->primaryApiProvider;
|
||||
if (!$apiProvider) {
|
||||
// Fallback to the first enabled API provider from the many-to-many relationship
|
||||
$apiProvider = $style->aiModel->apiProviders->where('enabled', true)->first();
|
||||
}
|
||||
if (!$apiProvider) {
|
||||
// If no enabled provider found, try any provider
|
||||
$apiProvider = $style->aiModel->apiProviders->first();
|
||||
}
|
||||
if (!$apiProvider) {
|
||||
\Illuminate\Support\Facades\Log::error('No API provider found for style', [
|
||||
'style_id' => $style->id,
|
||||
@@ -276,9 +264,7 @@ class ImageController extends Controller
|
||||
try {
|
||||
// Find the image associated with the prompt_id, eagerly loading relationships
|
||||
$image = Image::with(['style.aiModel' => function ($query) {
|
||||
$query->with(['primaryApiProvider', 'apiProviders' => function ($query) {
|
||||
$query->where('enabled', true);
|
||||
}]);
|
||||
$query->with('primaryApiProvider');
|
||||
}])->where('comfyui_prompt_id', $promptId)->first();
|
||||
|
||||
if (!$image) {
|
||||
@@ -302,26 +288,18 @@ class ImageController extends Controller
|
||||
}
|
||||
Log::info('fetchStyledImage: AI Model found.', ['ai_model_id' => $style->aiModel->id, 'ai_model_name' => $style->aiModel->name]);
|
||||
|
||||
if ($style->aiModel->apiProviders->isEmpty()) {
|
||||
Log::warning('fetchStyledImage: No enabled API Providers found for AI Model.', ['ai_model_id' => $style->aiModel->id]);
|
||||
return response()->json(['error' => __('api.style_or_provider_not_found')], 404);
|
||||
}
|
||||
// Use the primary API provider for this AI model if available
|
||||
// Use the primary API provider for this AI model
|
||||
$apiProvider = $style->aiModel->primaryApiProvider;
|
||||
if (!$apiProvider) {
|
||||
// Fallback to the first enabled API provider from the many-to-many relationship
|
||||
$apiProvider = $style->aiModel->apiProviders->where('enabled', true)->first();
|
||||
}
|
||||
if (!$apiProvider) {
|
||||
// If no enabled provider found, try any provider
|
||||
$apiProvider = $style->aiModel->apiProviders->first();
|
||||
Log::warning('fetchStyledImage: No API Provider found for AI Model.', ['ai_model_id' => $style->aiModel->id]);
|
||||
return response()->json(['error' => __('api.style_or_provider_not_found')], 404);
|
||||
}
|
||||
Log::info('fetchStyledImage: API Provider found.', ['api_provider_id' => $apiProvider->id, 'api_provider_name' => $apiProvider->name]);
|
||||
|
||||
Log::info('Fetching base64 image from plugin.', ['prompt_id' => $promptId, 'api_provider' => $apiProvider->name]);
|
||||
// Use the plugin to get the final image data (e.g., from ComfyUI's history/view)
|
||||
$plugin = PluginLoader::getPlugin($apiProvider->plugin, $apiProvider);
|
||||
$base64Image = $plugin->waitForResult($promptId); // Re-purpose waitForResult for final fetch
|
||||
$base64Image = $plugin->getStyledImage($promptId); // Use the new method
|
||||
|
||||
if (empty($base64Image)) {
|
||||
Log::error('Received empty base64 image from plugin.', ['prompt_id' => $promptId]);
|
||||
@@ -376,43 +354,23 @@ class ImageController extends Controller
|
||||
// If style_id is provided, get the API provider for that style
|
||||
if ($styleId) {
|
||||
$style = Style::with(['aiModel' => function ($query) {
|
||||
$query->where('enabled', true)->with(['primaryApiProvider', 'apiProviders' => function ($query) {
|
||||
$query->where('enabled', true);
|
||||
}]);
|
||||
$query->where('enabled', true)->with('primaryApiProvider');
|
||||
}])->find($styleId);
|
||||
|
||||
if ($style && $style->aiModel) {
|
||||
// Use the primary API provider for this AI model if available
|
||||
// Use the primary API provider for this AI model
|
||||
$apiProvider = $style->aiModel->primaryApiProvider;
|
||||
if (!$apiProvider) {
|
||||
// Fallback to the first enabled API provider from the many-to-many relationship
|
||||
$apiProvider = $style->aiModel->apiProviders->where('enabled', true)->first();
|
||||
}
|
||||
if (!$apiProvider) {
|
||||
// If no enabled provider found, try any provider
|
||||
$apiProvider = $style->aiModel->apiProviders->first();
|
||||
}
|
||||
}
|
||||
}
|
||||
// If image_uuid is provided, get the API provider for that image's style
|
||||
elseif ($imageUuid) {
|
||||
$image = Image::with(['style.aiModel' => function ($query) {
|
||||
$query->with(['primaryApiProvider', 'apiProviders' => function ($query) {
|
||||
$query->where('enabled', true);
|
||||
}]);
|
||||
$query->with('primaryApiProvider');
|
||||
}])->where('uuid', $imageUuid)->first();
|
||||
|
||||
if ($image && $image->style && $image->style->aiModel) {
|
||||
// Use the primary API provider for this AI model if available
|
||||
// Use the primary API provider for this AI model
|
||||
$apiProvider = $image->style->aiModel->primaryApiProvider;
|
||||
if (!$apiProvider) {
|
||||
// Fallback to the first enabled API provider from the many-to-many relationship
|
||||
$apiProvider = $image->style->aiModel->apiProviders->where('enabled', true)->first();
|
||||
}
|
||||
if (!$apiProvider) {
|
||||
// If no enabled provider found, try any provider
|
||||
$apiProvider = $image->style->aiModel->apiProviders->first();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback to the old behavior if no style_id or image_uuid is provided
|
||||
@@ -421,22 +379,12 @@ class ImageController extends Controller
|
||||
$defaultStyleSetting = \App\Models\Setting::where('key', 'default_style_id')->first();
|
||||
if ($defaultStyleSetting && $defaultStyleSetting->value) {
|
||||
$style = Style::with(['aiModel' => function ($query) {
|
||||
$query->where('enabled', true)->with(['primaryApiProvider', 'apiProviders' => function ($query) {
|
||||
$query->where('enabled', true);
|
||||
}]);
|
||||
$query->where('enabled', true)->with('primaryApiProvider');
|
||||
}])->find($defaultStyleSetting->value);
|
||||
|
||||
if ($style && $style->aiModel) {
|
||||
// Use the primary API provider for this AI model if available
|
||||
// Use the primary API provider for this AI model
|
||||
$apiProvider = $style->aiModel->primaryApiProvider;
|
||||
if (!$apiProvider) {
|
||||
// Fallback to the first enabled API provider from the many-to-many relationship
|
||||
$apiProvider = $style->aiModel->apiProviders->where('enabled', true)->first();
|
||||
}
|
||||
if (!$apiProvider) {
|
||||
// If no enabled provider found, try any provider
|
||||
$apiProvider = $style->aiModel->apiProviders->first();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ class StyleController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$styles = Style::with(['aiModel.apiProviders'])
|
||||
$styles = Style::with(['aiModel.primaryApiProvider'])
|
||||
->where('enabled', true)
|
||||
->whereHas('aiModel', function ($query) {
|
||||
$query->where('enabled', true);
|
||||
$query->whereHas('apiProviders', function ($query) {
|
||||
$query->whereHas('primaryApiProvider', function ($query) {
|
||||
$query->where('enabled', true);
|
||||
});
|
||||
})
|
||||
|
||||
@@ -14,6 +14,7 @@ class AiModel extends Model
|
||||
'model_id',
|
||||
'model_type',
|
||||
'parameters',
|
||||
'api_provider_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
@@ -24,9 +25,4 @@ class AiModel extends Model
|
||||
{
|
||||
return $this->belongsTo(ApiProvider::class, 'api_provider_id');
|
||||
}
|
||||
|
||||
public function apiProviders()
|
||||
{
|
||||
return $this->belongsToMany(ApiProvider::class, 'ai_model_api_provider');
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,6 @@ class ApiProvider extends Model
|
||||
|
||||
public function aiModels()
|
||||
{
|
||||
return $this->belongsToMany(AiModel::class, 'ai_model_api_provider');
|
||||
return $this->hasMany(AiModel::class, 'api_provider_id');
|
||||
}
|
||||
}
|
||||
@@ -91,11 +91,6 @@ return new class extends Migration
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('ai_model_api_provider', function (Blueprint $table) {
|
||||
$table->foreignId('ai_model_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('api_provider_id')->constrained()->onDelete('cascade');
|
||||
$table->primary(['ai_model_id', 'api_provider_id']);
|
||||
});
|
||||
|
||||
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
||||
$table->string('email')->primary();
|
||||
@@ -133,7 +128,6 @@ return new class extends Migration
|
||||
Schema::dropIfExists('personal_access_tokens');
|
||||
Schema::dropIfExists('failed_jobs');
|
||||
Schema::dropIfExists('password_reset_tokens');
|
||||
Schema::dropIfExists('ai_model_api_provider');
|
||||
Schema::dropIfExists('settings');
|
||||
Schema::dropIfExists('images');
|
||||
Schema::dropIfExists('styles');
|
||||
|
||||
@@ -23,8 +23,9 @@ class AiModelApiProviderSeeder extends Seeder
|
||||
]
|
||||
];
|
||||
|
||||
// Update existing AI models with their API provider IDs
|
||||
foreach ($data as $row) {
|
||||
DB::table('ai_model_api_provider')->insert($row);
|
||||
\App\Models\AiModel::where('id', $row['ai_model_id'])->update(['api_provider_id' => $row['api_provider_id']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user