@umituz/react-native-ai-generation-content 1.89.26 → 1.89.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/domains/creations/presentation/components/GalleryScreenHeader.tsx +1 -1
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +2 -8
- package/src/domains/generation/index.ts +14 -0
- package/src/domains/generation/infrastructure/appearance-analysis.ts +54 -0
- package/src/domains/generation/infrastructure/couple-generation-builder.ts +203 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.ts +4 -2
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +4 -1
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.types.ts +2 -0
- package/src/domains/prompts/domain/base/constants.ts +34 -5
- package/src/domains/prompts/domain/base/creators.ts +25 -2
- package/src/domains/prompts/domain/base/types.ts +3 -0
- package/src/domains/prompts/index.ts +5 -0
- package/src/domains/scenarios/infrastructure/utils/scenario-utils.ts +10 -1
- package/src/infrastructure/utils/couple-input.util.ts +14 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.89.
|
|
3
|
+
"version": "1.89.27",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -20,7 +20,7 @@ export const GalleryScreenHeader: React.FC<GalleryScreenHeaderProps> = ({ title,
|
|
|
20
20
|
const styles = useMemo(() => createStyles(tokens), [tokens]);
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
|
-
<View style={
|
|
23
|
+
<View style={styles.screenHeader}>
|
|
24
24
|
<TouchableOpacity
|
|
25
25
|
onPress={onBack}
|
|
26
26
|
style={styles.backButton}
|
|
@@ -76,12 +76,7 @@ export function CreationsGalleryScreen({
|
|
|
76
76
|
|
|
77
77
|
useAppFocusEffect(useCallback(() => {
|
|
78
78
|
void refetch();
|
|
79
|
-
|
|
80
|
-
if (!initialCreationId) {
|
|
81
|
-
const { setSelectedCreation } = galleryState;
|
|
82
|
-
setSelectedCreation(null);
|
|
83
|
-
}
|
|
84
|
-
}, [refetch, initialCreationId, galleryState.setSelectedCreation]));
|
|
79
|
+
}, [refetch]));
|
|
85
80
|
|
|
86
81
|
const filterButtons = useMemo(() =>
|
|
87
82
|
createFilterButtons({
|
|
@@ -165,7 +160,6 @@ export function CreationsGalleryScreen({
|
|
|
165
160
|
{
|
|
166
161
|
backgroundColor: tokens.colors.surface,
|
|
167
162
|
borderBottomColor: tokens.colors.border,
|
|
168
|
-
paddingTop: hasScreenHeader ? 0 : insets.top
|
|
169
163
|
}
|
|
170
164
|
]}>
|
|
171
165
|
<GalleryHeader
|
|
@@ -226,7 +220,7 @@ export function CreationsGalleryScreen({
|
|
|
226
220
|
}
|
|
227
221
|
|
|
228
222
|
return (
|
|
229
|
-
<ScreenLayout header={screenHeader} scrollable={false} edges={["left", "right", "bottom"]}>
|
|
223
|
+
<ScreenLayout header={screenHeader} scrollable={false} edges={["top", "left", "right", "bottom"]}>
|
|
230
224
|
{renderHeader}
|
|
231
225
|
{filters.filtered.length === 0 ? (
|
|
232
226
|
<View style={[styles.listContent, styles.emptyContent]}>
|
|
@@ -34,6 +34,20 @@ export type { GenerationResult } from "../../domain/entities/generation.types";
|
|
|
34
34
|
|
|
35
35
|
export { ExecutorFactory, type GenerationType as ExecutorGenerationType } from "./infrastructure/executors/executor-factory";
|
|
36
36
|
|
|
37
|
+
// Couple Generation Utilities
|
|
38
|
+
export {
|
|
39
|
+
buildCoupleGenerationInput,
|
|
40
|
+
buildScenarioGenerationInput,
|
|
41
|
+
type CoupleGenerationInputParams,
|
|
42
|
+
type CoupleGenerationInput,
|
|
43
|
+
type ScenarioGenerationInputParams,
|
|
44
|
+
} from "./infrastructure/couple-generation-builder";
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
getAppearanceContext,
|
|
48
|
+
enhancePromptWithAnalysis,
|
|
49
|
+
} from "./infrastructure/appearance-analysis";
|
|
50
|
+
|
|
37
51
|
// Wizard Domain
|
|
38
52
|
export type {
|
|
39
53
|
BaseStepConfig,
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Appearance Analysis Utility
|
|
3
|
+
*
|
|
4
|
+
* Fotoğraf analizi ve appearance context çıkarma utility'si.
|
|
5
|
+
* Vision analysis暂时禁用 - 返回空上下文。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { refinePromptForCouple } from "../../prompts";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Fotoğrafları analiz eder ve appearance context string'i döndürür.
|
|
12
|
+
* Şu an vision analysis devre dışı - boş string döndürür.
|
|
13
|
+
*
|
|
14
|
+
* @param photoUris - Analiz edilecek fotoğraf URI'leri
|
|
15
|
+
* @param isCoupleMode - Çift modu mu?
|
|
16
|
+
* @returns Appearance context string (şu an boş)
|
|
17
|
+
*/
|
|
18
|
+
export async function getAppearanceContext(
|
|
19
|
+
photoUris: string[],
|
|
20
|
+
isCoupleMode: boolean,
|
|
21
|
+
): Promise<string> {
|
|
22
|
+
// Vision analysis temporarily disabled due to API limitations
|
|
23
|
+
// Future: Implement vision analysis to extract appearance features
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Fotoğraf analizi based prompt enhancement
|
|
29
|
+
*
|
|
30
|
+
* Tüm generation tab'larında kullanılan standard logic.
|
|
31
|
+
*
|
|
32
|
+
* @param originalPrompt - Orijinal prompt
|
|
33
|
+
* @param photoUris - Fotoğraf URI'leri
|
|
34
|
+
* @param isCoupleMode - Çift modu mu?
|
|
35
|
+
* @returns Enhanced prompt
|
|
36
|
+
*/
|
|
37
|
+
export async function enhancePromptWithAnalysis(
|
|
38
|
+
originalPrompt: string,
|
|
39
|
+
photoUris: string[],
|
|
40
|
+
isCoupleMode: boolean,
|
|
41
|
+
): Promise<string> {
|
|
42
|
+
// Always apply basic couple refinement first
|
|
43
|
+
let finalPrompt = refinePromptForCouple(originalPrompt, isCoupleMode);
|
|
44
|
+
|
|
45
|
+
if (photoUris.length === 0) return finalPrompt;
|
|
46
|
+
|
|
47
|
+
const appearanceContext = await getAppearanceContext(photoUris, isCoupleMode);
|
|
48
|
+
|
|
49
|
+
if (appearanceContext) {
|
|
50
|
+
finalPrompt = `${appearanceContext}\n\n${finalPrompt}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return finalPrompt;
|
|
54
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Couple Image Generation Builder
|
|
3
|
+
*
|
|
4
|
+
* Wardrobe'da kusursuz çalışan mantığı tüm couple generation için paylaştırır.
|
|
5
|
+
* Bu utility'yi tüm çift görüntü oluşturma işlemleri kullanır.
|
|
6
|
+
*
|
|
7
|
+
* Kullanım alanları:
|
|
8
|
+
* - Senaryo generation (Home couple images)
|
|
9
|
+
* - Wardrobe generation
|
|
10
|
+
* - Background generation
|
|
11
|
+
* - Art style generation
|
|
12
|
+
* - Mood filter generation
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
resolveCoupleInput,
|
|
17
|
+
prependContext,
|
|
18
|
+
refinePromptForCouple,
|
|
19
|
+
createPhotorealisticPrompt,
|
|
20
|
+
} from "../../prompts";
|
|
21
|
+
import { getAppearanceContext } from "./appearance-analysis";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generation target configuration
|
|
25
|
+
* TODO: Import from app config when available
|
|
26
|
+
*/
|
|
27
|
+
const GENERATION_TARGETS = {
|
|
28
|
+
imageCoupleMultiRef: { model: "p-image-edit", providerId: "pruna" },
|
|
29
|
+
imageSingleEdit: { model: "p-image-edit", providerId: "pruna" },
|
|
30
|
+
} as const;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Couple generation input parameters
|
|
34
|
+
*/
|
|
35
|
+
export interface CoupleGenerationInputParams {
|
|
36
|
+
// Required params
|
|
37
|
+
partner1PhotoUri: string;
|
|
38
|
+
partner2PhotoUri: string | null;
|
|
39
|
+
isCoupleMode: boolean;
|
|
40
|
+
basePrompt: string; // Scenario prompt, wardrobe prompt, background prompt, etc.
|
|
41
|
+
|
|
42
|
+
// Optional params
|
|
43
|
+
customInstructions?: string;
|
|
44
|
+
aspectRatio?: string; // Default: "3:4"
|
|
45
|
+
strength?: number; // Optional strength for some operations
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Couple generation result
|
|
50
|
+
*/
|
|
51
|
+
export interface CoupleGenerationInput {
|
|
52
|
+
target: string;
|
|
53
|
+
prompt: string;
|
|
54
|
+
params: Record<string, unknown>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Scenario generation input parameters
|
|
59
|
+
*/
|
|
60
|
+
export interface ScenarioGenerationInputParams {
|
|
61
|
+
partner1PhotoUri: string;
|
|
62
|
+
partner2PhotoUri: string | null;
|
|
63
|
+
isCoupleMode: boolean;
|
|
64
|
+
scenarioPrompt: string; // Senaryo prompt'u (aiPrompt)
|
|
65
|
+
customInstructions?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Merkezi couple generation input builder
|
|
70
|
+
*
|
|
71
|
+
* Wardrobe mantığını tüm couple generation için paylaştırır:
|
|
72
|
+
* 1. Appearance analysis (fotoğrafları analiz et)
|
|
73
|
+
* 2. Couple refinement (çift modu için iyileştir)
|
|
74
|
+
* 3. Context prepending (context'i prompt'a ekle)
|
|
75
|
+
* 4. Photorealistic prompt creation
|
|
76
|
+
* 5. Couple input resolution (doğru target ve image'lar)
|
|
77
|
+
*
|
|
78
|
+
* @param params - Generation parameters
|
|
79
|
+
* @returns Generation input with target, prompt, and params
|
|
80
|
+
*/
|
|
81
|
+
export async function buildCoupleGenerationInput(
|
|
82
|
+
params: CoupleGenerationInputParams,
|
|
83
|
+
): Promise<CoupleGenerationInput> {
|
|
84
|
+
const {
|
|
85
|
+
partner1PhotoUri,
|
|
86
|
+
partner2PhotoUri,
|
|
87
|
+
isCoupleMode,
|
|
88
|
+
basePrompt,
|
|
89
|
+
customInstructions,
|
|
90
|
+
aspectRatio = "3:4", // Standard portrait ratio like Wardrobe
|
|
91
|
+
strength,
|
|
92
|
+
} = params;
|
|
93
|
+
|
|
94
|
+
// 1. GET PHOTO URIs - Couple mode kontrolü
|
|
95
|
+
const photoUris =
|
|
96
|
+
isCoupleMode && partner2PhotoUri
|
|
97
|
+
? [partner1PhotoUri, partner2PhotoUri]
|
|
98
|
+
: [partner1PhotoUri];
|
|
99
|
+
|
|
100
|
+
// 2. ANALYZE APPEARANCE - Wardrobe'daki gibi
|
|
101
|
+
// Fotoğrafları analiz et ve context çıkar
|
|
102
|
+
const appearanceContext = await getAppearanceContext(
|
|
103
|
+
photoUris,
|
|
104
|
+
isCoupleMode,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// 3. REFINE FOR COUPLE + PREPEND CONTEXT - Wardrobe mantığı
|
|
108
|
+
// Coupler modu için prompt'u iyileştir ve context'i ekle
|
|
109
|
+
const refinedPrompt = prependContext(
|
|
110
|
+
refinePromptForCouple(basePrompt, isCoupleMode),
|
|
111
|
+
appearanceContext,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// 4. CREATE FINAL PROMPT - Photorealistic
|
|
115
|
+
const prompt = createPhotorealisticPrompt(refinedPrompt, {
|
|
116
|
+
isCouple: isCoupleMode,
|
|
117
|
+
customInstructions,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// 5. RESOLVE COUPLE INPUT - Doğru target ve image'lar
|
|
121
|
+
const { target, imageUrls } = resolveCoupleInput(
|
|
122
|
+
partner1PhotoUri,
|
|
123
|
+
partner2PhotoUri,
|
|
124
|
+
isCoupleMode,
|
|
125
|
+
GENERATION_TARGETS.imageSingleEdit,
|
|
126
|
+
GENERATION_TARGETS.imageCoupleMultiRef,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// 6. BUILD PARAMS - Wardrobe formatında
|
|
130
|
+
const genParams: Record<string, unknown> = {
|
|
131
|
+
prompt,
|
|
132
|
+
image_urls: imageUrls,
|
|
133
|
+
aspect_ratio: aspectRatio,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Optional strength parameter
|
|
137
|
+
if (strength !== undefined) {
|
|
138
|
+
genParams.strength = strength;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
target,
|
|
143
|
+
prompt,
|
|
144
|
+
params: genParams,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Scenario generation için özel wrapper
|
|
150
|
+
*
|
|
151
|
+
* Senaryo aiPrompt'larını (zaten createPhotorealisticPrompt ile oluşturulmuş)
|
|
152
|
+
* Wardrobe mantığı ile birleştirir.
|
|
153
|
+
*/
|
|
154
|
+
export async function buildScenarioGenerationInput(
|
|
155
|
+
params: ScenarioGenerationInputParams,
|
|
156
|
+
): Promise<CoupleGenerationInput> {
|
|
157
|
+
const {
|
|
158
|
+
partner1PhotoUri,
|
|
159
|
+
partner2PhotoUri,
|
|
160
|
+
isCoupleMode,
|
|
161
|
+
scenarioPrompt,
|
|
162
|
+
customInstructions,
|
|
163
|
+
} = params;
|
|
164
|
+
|
|
165
|
+
// 1. GET PHOTO URIs
|
|
166
|
+
const photoUris =
|
|
167
|
+
isCoupleMode && partner2PhotoUri
|
|
168
|
+
? [partner1PhotoUri, partner2PhotoUri]
|
|
169
|
+
: [partner1PhotoUri];
|
|
170
|
+
|
|
171
|
+
// 2. ANALYZE APPEARANCE
|
|
172
|
+
const appearanceContext = await getAppearanceContext(
|
|
173
|
+
photoUris,
|
|
174
|
+
isCoupleMode,
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// 3. REFINE FOR COUPLE + PREPEND CONTEXT
|
|
178
|
+
// Senaryo prompt'unu (zaten photorealistic) dynamic context ile birleştir
|
|
179
|
+
const finalPrompt = prependContext(
|
|
180
|
+
refinePromptForCouple(scenarioPrompt, isCoupleMode),
|
|
181
|
+
appearanceContext,
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// 4. RESOLVE COUPLE INPUT
|
|
185
|
+
const { target, imageUrls } = resolveCoupleInput(
|
|
186
|
+
partner1PhotoUri,
|
|
187
|
+
partner2PhotoUri,
|
|
188
|
+
isCoupleMode,
|
|
189
|
+
GENERATION_TARGETS.imageSingleEdit,
|
|
190
|
+
GENERATION_TARGETS.imageCoupleMultiRef,
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// 5. BUILD PARAMS - Scenario formatında
|
|
194
|
+
return {
|
|
195
|
+
target,
|
|
196
|
+
prompt: finalPrompt,
|
|
197
|
+
params: {
|
|
198
|
+
prompt: finalPrompt,
|
|
199
|
+
image_urls: imageUrls,
|
|
200
|
+
aspect_ratio: "3:4",
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.ts
CHANGED
|
@@ -69,14 +69,16 @@ export async function executeImageGeneration(
|
|
|
69
69
|
|
|
70
70
|
const modelInput: Record<string, unknown> = {
|
|
71
71
|
prompt: finalPrompt,
|
|
72
|
-
aspect_ratio: MODEL_INPUT_DEFAULTS.aspectRatio,
|
|
72
|
+
aspect_ratio: input.aspectRatio || MODEL_INPUT_DEFAULTS.aspectRatio,
|
|
73
73
|
output_format: MODEL_INPUT_DEFAULTS.outputFormat,
|
|
74
74
|
num_images: MODEL_INPUT_DEFAULTS.numImages,
|
|
75
75
|
enable_safety_checker: MODEL_INPUT_DEFAULTS.enableSafetyChecker,
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
-
//
|
|
78
|
+
// p-image-edit (and typical multi-ref models) usually expect 'images' key
|
|
79
|
+
// supporting both 'images' and 'image_urls' for maximum compatibility
|
|
79
80
|
if (imageUrls.length > 0) {
|
|
81
|
+
modelInput.images = imageUrls;
|
|
80
82
|
modelInput.image_urls = imageUrls;
|
|
81
83
|
}
|
|
82
84
|
|
package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts
CHANGED
|
@@ -44,7 +44,10 @@ export async function buildImageInput(
|
|
|
44
44
|
const styleValue = extractSelection(wizardData.style);
|
|
45
45
|
const style = typeof styleValue === "string" ? styleValue : undefined;
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
// Extract aspect ratio from wizard data
|
|
48
|
+
const aspectRatio = typeof wizardData.aspect_ratio === "string" ? wizardData.aspect_ratio : undefined;
|
|
49
|
+
|
|
50
|
+
return { photos, prompt: finalPrompt, style, aspectRatio };
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
/**
|
|
@@ -11,6 +11,8 @@ export interface WizardImageInput {
|
|
|
11
11
|
readonly prompt: string;
|
|
12
12
|
/** Optional style from wizard selection (text-to-image only) */
|
|
13
13
|
readonly style?: string;
|
|
14
|
+
/** Optional aspect ratio (passed to model) */
|
|
15
|
+
readonly aspectRatio?: string;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export interface CreateImageStrategyOptions {
|
|
@@ -13,11 +13,12 @@ Preserve the EXACT facial appearance, structure, and unique characteristics from
|
|
|
13
13
|
|
|
14
14
|
export const IDENTITY_PRESERVATION_COUPLE = `IDENTITY PRESERVATION (CRITICAL):
|
|
15
15
|
Preserve the EXACT facial appearance of BOTH people from the uploaded photos with 100% accuracy.
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- Both people must be instantly recognizable as
|
|
19
|
-
-
|
|
20
|
-
-
|
|
16
|
+
- MAPPING: Map the first person in the first photo to the first person in the scene, and the second person in the second photo to the second person in the scene.
|
|
17
|
+
- Maintain unique bone structure, facial proportions, and specific features for both individuals independently.
|
|
18
|
+
- Both people must be clearly distinct and instantly recognizable as their original selves.
|
|
19
|
+
- Keep authentic skin textures, expressions, and gender-specific traits for both.
|
|
20
|
+
- Ensure natural relative heights and genuine chemistry between the two.
|
|
21
|
+
- DO NOT mix facial features between the two people or apply artificial smoothing.`;
|
|
21
22
|
|
|
22
23
|
export const PHOTOREALISTIC_RENDERING = `STYLE - PHOTOREALISTIC QUALITY (CRITICAL):
|
|
23
24
|
Create an authentic photograph with professional camera characteristics.
|
|
@@ -47,3 +48,31 @@ Ensure a real photographic look, NOT digital art or AI-generated appearance.
|
|
|
47
48
|
- Natural highlights and soft shadow falloff across faces.
|
|
48
49
|
- Realistic fabric folds and individual hair movement.
|
|
49
50
|
- NO poreless skin, artificial glow, or over-processed effects.`;
|
|
51
|
+
|
|
52
|
+
export const TECHNICAL_STANDARDS = `TECHNICAL QUALITY STANDARDS:
|
|
53
|
+
- Professional DSLR photograph quality (Canon/Nikon/Sony).
|
|
54
|
+
- Authentic 35mm film photography aesthetic, unfiltered raw capture.
|
|
55
|
+
- Fujifilm or Kodak Portra film color science - natural, organic, slightly muted.
|
|
56
|
+
- Natural uneven lighting with realistic deep shadows and highlights.
|
|
57
|
+
- Sharp focus on clothing but preserve raw skin texture with visible tiny pores.
|
|
58
|
+
- Result MUST NOT look AI-generated (Negative: plastic, render, CGI, 3d, airbrushed, doll, cartoon).`;
|
|
59
|
+
|
|
60
|
+
export const ARTISTIC_STANDARDS = `ARTISTIC QUALITY STANDARDS:
|
|
61
|
+
- High-fidelity digital art masterpiece.
|
|
62
|
+
- Deep texture details and masterful light/shadow interplay.
|
|
63
|
+
- Vibrant and harmonious color palette original to the selected theme.
|
|
64
|
+
- Sharp focus on subject identity while background blends into the artistic theme.
|
|
65
|
+
- NO blurred faces, NO distorted features.`;
|
|
66
|
+
|
|
67
|
+
export const WARDROBE_TRANSFORMATION_RULES = `WARDROBE TRANSFORMATION RULES:
|
|
68
|
+
- Change ONLY the clothing/outfits and apply accessories if requested.
|
|
69
|
+
- Keep ALL identity features IDENTICAL to reference photos.
|
|
70
|
+
- Core facial structure, hair color, and basic style must remain unchanged.`;
|
|
71
|
+
|
|
72
|
+
export const ART_STYLE_TRANSFORMATION_RULES = `ART STYLE TRANSFORMATION RULES:
|
|
73
|
+
- Apply the artistic style ONLY to the texture, lighting, and background.
|
|
74
|
+
- DO NOT change faces into generic art faces. They MUST be recognizable as the original individuals.`;
|
|
75
|
+
|
|
76
|
+
export const RETOUCH_TRANSFORMATION_RULES = `RETOUCH TRANSFORMATION RULES:
|
|
77
|
+
- Subtle, natural improvement while keeping original bone structure.
|
|
78
|
+
- NO extreme changes to identity. Keep facial markers (moles, freckles) if choice allows.`;
|
|
@@ -8,6 +8,11 @@ import {
|
|
|
8
8
|
PHOTOREALISTIC_RENDERING,
|
|
9
9
|
NATURAL_POSE_GUIDELINES,
|
|
10
10
|
NATURAL_POSE_GUIDELINES_COUPLE,
|
|
11
|
+
TECHNICAL_STANDARDS,
|
|
12
|
+
ARTISTIC_STANDARDS,
|
|
13
|
+
WARDROBE_TRANSFORMATION_RULES,
|
|
14
|
+
ART_STYLE_TRANSFORMATION_RULES,
|
|
15
|
+
RETOUCH_TRANSFORMATION_RULES,
|
|
11
16
|
} from "./constants";
|
|
12
17
|
import type { CreatePromptOptions } from "./types";
|
|
13
18
|
|
|
@@ -20,28 +25,46 @@ export const createPhotorealisticPrompt = (
|
|
|
20
25
|
includePhotoRealism = true,
|
|
21
26
|
includePoseGuidelines = true,
|
|
22
27
|
isCouple = false,
|
|
28
|
+
isArtistic = false,
|
|
29
|
+
isWardrobe = false,
|
|
30
|
+
isRetouch = false,
|
|
23
31
|
customInstructions,
|
|
24
32
|
} = options;
|
|
25
33
|
|
|
26
34
|
const parts: string[] = [];
|
|
27
35
|
|
|
36
|
+
// 1. Identity Segment (Highest Priority)
|
|
28
37
|
if (includeIdentityPreservation) {
|
|
29
38
|
parts.push(isCouple ? IDENTITY_PRESERVATION_COUPLE : IDENTITY_PRESERVATION_CORE);
|
|
30
39
|
}
|
|
31
40
|
|
|
41
|
+
// 2. Transformation Rules (Domain Specific)
|
|
42
|
+
if (isWardrobe) parts.push(WARDROBE_TRANSFORMATION_RULES);
|
|
43
|
+
if (isArtistic) parts.push(ART_STYLE_TRANSFORMATION_RULES);
|
|
44
|
+
if (isRetouch) parts.push(RETOUCH_TRANSFORMATION_RULES);
|
|
45
|
+
|
|
46
|
+
// 3. Technical Standards (Realism vs Artistic)
|
|
32
47
|
if (includePhotoRealism) {
|
|
33
|
-
parts.push(
|
|
48
|
+
parts.push(isArtistic ? ARTISTIC_STANDARDS : TECHNICAL_STANDARDS);
|
|
49
|
+
if (!isArtistic) parts.push(PHOTOREALISTIC_RENDERING);
|
|
34
50
|
}
|
|
35
51
|
|
|
52
|
+
// 4. Pose Guidelines
|
|
36
53
|
if (includePoseGuidelines) {
|
|
37
54
|
parts.push(isCouple ? NATURAL_POSE_GUIDELINES_COUPLE : NATURAL_POSE_GUIDELINES);
|
|
38
55
|
}
|
|
39
56
|
|
|
57
|
+
// 5. Custom Instructions (Appended here to allow overrides)
|
|
40
58
|
if (customInstructions) {
|
|
41
59
|
parts.push(customInstructions);
|
|
42
60
|
}
|
|
43
61
|
|
|
44
|
-
|
|
62
|
+
// 6. Final Scenario Context
|
|
63
|
+
if (isCouple && !scenarioPrompt.toLowerCase().includes("couple")) {
|
|
64
|
+
parts.push(`SCENARIO DESCRIPTION:\nA photo of a couple, ${scenarioPrompt}`);
|
|
65
|
+
} else {
|
|
66
|
+
parts.push(`SCENARIO DESCRIPTION:\n${scenarioPrompt}`);
|
|
67
|
+
}
|
|
45
68
|
|
|
46
69
|
return parts.join('\n\n');
|
|
47
70
|
};
|
|
@@ -9,6 +9,11 @@ export {
|
|
|
9
9
|
PHOTOREALISTIC_RENDERING,
|
|
10
10
|
NATURAL_POSE_GUIDELINES,
|
|
11
11
|
NATURAL_POSE_GUIDELINES_COUPLE,
|
|
12
|
+
TECHNICAL_STANDARDS,
|
|
13
|
+
ARTISTIC_STANDARDS,
|
|
14
|
+
WARDROBE_TRANSFORMATION_RULES,
|
|
15
|
+
ART_STYLE_TRANSFORMATION_RULES,
|
|
16
|
+
RETOUCH_TRANSFORMATION_RULES,
|
|
12
17
|
} from './domain/base/constants';
|
|
13
18
|
|
|
14
19
|
export {
|
|
@@ -44,11 +44,20 @@ export const CREATIVE_BASE = {
|
|
|
44
44
|
*/
|
|
45
45
|
export const createPhotorealisticPrompt = (
|
|
46
46
|
scene: string,
|
|
47
|
-
options?: {
|
|
47
|
+
options?: {
|
|
48
|
+
customInstructions?: string;
|
|
49
|
+
isCouple?: boolean;
|
|
50
|
+
isArtistic?: boolean;
|
|
51
|
+
isWardrobe?: boolean;
|
|
52
|
+
isRetouch?: boolean;
|
|
53
|
+
},
|
|
48
54
|
): string => {
|
|
49
55
|
return createUnifiedPrompt(scene, {
|
|
50
56
|
customInstructions: options?.customInstructions,
|
|
51
57
|
isCouple: options?.isCouple,
|
|
58
|
+
isArtistic: options?.isArtistic,
|
|
59
|
+
isWardrobe: options?.isWardrobe,
|
|
60
|
+
isRetouch: options?.isRetouch,
|
|
52
61
|
});
|
|
53
62
|
};
|
|
54
63
|
|
|
@@ -58,8 +58,21 @@ export function refinePromptForCouple(prompt: string, isCouple: boolean): string
|
|
|
58
58
|
.replace(/\bidentical\b/gi, "identical for both individuals")
|
|
59
59
|
.replace(/\binstantly recognizable\b/gi, "instantly recognizable as themselves");
|
|
60
60
|
|
|
61
|
+
// Special mapping for common couple scenarios: map "dress/gown" to person 1 and "suit/tuxedo" to person 2
|
|
62
|
+
// this helps the AI map reference images correctly to the scene roles
|
|
63
|
+
if (/\b(dress|gown)\b/i.test(refined) && /\b(suit|tuxedo|linen trousers)\b/i.test(refined)) {
|
|
64
|
+
refined = refined
|
|
65
|
+
.replace(/\b(dress|gown)\b/gi, "$1 (worn by Person 1)")
|
|
66
|
+
.replace(/\b(suit|tuxedo|linen trousers)\b/gi, "$1 (worn by Person 2)");
|
|
67
|
+
|
|
68
|
+
// Also add explicit mapping to the top if not already there
|
|
69
|
+
if (!refined.includes("DIRECTIVE: MAP PHOTO 1 TO PERSON 1")) {
|
|
70
|
+
refined = `DIRECTIVE: MAP PHOTO 1 TO PERSON 1, MAP PHOTO 2 TO PERSON 2\n\n${refined}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
// If it doesn't already have couple-hints, add them at the start
|
|
62
|
-
if (!/\b(couple|both|matching|dual|two people)\b/i.test(refined)) {
|
|
75
|
+
if (!/\b(couple|both|matching|dual|two people)\b/i.test(refined) && !refined.includes("DIRECTIVE:")) {
|
|
63
76
|
refined = `A photo of a couple, ${refined}`;
|
|
64
77
|
}
|
|
65
78
|
return refined;
|