feat: save prompt caption alongside every generated image
After each successful image upload to storage, a sidecar `.caption`
file is uploaded at the same path with `.caption` extension containing
the exact prompt used to generate the image.
Coverage:
- generation/handlers.go: ImageHandler → media/{userID}/images/{jobID}_{i}.caption
- album/handler.go: AnchorHandler → albums/{userID}/{albumID}/anchor.caption
- album/handler.go: ShotHandler → albums/{userID}/{albumID}/shots/{shotIndex}.caption
- personagen/service.go: generatePosition → personas/{specID}/images/{pos:02d}.caption
Caption failures are logged at warn level and never abort the job.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3979ef2d08
commit
062a828a00
@ -83,6 +83,10 @@ func AnchorHandler(mg *mediagen.Manager, store storage.Store, pub realtime.Event
|
|||||||
logger.Warn("failed to persist anchor to storage, using inline URL", "error", uploadErr, "job_id", job.ID)
|
logger.Warn("failed to persist anchor to storage, using inline URL", "error", uploadErr, "job_id", job.ID)
|
||||||
} else {
|
} else {
|
||||||
anchorURL = url
|
anchorURL = url
|
||||||
|
captionPath := fmt.Sprintf("albums/%s/%s/anchor.caption", userID, albumID)
|
||||||
|
if _, captionErr := store.Upload(ctx, captionPath, []byte(subjectDesc), "text/plain"); captionErr != nil {
|
||||||
|
logger.Warn("failed to persist anchor caption", "error", captionErr, "job_id", job.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +217,10 @@ func ShotHandler(mg *mediagen.Manager, store storage.Store, pub realtime.EventPu
|
|||||||
"error", uploadErr, "job_id", job.ID)
|
"error", uploadErr, "job_id", job.ID)
|
||||||
} else {
|
} else {
|
||||||
imageURL = url
|
imageURL = url
|
||||||
|
captionPath := fmt.Sprintf("albums/%s/%s/shots/%d.caption", userID, albumID, shotIndex)
|
||||||
|
if _, captionErr := store.Upload(ctx, captionPath, []byte(prompt), "text/plain"); captionErr != nil {
|
||||||
|
logger.Warn("failed to persist shot caption", "error", captionErr, "job_id", job.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -100,6 +100,10 @@ func ImageHandler(mg *mediagen.Manager, store storage.Store, pub realtime.EventP
|
|||||||
if uploadErr != nil {
|
if uploadErr != nil {
|
||||||
logger.Warn("failed to persist image to storage", "error", uploadErr, "job_id", job.ID)
|
logger.Warn("failed to persist image to storage", "error", uploadErr, "job_id", job.ID)
|
||||||
} else {
|
} else {
|
||||||
|
captionPath := fmt.Sprintf("media/%s/images/%s_%d.caption", userID, job.ID, i)
|
||||||
|
if _, captionErr := store.Upload(ctx, captionPath, []byte(prompt), "text/plain"); captionErr != nil {
|
||||||
|
logger.Warn("failed to persist image caption", "error", captionErr, "job_id", job.ID)
|
||||||
|
}
|
||||||
images[i] = GeneratedImage{Data: url, IsURL: true, Seed: resp.Seed}
|
images[i] = GeneratedImage{Data: url, IsURL: true, Seed: resp.Seed}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -228,6 +228,13 @@ func (s *Service) generatePosition(ctx context.Context, spec *persona.PersonaSpe
|
|||||||
return fmt.Errorf("storing position %d: %w", pos, err)
|
return fmt.Errorf("storing position %d: %w", pos, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if imgSpec.Prompt != "" {
|
||||||
|
captionPath := fmt.Sprintf("personas/%s/images/%02d.caption", spec.ID, pos)
|
||||||
|
if _, captionErr := s.store.Upload(ctx, captionPath, []byte(imgSpec.Prompt), "text/plain"); captionErr != nil {
|
||||||
|
s.logger.Warn("failed to persist image caption", "error", captionErr, "position", pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
imgSpec.URL = url
|
imgSpec.URL = url
|
||||||
imgSpec.Status = persona.ImageStatusComplete
|
imgSpec.Status = persona.ImageStatusComplete
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user