163 lines
6.6 KiB
Markdown
163 lines
6.6 KiB
Markdown
# Persona Generation Guide
|
||
|
||
`pkg/personagen` provides a complete pipeline for generating synthetic persona profiles with
|
||
biological DNA, personality psychology, lifestyle preferences, a 20-position image matrix,
|
||
and 4-motion-type video specs.
|
||
|
||
## Overview
|
||
|
||
A `PersonaSpec` is the top-level output — it contains:
|
||
- **CoreIdentity**: name, age, gender, ethnicity, occupation, location
|
||
- **DNA**: immutable biological characteristics (face, body, voice)
|
||
- **Psychology**: HEXACO personality profile, attachment style, values
|
||
- **Lifestyle**: interests (5 categories), fashion sense (15 contexts), vacation style
|
||
- **ImageMatrix**: 20-position image generation specs (4 tiers: Identity, Expressions, Angles, Context)
|
||
- **Videos**: 4 video specs (smile_reveal, personality_moment, lifestyle, invitation)
|
||
|
||
## Generation Flow
|
||
|
||
```
|
||
POST /api/{service}/persona/generate
|
||
→ "persona_generate" job enqueued → 202 {jobId}
|
||
→ Worker picks up job
|
||
→ personagen.Service.GenerateSpec() → 5-stage LLM pipeline
|
||
→ personagen.Service.GenerateImages() → 20 image positions (position 1 = anchor first)
|
||
→ personagen.Service.GenerateVideo() → 4 video motion types
|
||
→ SSE events delivered to user:<userId>
|
||
```
|
||
|
||
## 5-Stage Spec Pipeline
|
||
|
||
| Stage | What it does | LLM calls |
|
||
|-------|-------------|-----------|
|
||
| 1 | Identity: name, age, ethnicity, occupation, location | 1 |
|
||
| 2 | Psychology: HEXACO scores, attachment, values | 1 |
|
||
| 3 | Lifestyle: interests, fashion context, vacation style | 1 |
|
||
| 4 | Visual DNA: all face/body/voice characteristics | 1 |
|
||
| 5 | Populate image matrix from lifestyle (no LLM needed) | 0 |
|
||
|
||
Total: **4 LLM calls** per persona spec.
|
||
|
||
## Image Matrix Tiers
|
||
|
||
| Tier | Positions | Focus |
|
||
|------|-----------|-------|
|
||
| 1 – Identity | 1–5 | Core look, position 1 is the anchor |
|
||
| 2 – Expressions | 6–11 | Personality through facial expressions |
|
||
| 3 – Angles | 12–16 | Camera angle variety |
|
||
| 4 – Context | 17–20 | Situational lifestyle shots |
|
||
|
||
**Position 1 is always generated first** and becomes the anchor image for all subsequent
|
||
positions (passed as `ReferenceImage` to the mediagen provider).
|
||
|
||
## HEIA Prompt Structure
|
||
|
||
Images use the HEIA (High-Engagement Influencer Aesthetic) prompt format:
|
||
|
||
```
|
||
[IDENTITY] 26-year-old Korean woman, 5'4" (163cm), slender build.
|
||
[FACE] oval face with high cheekbones, defined jawline, almond-shaped dark brown eyes...
|
||
[BODY] slender build, narrow shoulders, 0.72 WHR, upright posture.
|
||
[POSE] mid distance, 3/4 angle, standing, soft gaze expression, slight over-shoulder turn.
|
||
[CLOTHING] crisp white off-shoulder blouse, minimal gold jewelry — slim, structured.
|
||
[SCENE] neutral light background, subtle gradient.
|
||
[CONSTRAINTS] WOMAN SUBJECT ONLY. Human body has EXACTLY 2 arms, 2 legs, 10 fingers total...
|
||
```
|
||
|
||
## SSE Events
|
||
|
||
Subscribe to `user:<userId>` channel before calling the generate endpoint:
|
||
|
||
```json
|
||
{"type": "persona_spec_started", "jobId": "...", "message": "Generating persona profile..."}
|
||
{"type": "persona_spec_complete", "jobId": "...", "result": {"personaId": "ps_abc123"}}
|
||
{"type": "persona_image_started", "jobId": "...", "result": {"position": 1}}
|
||
{"type": "persona_image_progress", "jobId": "...", "progress": 45, "result": {"position": 9, "url": "..."}}
|
||
{"type": "persona_image_complete", "jobId": "...", "progress": 100, "result": {"personaId": "..."}}
|
||
{"type": "persona_video_started", "jobId": "...", "result": {"motionType": "smile_reveal"}}
|
||
{"type": "persona_video_complete", "jobId": "...", "result": {"motionType": "smile_reveal", "url": "..."}}
|
||
{"type": "persona_video_failed", "jobId": "...", "error": "smile_reveal video failed: ...", "result": {"motionType": "smile_reveal"}}
|
||
{"type": "persona_failed", "jobId": "...", "error": "Spec generation failed: ..."}
|
||
```
|
||
|
||
## Environment Requirements
|
||
|
||
Both AI providers must be configured for persona generation to work:
|
||
|
||
| Env Var | Purpose |
|
||
|---------|---------|
|
||
| `LAOZHANG_API_KEY` | Image and video generation (Flux, Kling) |
|
||
| `GEMINI_API_KEY` | Text generation (Gemini) + additional media (Imagen, Veo) |
|
||
|
||
These are auto-injected by rdev into every deployed service. Locally, source from `.secrets`.
|
||
|
||
## Using the Service Directly
|
||
|
||
```go
|
||
// Create the service
|
||
svc := personagen.New(textgenMgr, mediagenMgr, store, logger.Logger)
|
||
|
||
// Generate a full persona spec (5-stage LLM pipeline)
|
||
spec, err := svc.GenerateSpec(ctx, personagen.SeedParams{
|
||
Description: "confident Latina entrepreneur who loves fashion and travel",
|
||
Gender: "woman",
|
||
Name: "Sofia Reyes", // optional
|
||
})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// Generate all 20 images (position 1 first, sets anchor automatically)
|
||
if err := svc.GenerateImages(ctx, spec, nil); err != nil {
|
||
return err
|
||
}
|
||
|
||
// Generate a specific video
|
||
videoSpec, err := svc.GenerateVideo(ctx, spec, persona.MotionSmileReveal)
|
||
|
||
// Generate utility images
|
||
avatarBytes, err := svc.GenerateAvatar(ctx, spec)
|
||
bannerBytes, err := svc.GenerateBanner(ctx, spec, "lifestyle")
|
||
```
|
||
|
||
## Fashion Contexts
|
||
|
||
15 named fashion contexts are available in `pkg/persona`:
|
||
|
||
| Context Name | Style |
|
||
|-------------|-------|
|
||
| `classic_minimalist` | Clean lines, neutral palette |
|
||
| `streetwear_chic` | Urban oversized fits, sneakers |
|
||
| `bohemian_free_spirit` | Flowing fabrics, earth tones |
|
||
| `athleisure_pro` | Performance fabrics, gym-to-street |
|
||
| `business_casual` | Polished professional with comfort |
|
||
| `romantic_feminine` | Florals, lace, pastels |
|
||
| `edgy_alternative` | Dark palette, leather, hardware |
|
||
| `coastal_casual` | Relaxed, beachy, linen |
|
||
| `urban_professional` | Sharp city-dweller aesthetic |
|
||
| `festival_glam` | Bold prints, glitter, maximalist |
|
||
| `preppy_classic` | Collegiate, polo shirts, chinos |
|
||
| `dark_academia` | Literary, tweed, earth tones |
|
||
| `cottagecore` | Prairie dresses, pastoral romance |
|
||
| `y2k_revival` | Low-rise, metallics, early 2000s |
|
||
| `luxe_loungewear` | Elevated comfort in premium fabrics |
|
||
|
||
Use `persona.AllFashionContexts()` for the full catalog or `persona.FashionContextFor(name)` for a single context.
|
||
|
||
## Motion Types
|
||
|
||
| Motion Type | Description | Duration | Aspect |
|
||
|------------|-------------|----------|--------|
|
||
| `smile_reveal` | Warm genuine smile moment | 5s | 9:16 |
|
||
| `personality_moment` | Expressive personality showcase | 8s | 9:16 |
|
||
| `lifestyle` | Contextual lifestyle shot | 8s | 16:9 |
|
||
| `invitation` | Direct-address to viewer | 5s | 9:16 |
|
||
|
||
## Errors
|
||
|
||
| Error | Cause |
|
||
|-------|-------|
|
||
| `ErrAnchorNotSet` | `GenerateVideo()` called before position 1 image was generated |
|
||
| `"mediagen not configured"` | No AI provider keys set |
|
||
| `"stage N X: ..."` | LLM call or JSON parse failure in specgen pipeline |
|