Skip to content

feat(ai): Fashion Decode 파싱 파이프라인 (Vision AI → seed_*) #260

@cocoyoon

Description

@cocoyoon

Summary

R2(decoded-media)에 적재된 fashion-decode 이미지를 Vision AI로 파싱해 구조화 데이터(ParsedDecodeResult)로 추출하고, 기존 seed 파이프라인(seed_posts → seed_spots → seed_solutions)에 투입한다.

플랫폼 무관warehouse.source_mediaparse_status='pending' 레코드만 바라보고 동작한다.

Related:


Architecture

ARQ 잡 (10분 간격)
  → source_media WHERE parse_status='pending' LIMIT 10
  → R2 GET (r2_key)
  → GeminiClient (gemini-3-flash-preview)
       input: image bytes + caption
       output: ParsedDecodeResult (Pydantic structured output)
  → seed_writer:
      seed_posts  ← image_url=r2_url, media_source={platform, external_id}
      seed_spots  ← position_left/top, subcategory_code (item별)
      seed_solutions ← brand, product_name, price_*
      seed_asset  ← archived_url=r2_url, image_hash
  → source_media UPDATE parse_status='parsed', seed_post_id=<new>, parse_result=<json>

스키마 (재사용)

class ParsedItem(BaseModel):
    brand: str
    product_name: str | None
    price_amount: float | None
    price_currency: str | None        # USD | KRW | EUR | ...
    subcategory: str                   # top | bottom | shoes | bag | accessory | ...
    position_x_pct: int               # 0-100 (seed_spots.position_left)
    position_y_pct: int               # 0-100 (seed_spots.position_top)

class ParsedDecodeResult(BaseModel):
    celebrity_name: str | None
    group_name: str | None
    occasion: str | None
    items: list[ParsedItem]

엔티티 매칭(brand 문자열 → brands 테이블 FK 해소)은 파이프라인 4(디테일 enrichment) 담당. 여기서는 문자열 그대로 seed_solutions 에 저장.


파일

신규

파일 역할
packages/ai-server/src/services/media/vision_parser.py MediaVisionParser
packages/ai-server/src/services/media/seed_writer.py source_media → seed_* 매핑
packages/ai-server/src/services/media/jobs.py parse_media_job ARQ 잡

수정

파일 변경
packages/ai-server/src/bootstrap.py 파싱 잡 10분 스케줄 등록
packages/ai-server/src/api/media.py POST /media/items/{id}/reparse 수동 재파싱

에러 처리

  • 파싱 실패: parse_status='failed', parse_result={error: ...} — 재시도 최대 3회
  • 아이템 0개: parse_status='skipped' (fashion-decode 포맷이 아님)
  • Vision API rate-limit: ARQ backoff

검증

  • 샘플 fashion-decode 이미지 20장으로 파싱 정확도 측정 (브랜드/가격/위치 수동 라벨 vs AI 출력)
  • E2E: source_media(pending) → 파싱 잡 1회 → seed_posts/seed_spots/seed_solutions 생성 + parse_status='parsed'
  • Vision API 실패/타임아웃 시 재시도 동작 확인
  • Admin 검수 UI에서 파싱 결과 표시 확인

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions