Updated search optimizer prompt
Browse files
app/ads1/search_term_optimizer.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import pandas as pd
|
| 2 |
from app.recs.generate import TARGET_CPL, generate_explanation, is_bad_llm_output
|
|
|
|
| 3 |
|
| 4 |
def build_search_term_features(df: pd.DataFrame) -> pd.DataFrame:
|
| 5 |
df = df.copy()
|
|
@@ -35,42 +36,52 @@ def detect_negative_terms(df):
|
|
| 35 |
def detect_review_terms(df):
|
| 36 |
return df[
|
| 37 |
(df["clicks"] >= 10) &
|
| 38 |
-
(df["ctr"] <
|
| 39 |
(df["conversions"] == 0)
|
| 40 |
]
|
| 41 |
|
| 42 |
def detect_scaling_terms(df):
|
| 43 |
return df[(df["conversions"] > 0)].sort_values("cpa", ascending=True)
|
| 44 |
|
| 45 |
-
def classify_search_term(dfs: dict) -> dict:
|
| 46 |
-
|
| 47 |
-
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
{context['review_terms']}
|
| 67 |
-
WINNERS:
|
| 68 |
-
{context['winning_terms']}
|
| 69 |
-
Return:
|
| 70 |
-
- 3 actions to reduce waste
|
| 71 |
-
- 2 scaling opportunities
|
| 72 |
-
- 2 keyword negatives to add immediately
|
| 73 |
-
"""
|
| 74 |
|
| 75 |
def build_search_optimizer_context(dfs: dict, campaign_name: str | None = None):
|
| 76 |
df = _search_terms_for_campaign(dfs, campaign_name)
|
|
|
|
| 1 |
import pandas as pd
|
| 2 |
from app.recs.generate import TARGET_CPL, generate_explanation, is_bad_llm_output
|
| 3 |
+
import json
|
| 4 |
|
| 5 |
def build_search_term_features(df: pd.DataFrame) -> pd.DataFrame:
|
| 6 |
df = df.copy()
|
|
|
|
| 36 |
def detect_review_terms(df):
|
| 37 |
return df[
|
| 38 |
(df["clicks"] >= 10) &
|
| 39 |
+
(df["ctr"] < 2) &
|
| 40 |
(df["conversions"] == 0)
|
| 41 |
]
|
| 42 |
|
| 43 |
def detect_scaling_terms(df):
|
| 44 |
return df[(df["conversions"] > 0)].sort_values("cpa", ascending=True)
|
| 45 |
|
| 46 |
+
# def classify_search_term(dfs: dict) -> dict:
|
| 47 |
+
# df = dfs["search_terms"].copy()
|
| 48 |
+
# df = build_search_term_features(df)
|
| 49 |
|
| 50 |
+
# negatives = detect_negative_terms(df)
|
| 51 |
+
# review = detect_review_terms(df)
|
| 52 |
+
# winners = detect_scaling_terms(df)
|
| 53 |
|
| 54 |
+
# return {
|
| 55 |
+
# "negative_keywords": negatives.to_dict("records"),
|
| 56 |
+
# "review_terms": review.to_dict("records"),
|
| 57 |
+
# "winning_terms": winners.head(10).to_dict("records"),
|
| 58 |
+
# }
|
| 59 |
+
|
| 60 |
+
def build_search_optimizer_prompt(context: dict) -> str:
|
| 61 |
+
# Convert data to clean JSON string strings for better LLM readability
|
| 62 |
+
neg_json = json.dumps(context['negative_keywords'], indent=2)
|
| 63 |
+
rev_json = json.dumps(context['review_terms'], indent=2)
|
| 64 |
+
win_json = json.dumps(context['winning_terms'], indent=2)
|
| 65 |
+
|
| 66 |
+
return f"""You are an expert Google Ads optimization engine.
|
| 67 |
+
Analyze the following three categories of search terms for the campaign "{context['campaign_name'] or 'All Campaigns'}":
|
| 68 |
+
|
| 69 |
+
### HIGH WASTE TERMS (Add as negatives)
|
| 70 |
+
{neg_json}
|
| 71 |
+
|
| 72 |
+
### LOW CTR REVIEW TERMS (Needs attention)
|
| 73 |
+
{rev_json}
|
| 74 |
+
|
| 75 |
+
### WINNING SCALING TERMS (Profitable)
|
| 76 |
+
{win_json}
|
| 77 |
|
| 78 |
+
Provide your analysis in a strict JSON format with this exact schema:
|
| 79 |
+
{{
|
| 80 |
+
"waste_reduction_actions": ["action 1", "action 2"],
|
| 81 |
+
"scaling_opportunities": ["opportunity 1", "opportunity 2"],
|
| 82 |
+
"immediate_negative_keywords": ["keyword 1", "keyword 2"]
|
| 83 |
+
}}
|
| 84 |
+
Return ONLY valid JSON. Do not include markdown code blocks, explanations, or extra text."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
def build_search_optimizer_context(dfs: dict, campaign_name: str | None = None):
|
| 87 |
df = _search_terms_for_campaign(dfs, campaign_name)
|