ps1811 commited on
Commit
bd40067
·
1 Parent(s): ec1c6ae

Sample data improved. Minor prompts improvements

Browse files
app/ads1/budget_optimizer.py CHANGED
@@ -41,7 +41,7 @@ def build_budget_optimizer_prompt(context: dict) -> str:
41
  name = context.get("campaign_name", "this account")
42
 
43
  return (
44
- f"Write 3 to 5 bullet points of actionable Budget optimization insights for {name}.\n"
45
  "Use simple language. One insight per bullet. Start each line with '- '. No intro sentence.\n\n"
46
  f"Data (JSON):\n{payload}"
47
  )
 
41
  name = context.get("campaign_name", "this account")
42
 
43
  return (
44
+ f"Write 3 to 5 bullet points of actionable Budget optimization methods for {name}.\n"
45
  "Use simple language. One insight per bullet. Start each line with '- '. No intro sentence.\n\n"
46
  f"Data (JSON):\n{payload}"
47
  )
app/ads1/keyword_inspector.py CHANGED
@@ -27,13 +27,12 @@ def build_keyword_features(df: pd.DataFrame) -> pd.DataFrame:
27
  def build_keyword_prompt(context: dict) -> str:
28
  payload = json.dumps(context, indent=2, default=str)
29
 
30
- return f"""
31
- Write 3 to 5 bullet points of actionable keyword performance insights.\n"
32
- "Analyze individual keywords from the data and classify them as winning,
33
- wasted spend, or scaling opportunities using CTR, cost, and conversions. Add reasoning.
34
  "Use simple language. One insight per bullet. Start each line with '- '. No intro sentence.\n\n"
35
  f"Data (JSON):\n{payload}"
36
- """
37
  # -------------------------
38
  # Main runner
39
  # -------------------------
@@ -70,4 +69,4 @@ def run_keyword_inspector(dfs: dict, campaign_name: str | None = None) -> str:
70
  )
71
 
72
  print("📤 [keyword_inspector] result received", flush=True)
73
- return result
 
27
  def build_keyword_prompt(context: dict) -> str:
28
  payload = json.dumps(context, indent=2, default=str)
29
 
30
+ return (
31
+ "Write 3 to 5 bullet points of actionable keyword performance insights.\n"
32
+ "Classify individual keywords as winning, wasted spend, or scaling opportunities using CTR, cost, and conversions.\n"
 
33
  "Use simple language. One insight per bullet. Start each line with '- '. No intro sentence.\n\n"
34
  f"Data (JSON):\n{payload}"
35
+ )
36
  # -------------------------
37
  # Main runner
38
  # -------------------------
 
69
  )
70
 
71
  print("📤 [keyword_inspector] result received", flush=True)
72
+ return result
app/ads1/merge.py CHANGED
@@ -8,7 +8,7 @@ def merge_dfs(real_dfs: dict, sample_dfs: dict) -> dict:
8
 
9
  merged = {}
10
 
11
- for key in real_dfs.keys():
12
  real_df = real_dfs.get(key)
13
  sample_df = sample_dfs.get(key)
14
 
@@ -44,4 +44,4 @@ def merge_dfs(real_dfs: dict, sample_dfs: dict) -> dict:
44
  sample_df["source"] = "sample"
45
  merged[key] = sample_df
46
 
47
- return merged
 
8
 
9
  merged = {}
10
 
11
+ for key in sorted(set(real_dfs.keys()) | set(sample_dfs.keys())):
12
  real_df = real_dfs.get(key)
13
  sample_df = sample_dfs.get(key)
14
 
 
44
  sample_df["source"] = "sample"
45
  merged[key] = sample_df
46
 
47
+ return merged
app/ads1/sample_data.py CHANGED
@@ -1,14 +1,13 @@
1
- import numpy as np
2
  import pandas as pd
3
 
4
- def _rand(low, high, size):
5
- return np.random.randint(low, high, size)
6
 
7
- def _money(low, high, size):
8
- return np.round(np.random.uniform(low, high, size), 2)
 
 
 
 
9
 
10
- def _pick(arr, size):
11
- return np.random.choice(arr, size)
12
 
13
  def generate_sample_campaigns():
14
  campaigns = [
@@ -16,196 +15,197 @@ def generate_sample_campaigns():
16
  "id": 1001,
17
  "name": "Nursery Admissions 2026",
18
  "status": "ENABLED",
19
- "impressions": 120000,
20
- "clicks": 8500,
21
- "cost": 12000.0,
22
- "ctr": 7.08,
23
  "conversions": 420,
24
  },
25
  {
26
  "id": 1002,
27
  "name": "Playgroup Enrollment Campaign",
28
  "status": "ENABLED",
29
- "impressions": 90000,
30
- "clicks": 6200,
31
- "cost": 8000.0,
32
- "ctr": 6.88,
33
- "conversions": 310,
34
  },
35
  {
36
  "id": 1003,
37
  "name": "Summer Camp 2026",
38
  "status": "ENABLED",
39
- "impressions": 150000,
40
- "clicks": 4000,
41
- "cost": 7000.0,
42
- "ctr": 2.66,
43
- "conversions": 180,
44
  },
45
  {
46
  "id": 1004,
47
  "name": "School Tour Booking Campaign",
48
  "status": "ENABLED",
49
- "impressions": 60000,
50
- "clicks": 2200,
51
- "cost": 3500.0,
52
- "ctr": 3.66,
53
- "conversions": 140,
54
  },
55
  ]
56
-
57
  return pd.DataFrame(campaigns)
58
 
59
- # 2. SEARCH TERMS
60
- def generate_sample_search_terms():
61
- positive_intent = [
62
- "nursery admission near me",
63
- "best preschool in Yelahanka",
64
- "play school admission 2026",
65
- "kg admission Bangalore",
66
- "preschool fees near me",
67
- "daycare near Yelahanka",
68
- ]
69
-
70
- negative_intent = [
71
- "free babysitting jobs",
72
- "toy store near me",
73
- "kids games online",
74
- "montessori certification course",
75
- "child psychology course",
76
- "teaching jobs preschool",
77
- ]
78
 
79
- campaigns = [
80
- "Nursery Admissions 2026",
81
- "Playgroup Enrollment Campaign",
82
- "Summer Camp 2026",
83
- "School Tour Booking Campaign",
 
 
 
 
 
 
 
 
 
 
 
 
84
  ]
85
 
86
  rows = []
87
-
88
- for campaign in campaigns:
89
- for term in positive_intent + negative_intent:
90
-
91
- clicks = np.random.randint(5, 250)
92
- impressions = clicks * np.random.randint(5, 60)
93
- cost = round(clicks * np.random.uniform(0.5, 4.0), 2)
94
-
95
- # realistic conversion logic
96
- if term in positive_intent:
97
- conversions = np.random.randint(1, 25)
98
- else:
99
- conversions = np.random.choice([0, 0, 0, 1])
100
-
101
- rows.append({
102
  "search_term": term,
103
- "campaign_name": campaign,
104
- "clicks": clicks,
105
- "impressions": impressions,
106
- "cost": cost,
107
- "conversions": conversions,
108
- })
109
-
110
- return pd.DataFrame(rows)
111
-
112
- # 3. KEYWORDS
113
- def generate_sample_keywords():
114
- keywords = [
115
- "preschool admission",
116
- "nursery school near me",
117
- "play school Bangalore",
118
- "kg admission",
119
- "daycare Yelahanka",
120
- "best preschool",
121
- ]
122
 
123
- campaigns = [
124
- "Nursery Admissions 2026",
125
- "Playgroup Enrollment Campaign",
126
- "Summer Camp 2026",
127
- "School Tour Booking Campaign",
128
- ]
129
 
 
130
  rows = []
 
 
 
 
 
 
 
 
 
131
 
132
- for campaign in campaigns:
133
- for kw in keywords:
134
-
135
- clicks = np.random.randint(50, 500)
136
- impressions = clicks * np.random.randint(10, 80)
137
- cost = round(clicks * np.random.uniform(0.8, 5.0), 2)
138
 
139
- # realistic conversion behavior
140
- if "admission" in kw or "preschool" in kw:
141
- conversions = np.random.randint(5, 40)
142
- else:
143
- conversions = np.random.choice([0, 0, 1, 2, 3])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
- ctr = round((clicks / impressions) * 100, 2)
146
 
147
- rows.append({
148
- "campaign_name": campaign,
149
- "keyword": kw,
150
- "clicks": clicks,
151
- "impressions": impressions,
152
- "cost": cost,
153
- "conversions": conversions,
154
- "ctr": ctr,
155
- })
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  return pd.DataFrame(rows)
158
 
159
- # ==================================================
160
- # 4. HOURLY (OPTIONAL BUT MATCHES REAL STRUCTURE)
161
- # ==================================================
162
 
163
  def generate_sample_hourly():
164
- hours = list(range(24))
165
  rows = []
166
-
167
- for campaign in [
168
- "Nursery Admissions 2026",
169
- "Playgroup Enrollment Campaign",
170
- "Summer Camp 2026",
171
- "School Tour Booking Campaign",
172
- ]:
173
- for h in hours:
174
- clicks = np.random.randint(0, 80)
175
- impressions = clicks * np.random.randint(5, 30)
176
- cost = round(clicks * np.random.uniform(0.2, 3.0), 2)
177
-
178
- rows.append({
179
- "date": "2026-06-01",
180
- "hour": h,
181
- "clicks": clicks,
182
- "impressions": impressions,
183
- "cost": cost,
184
- })
185
-
 
 
 
 
 
 
 
186
  return pd.DataFrame(rows)
187
 
188
 
189
- # ==================================================
190
- # 5. GEO (OPTIONAL BUT MATCHES REAL STRUCTURE)
191
- # ==================================================
192
-
193
  def generate_sample_geo():
194
- countries = ["IN", "AE", "US"]
195
- rows = []
196
-
197
- for c in countries:
198
- rows.append({
199
- "country_id": c,
200
- "clicks": np.random.randint(500, 5000),
201
- "impressions": np.random.randint(10000, 100000),
202
- "cost": round(np.random.uniform(500, 5000), 2),
203
- })
204
-
205
  return pd.DataFrame(rows)
206
 
207
 
208
- # 4. MASTER GENERATOR
209
  def generate_sample_dfs():
210
  return {
211
  "campaigns": generate_sample_campaigns(),
@@ -213,6 +213,6 @@ def generate_sample_dfs():
213
  "keywords": generate_sample_keywords(),
214
  "hourly": generate_sample_hourly(),
215
  "geo": generate_sample_geo(),
216
- "devices": pd.DataFrame(), # optional placeholder
217
- "recommendations": pd.DataFrame(), # optional placeholder
218
- }
 
 
1
  import pandas as pd
2
 
 
 
3
 
4
+ CAMPAIGNS = [
5
+ "Nursery Admissions 2026",
6
+ "Playgroup Enrollment Campaign",
7
+ "Summer Camp 2026",
8
+ "School Tour Booking Campaign",
9
+ ]
10
 
 
 
11
 
12
  def generate_sample_campaigns():
13
  campaigns = [
 
15
  "id": 1001,
16
  "name": "Nursery Admissions 2026",
17
  "status": "ENABLED",
18
+ "impressions": 118000,
19
+ "clicks": 8600,
20
+ "cost": 10450.0,
21
+ "ctr": 7.29,
22
  "conversions": 420,
23
  },
24
  {
25
  "id": 1002,
26
  "name": "Playgroup Enrollment Campaign",
27
  "status": "ENABLED",
28
+ "impressions": 76000,
29
+ "clicks": 4300,
30
+ "cost": 9800.0,
31
+ "ctr": 5.66,
32
+ "conversions": 62,
33
  },
34
  {
35
  "id": 1003,
36
  "name": "Summer Camp 2026",
37
  "status": "ENABLED",
38
+ "impressions": 132000,
39
+ "clicks": 5100,
40
+ "cost": 8600.0,
41
+ "ctr": 3.86,
42
+ "conversions": 105,
43
  },
44
  {
45
  "id": 1004,
46
  "name": "School Tour Booking Campaign",
47
  "status": "ENABLED",
48
+ "impressions": 54000,
49
+ "clicks": 2300,
50
+ "cost": 3200.0,
51
+ "ctr": 4.26,
52
+ "conversions": 145,
53
  },
54
  ]
 
55
  return pd.DataFrame(campaigns)
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
+ def _search_rows_for_campaign(campaign_name, multiplier=1.0):
59
+ base_rows = [
60
+ # Clear high-intent / scale candidates
61
+ ("nursery admission near me", 180, 4200, 260.0, 22),
62
+ ("preschool fees near me", 140, 3500, 190.0, 18),
63
+ ("best preschool in Yelahanka", 125, 2800, 210.0, 16),
64
+ ("school tour booking near me", 90, 1800, 135.0, 14),
65
+ ("kg admission Bangalore", 155, 3900, 245.0, 15),
66
+ # Investigate: engagement but weak conversion
67
+ ("daycare near Yelahanka", 170, 5200, 380.0, 2),
68
+ ("play school admission 2026", 210, 6100, 430.0, 3),
69
+ # Clear negative/waste terms
70
+ ("free babysitting jobs", 190, 5000, 620.0, 0),
71
+ ("toy store near me", 160, 4300, 510.0, 0),
72
+ ("kids games online", 135, 3600, 420.0, 0),
73
+ ("montessori certification course", 155, 4100, 540.0, 0),
74
+ ("teaching jobs preschool", 145, 3700, 460.0, 0),
75
  ]
76
 
77
  rows = []
78
+ for idx, (term, clicks, impressions, cost, conversions) in enumerate(base_rows, start=1):
79
+ rows.append(
80
+ {
 
 
 
 
 
 
 
 
 
 
 
 
81
  "search_term": term,
82
+ "campaign_name": campaign_name,
83
+ "clicks": int(round(clicks * multiplier)),
84
+ "impressions": int(round(impressions * multiplier)),
85
+ "cost": round(cost * multiplier, 2),
86
+ "conversions": int(round(conversions * multiplier)),
87
+ }
88
+ )
89
+ return rows
 
 
 
 
 
 
 
 
 
 
 
90
 
 
 
 
 
 
 
91
 
92
+ def generate_sample_search_terms():
93
  rows = []
94
+ multipliers = {
95
+ "Nursery Admissions 2026": 1.15,
96
+ "Playgroup Enrollment Campaign": 0.85,
97
+ "Summer Camp 2026": 0.75,
98
+ "School Tour Booking Campaign": 1.0,
99
+ }
100
+ for campaign in CAMPAIGNS:
101
+ rows.extend(_search_rows_for_campaign(campaign, multipliers[campaign]))
102
+ return pd.DataFrame(rows)
103
 
 
 
 
 
 
 
104
 
105
+ def _keyword_rows_for_campaign(campaign_name, profile):
106
+ if profile == "winner":
107
+ return [
108
+ ("preschool admission", 720, 14800, 820.0, 54),
109
+ ("nursery school near me", 510, 9400, 610.0, 38),
110
+ ("best preschool", 430, 7600, 520.0, 34),
111
+ ("kg admission", 390, 7000, 480.0, 29),
112
+ ("daycare Yelahanka", 280, 8100, 560.0, 4),
113
+ ("play school Bangalore", 330, 9800, 690.0, 0),
114
+ ]
115
+ if profile == "drain":
116
+ return [
117
+ ("preschool admission", 620, 14500, 1850.0, 12),
118
+ ("nursery school near me", 540, 12800, 1760.0, 8),
119
+ ("play school Bangalore", 470, 11800, 1620.0, 0),
120
+ ("daycare Yelahanka", 430, 10100, 1490.0, 0),
121
+ ("best preschool", 390, 9200, 1380.0, 2),
122
+ ("kg admission", 250, 7400, 860.0, 1),
123
+ ]
124
+ if profile == "investigate":
125
+ return [
126
+ ("preschool admission", 360, 13200, 910.0, 14),
127
+ ("nursery school near me", 300, 10100, 780.0, 9),
128
+ ("summer camp for kids", 560, 22000, 1900.0, 11),
129
+ ("kids activity camp", 480, 21000, 1680.0, 3),
130
+ ("free summer activities", 410, 18000, 1250.0, 0),
131
+ ("art classes for kids", 310, 12000, 940.0, 1),
132
+ ]
133
+ return [
134
+ ("school tour booking", 310, 6200, 340.0, 28),
135
+ ("book school visit", 250, 5100, 290.0, 22),
136
+ ("preschool admission", 210, 4800, 260.0, 16),
137
+ ("nursery school near me", 180, 4200, 230.0, 13),
138
+ ("daycare Yelahanka", 160, 6100, 410.0, 2),
139
+ ("teaching jobs preschool", 190, 7800, 520.0, 0),
140
+ ]
141
 
 
142
 
143
+ def generate_sample_keywords():
144
+ profiles = {
145
+ "Nursery Admissions 2026": "winner",
146
+ "Playgroup Enrollment Campaign": "drain",
147
+ "Summer Camp 2026": "investigate",
148
+ "School Tour Booking Campaign": "scale",
149
+ }
 
 
150
 
151
+ rows = []
152
+ for campaign in CAMPAIGNS:
153
+ for keyword, clicks, impressions, cost, conversions in _keyword_rows_for_campaign(campaign, profiles[campaign]):
154
+ rows.append(
155
+ {
156
+ "campaign_name": campaign,
157
+ "keyword": keyword,
158
+ "clicks": clicks,
159
+ "impressions": impressions,
160
+ "cost": cost,
161
+ "conversions": conversions,
162
+ "ctr": round((clicks / impressions) * 100, 2) if impressions else 0,
163
+ }
164
+ )
165
  return pd.DataFrame(rows)
166
 
 
 
 
167
 
168
  def generate_sample_hourly():
 
169
  rows = []
170
+ dates = pd.date_range("2026-06-01", periods=14, freq="D")
171
+ campaign_click_bases = {
172
+ "Nursery Admissions 2026": 18,
173
+ "Playgroup Enrollment Campaign": 10,
174
+ "Summer Camp 2026": 13,
175
+ "School Tour Booking Campaign": 8,
176
+ }
177
+
178
+ for day_index, date in enumerate(dates):
179
+ trend_boost = day_index * 0.08
180
+ for campaign in CAMPAIGNS:
181
+ base = campaign_click_bases[campaign]
182
+ for hour in range(24):
183
+ daypart = 1.4 if 8 <= hour <= 12 or 18 <= hour <= 21 else 0.55
184
+ clicks = int(round(base * daypart * (1 + trend_boost)))
185
+ impressions = clicks * 28
186
+ cost = round(clicks * (1.45 if campaign != "Playgroup Enrollment Campaign" else 2.6), 2)
187
+ rows.append(
188
+ {
189
+ "date": date.strftime("%Y-%m-%d"),
190
+ "hour": hour,
191
+ "campaign_name": campaign,
192
+ "clicks": clicks,
193
+ "impressions": impressions,
194
+ "cost": cost,
195
+ }
196
+ )
197
  return pd.DataFrame(rows)
198
 
199
 
 
 
 
 
200
  def generate_sample_geo():
201
+ rows = [
202
+ {"country_id": "IN", "clicks": 6200, "impressions": 128000, "cost": 7600.0},
203
+ {"country_id": "AE", "clicks": 840, "impressions": 21000, "cost": 1380.0},
204
+ {"country_id": "US", "clicks": 360, "impressions": 11200, "cost": 980.0},
205
+ ]
 
 
 
 
 
 
206
  return pd.DataFrame(rows)
207
 
208
 
 
209
  def generate_sample_dfs():
210
  return {
211
  "campaigns": generate_sample_campaigns(),
 
213
  "keywords": generate_sample_keywords(),
214
  "hourly": generate_sample_hourly(),
215
  "geo": generate_sample_geo(),
216
+ "devices": pd.DataFrame(),
217
+ "recommendations": pd.DataFrame(),
218
+ }