sushilideaclan01 commited on
Commit
29066e0
·
1 Parent(s): 254d33c

Enhance extensive ad generation with custom niche support

Browse files

- Updated the ExtensiveGenerateRequest model to include an optional custom_niche field for enhanced flexibility in ad generation.
- Modified the generate_extensive function to validate custom niche input when 'others' is selected as the niche.
- Adjusted frontend components to accommodate the new custom_niche field, including validation in the ExtensiveForm and updates to the GeneratePage.
- Updated API endpoints to handle the new custom_niche parameter, ensuring seamless integration across the application.

frontend/app/generate/page.tsx CHANGED
@@ -365,6 +365,7 @@ export default function GeneratePage() {
365
 
366
  const handleExtensiveGenerate = async (data: {
367
  niche: Niche;
 
368
  target_audience?: string;
369
  offer?: string;
370
  num_images: number;
 
365
 
366
  const handleExtensiveGenerate = async (data: {
367
  niche: Niche;
368
+ custom_niche?: string;
369
  target_audience?: string;
370
  offer?: string;
371
  num_images: number;
frontend/components/generation/ExtensiveForm.tsx CHANGED
@@ -10,19 +10,32 @@ import { IMAGE_MODELS } from "@/lib/constants/models";
10
  import type { Niche } from "@/types/api";
11
 
12
  const extensiveSchema = z.object({
13
- niche: z.enum(["home_insurance", "glp1"]),
 
14
  target_audience: z.string().optional(),
15
  offer: z.string().optional(),
16
  num_images: z.number().min(1).max(3),
17
  num_strategies: z.number().min(1).max(10),
18
  image_model: z.string().nullable().optional(),
19
- });
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  type ExtensiveFormData = z.infer<typeof extensiveSchema>;
22
 
23
  interface ExtensiveFormProps {
24
  onSubmit: (data: {
25
  niche: Niche;
 
26
  target_audience?: string;
27
  offer?: string;
28
  num_images: number;
@@ -45,6 +58,7 @@ export const ExtensiveForm: React.FC<ExtensiveFormProps> = ({
45
  resolver: zodResolver(extensiveSchema),
46
  defaultValues: {
47
  niche: "home_insurance" as Niche,
 
48
  target_audience: "",
49
  offer: "",
50
  num_images: 1,
@@ -55,6 +69,7 @@ export const ExtensiveForm: React.FC<ExtensiveFormProps> = ({
55
 
56
  const numImages = watch("num_images");
57
  const numStrategies = watch("num_strategies");
 
58
 
59
  return (
60
  <Card variant="glass">
@@ -71,11 +86,29 @@ export const ExtensiveForm: React.FC<ExtensiveFormProps> = ({
71
  options={[
72
  { value: "home_insurance", label: "Home Insurance" },
73
  { value: "glp1", label: "GLP-1" },
 
74
  ]}
75
  error={errors.niche?.message}
76
  {...register("niche")}
77
  />
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  <div>
80
  <label className="block text-sm font-semibold text-gray-700 mb-2">
81
  Target Audience
 
10
  import type { Niche } from "@/types/api";
11
 
12
  const extensiveSchema = z.object({
13
+ niche: z.enum(["home_insurance", "glp1", "others"]),
14
+ custom_niche: z.string().optional(),
15
  target_audience: z.string().optional(),
16
  offer: z.string().optional(),
17
  num_images: z.number().min(1).max(3),
18
  num_strategies: z.number().min(1).max(10),
19
  image_model: z.string().nullable().optional(),
20
+ }).refine(
21
+ (data) => {
22
+ if (data.niche === "others") {
23
+ return data.custom_niche && data.custom_niche.trim().length > 0;
24
+ }
25
+ return true;
26
+ },
27
+ {
28
+ message: "Please enter your custom niche",
29
+ path: ["custom_niche"],
30
+ }
31
+ );
32
 
33
  type ExtensiveFormData = z.infer<typeof extensiveSchema>;
34
 
35
  interface ExtensiveFormProps {
36
  onSubmit: (data: {
37
  niche: Niche;
38
+ custom_niche?: string;
39
  target_audience?: string;
40
  offer?: string;
41
  num_images: number;
 
58
  resolver: zodResolver(extensiveSchema),
59
  defaultValues: {
60
  niche: "home_insurance" as Niche,
61
+ custom_niche: "",
62
  target_audience: "",
63
  offer: "",
64
  num_images: 1,
 
69
 
70
  const numImages = watch("num_images");
71
  const numStrategies = watch("num_strategies");
72
+ const selectedNiche = watch("niche");
73
 
74
  return (
75
  <Card variant="glass">
 
86
  options={[
87
  { value: "home_insurance", label: "Home Insurance" },
88
  { value: "glp1", label: "GLP-1" },
89
+ { value: "others", label: "Others" },
90
  ]}
91
  error={errors.niche?.message}
92
  {...register("niche")}
93
  />
94
 
95
+ {selectedNiche === "others" && (
96
+ <div>
97
+ <label className="block text-sm font-semibold text-gray-700 mb-2">
98
+ Custom Niche <span className="text-red-500">*</span>
99
+ </label>
100
+ <input
101
+ type="text"
102
+ className="w-full px-4 py-3 rounded-xl border-2 border-gray-300 bg-white/80 backdrop-blur-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-250"
103
+ placeholder="e.g., Pet Insurance, Solar Panels, Fitness Supplements"
104
+ {...register("custom_niche")}
105
+ />
106
+ {errors.custom_niche && (
107
+ <p className="text-red-500 text-xs mt-1">{errors.custom_niche.message}</p>
108
+ )}
109
+ </div>
110
+ )}
111
+
112
  <div>
113
  <label className="block text-sm font-semibold text-gray-700 mb-2">
114
  Target Audience
frontend/lib/api/endpoints.ts CHANGED
@@ -72,6 +72,7 @@ export const generateMatrixAd = async (params: {
72
  // Extensive Endpoint
73
  export const generateExtensiveAd = async (params: {
74
  niche: Niche;
 
75
  target_audience?: string;
76
  offer?: string;
77
  num_images: number;
@@ -83,6 +84,7 @@ export const generateExtensiveAd = async (params: {
83
  niche: params.niche,
84
  num_images: params.num_images || 1,
85
  num_strategies: params.num_strategies || 1,
 
86
  ...(params.target_audience && { target_audience: params.target_audience }),
87
  ...(params.offer && { offer: params.offer }),
88
  ...(params.image_model && { image_model: params.image_model }),
 
72
  // Extensive Endpoint
73
  export const generateExtensiveAd = async (params: {
74
  niche: Niche;
75
+ custom_niche?: string;
76
  target_audience?: string;
77
  offer?: string;
78
  num_images: number;
 
84
  niche: params.niche,
85
  num_images: params.num_images || 1,
86
  num_strategies: params.num_strategies || 1,
87
+ ...(params.custom_niche && { custom_niche: params.custom_niche }),
88
  ...(params.target_audience && { target_audience: params.target_audience }),
89
  ...(params.offer && { offer: params.offer }),
90
  ...(params.image_model && { image_model: params.image_model }),
frontend/types/api.ts CHANGED
@@ -1,6 +1,6 @@
1
  // API Response Types based on FastAPI backend
2
 
3
- export type Niche = "home_insurance" | "glp1";
4
 
5
  export interface ImageResult {
6
  filename?: string | null;
 
1
  // API Response Types based on FastAPI backend
2
 
3
+ export type Niche = "home_insurance" | "glp1" | "others";
4
 
5
  export interface ImageResult {
6
  filename?: string | null;
main.py CHANGED
@@ -1104,8 +1104,12 @@ async def get_compatible_concepts(angle_key: str):
1104
 
1105
  class ExtensiveGenerateRequest(BaseModel):
1106
  """Request for extensive generation."""
1107
- niche: Literal["home_insurance", "glp1"] = Field(
1108
- description="Target niche"
 
 
 
 
1109
  )
1110
  target_audience: Optional[str] = Field(
1111
  default=None,
@@ -1151,10 +1155,24 @@ async def generate_extensive(
1151
  5. Generates images for each strategy
1152
 
1153
  Returns all generated ads from all strategies (like batch generation).
 
 
 
1154
  """
1155
  try:
 
 
 
 
 
 
 
 
 
 
 
1156
  results = await ad_generator.generate_ad_extensive(
1157
- niche=request.niche,
1158
  target_audience=request.target_audience,
1159
  offer=request.offer,
1160
  num_images=request.num_images,
@@ -1167,6 +1185,8 @@ async def generate_extensive(
1167
  count=len(results),
1168
  ads=results
1169
  )
 
 
1170
  except Exception as e:
1171
  raise HTTPException(status_code=500, detail=str(e))
1172
 
 
1104
 
1105
  class ExtensiveGenerateRequest(BaseModel):
1106
  """Request for extensive generation."""
1107
+ niche: str = Field(
1108
+ description="Target niche: home_insurance, glp1, or others"
1109
+ )
1110
+ custom_niche: Optional[str] = Field(
1111
+ default=None,
1112
+ description="Custom niche name when 'others' is selected"
1113
  )
1114
  target_audience: Optional[str] = Field(
1115
  default=None,
 
1155
  5. Generates images for each strategy
1156
 
1157
  Returns all generated ads from all strategies (like batch generation).
1158
+
1159
+ Supports custom niches via the 'others' option - when niche is 'others',
1160
+ custom_niche field must be provided with the custom niche name.
1161
  """
1162
  try:
1163
+ # Determine effective niche
1164
+ if request.niche == "others":
1165
+ if not request.custom_niche or not request.custom_niche.strip():
1166
+ raise HTTPException(
1167
+ status_code=400,
1168
+ detail="custom_niche is required when niche is 'others'"
1169
+ )
1170
+ effective_niche = request.custom_niche.strip()
1171
+ else:
1172
+ effective_niche = request.niche
1173
+
1174
  results = await ad_generator.generate_ad_extensive(
1175
+ niche=effective_niche,
1176
  target_audience=request.target_audience,
1177
  offer=request.offer,
1178
  num_images=request.num_images,
 
1185
  count=len(results),
1186
  ads=results
1187
  )
1188
+ except HTTPException:
1189
+ raise
1190
  except Exception as e:
1191
  raise HTTPException(status_code=500, detail=str(e))
1192