fix: align Freepik API paths with OpenAPI spec
Some checks failed
Build and Push Docker Image / build (push) Failing after 9s

The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:

- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
  not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
  with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
  relight -> image-relight, style-transfer -> image-style-transfer,
  expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
  remove-background -> beta/remove-background, classifier -> classifier/image,
  audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
  minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
  not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
  results in data.generated[] array, classifier returns [{class_name, probability}]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 16:26:42 +01:00
parent 99c24adfe8
commit 1a5c686dfc
10 changed files with 333 additions and 269 deletions

View File

@@ -14,19 +14,19 @@ from app.schemas.image_editing import (
UpscalePrecisionRequest,
)
from app.services import freepik_client, task_tracker
from app.services.freepik_client import TaskResult, _extract_task_id
logger = logging.getLogger(__name__)
router = APIRouter(prefix='/api/v1/edit', tags=['image-editing'])
async def _submit_and_respond(result: dict, sync: bool, metadata: dict) -> TaskResponse | TaskDetail:
data = result.get('data', result)
freepik_task_id = str(data.get('task_id') or data.get('id', ''))
async def _submit_and_respond(result: TaskResult, sync: bool, metadata: dict) -> TaskResponse | TaskDetail:
freepik_task_id = _extract_task_id(result.data)
if not freepik_task_id:
raise HTTPException(status_code=502, detail='No task_id in Freepik response')
internal_id = task_tracker.submit(freepik_task_id, metadata)
internal_id = task_tracker.submit(freepik_task_id, result.status_path, metadata)
if not sync:
return TaskResponse(
@@ -63,9 +63,10 @@ async def upscale_creative(request: UpscaleCreativeRequest, sync: bool = Query(F
result = await freepik_client.upscale_creative(
image=request.image,
prompt=request.prompt,
scale=request.scale,
scale_factor=request.scale_factor,
creativity=request.creativity,
resemblance=request.resemblance,
optimized_for=request.optimized_for,
)
return await _submit_and_respond(result, sync, {'operation': 'upscale-creative'})
@@ -74,7 +75,7 @@ async def upscale_creative(request: UpscaleCreativeRequest, sync: bool = Query(F
async def upscale_precision(request: UpscalePrecisionRequest, sync: bool = Query(False)):
result = await freepik_client.upscale_precision(
image=request.image,
scale=request.scale,
scale_factor=request.scale_factor,
)
return await _submit_and_respond(result, sync, {'operation': 'upscale-precision'})
@@ -84,8 +85,8 @@ async def relight(request: RelightRequest, sync: bool = Query(False)):
result = await freepik_client.relight_image(
image=request.image,
prompt=request.prompt,
light_source=request.light_source,
intensity=request.intensity,
transfer_light_from_reference_image=request.transfer_light_from_reference_image,
light_transfer_strength=request.light_transfer_strength,
)
return await _submit_and_respond(result, sync, {'operation': 'relight'})
@@ -94,8 +95,10 @@ async def relight(request: RelightRequest, sync: bool = Query(False)):
async def style_transfer(request: StyleTransferRequest, sync: bool = Query(False)):
result = await freepik_client.style_transfer(
image=request.image,
style_reference=request.style_reference,
strength=request.strength,
reference_image=request.reference_image,
prompt=request.prompt,
style_strength=request.style_strength,
structure_strength=request.structure_strength,
)
return await _submit_and_respond(result, sync, {'operation': 'style-transfer'})
@@ -105,7 +108,6 @@ async def expand(request: ExpandRequest, sync: bool = Query(False)):
result = await freepik_client.expand_image(
image=request.image,
prompt=request.prompt,
direction=request.direction,
)
return await _submit_and_respond(result, sync, {'operation': 'expand'})