diff --git a/captn/captn_agents/backend/tools/_campaign_creation_team_tools.py b/captn/captn_agents/backend/tools/_campaign_creation_team_tools.py index 5600b85a..7f83d351 100644 --- a/captn/captn_agents/backend/tools/_campaign_creation_team_tools.py +++ b/captn/captn_agents/backend/tools/_campaign_creation_team_tools.py @@ -100,6 +100,27 @@ def descriptions_validator(cls, descriptions: List[str]) -> Optional[List[str]]: ) +class GBBAdGroupAdForCreation(AdGroupAdForCreation): + headlines: Annotated[ + List[ + Annotated[ + str, + "Maximum 30 characters. If keyword insertion is used, '{KeyWord' and '}' are NOT included in the 30 characters.", + ] + ], + Len(min_length=3, max_length=15), + ] + descriptions: Annotated[ + List[ + Annotated[ + str, + "Maximum 90 characters. If keyword insertion is used, '{KeyWord' and '}' are NOT included in the 90 characters.", + ] + ], + Len(min_length=2, max_length=4), + ] + + class AdGroupCriterionForCreation(AdBase): ad_group_id: Optional[ Annotated[str, Field(..., description="Always set this field to None")] @@ -138,6 +159,12 @@ class AdGroupWithAdAndKeywords(BaseModel): keywords: Annotated[List[AdGroupCriterionForCreation], Len(min_length=1)] +class GBBAdGroupWithAdAndKeywords(AdGroupWithAdAndKeywords): + ad_group_ad: Annotated[ + GBBAdGroupAdForCreation, "The ad for the ad group which will be created" + ] + + def _create_ad_group( user_id: int, conv_id: int, diff --git a/captn/captn_agents/backend/tools/_gbb_google_sheets_team_tools.py b/captn/captn_agents/backend/tools/_gbb_google_sheets_team_tools.py index d1b125ad..b2e2c59f 100644 --- a/captn/captn_agents/backend/tools/_gbb_google_sheets_team_tools.py +++ b/captn/captn_agents/backend/tools/_gbb_google_sheets_team_tools.py @@ -40,10 +40,10 @@ ) from ..toolboxes import Toolbox from ._campaign_creation_team_tools import ( - AdGroupAdForCreation, AdGroupCriterionForCreation, AdGroupForCreation, - AdGroupWithAdAndKeywords, + GBBAdGroupAdForCreation, + GBBAdGroupWithAdAndKeywords, _create_ad_group_with_ad_and_keywords, ) from ._functions import ( @@ -347,7 +347,7 @@ def _create_ad_group_with_ad_and_keywords_helper( ad_group_name: str, match_type: str, ad_group_keywords_df: pd.DataFrame, - ad_group_ad: AdGroupAdForCreation, + ad_group_ad: GBBAdGroupAdForCreation, context: GoogleSheetsTeamContext, ) -> None: ad_group = AdGroupForCreation( @@ -374,7 +374,7 @@ def _create_ad_group_with_ad_and_keywords_helper( ) ) - ad_group_with_ad_and_keywords = AdGroupWithAdAndKeywords( + ad_group_with_ad_and_keywords = GBBAdGroupWithAdAndKeywords( customer_id=customer_id, campaign_id=campaign_id, ad_group=ad_group, @@ -837,10 +837,14 @@ def _setup_campaign( for _, row in ads_df[ads_df["campaign name"] == campaign_name].iterrows(): headlines = [ - row[col] for col in row.index if col.lower().startswith("headline") + row[col] + for col in row.index + if col.lower().startswith("headline") and row[col] ] descriptions = [ - row[col] for col in row.index if col.lower().startswith("description") + row[col] + for col in row.index + if col.lower().startswith("description") and row[col] ] path1 = row.get("path 1", None) @@ -848,7 +852,7 @@ def _setup_campaign( final_url = row.get("final url") campaign = created_campaign_names_and_ids[campaign_name] - ad_group_ad = AdGroupAdForCreation( + ad_group_ad = GBBAdGroupAdForCreation( customer_id=customer_id, campaign_id=campaign_id, status="ENABLED", diff --git a/pyproject.toml b/pyproject.toml index 1a160f3e..77d8d918 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,7 @@ lint = [ "mypy==1.11.2", "black==24.4.2", "isort>=5", - "ruff==0.6.1", + "ruff==0.6.3", "pyupgrade-directories", "bandit==1.7.9", "semgrep==1.78.0", @@ -90,10 +90,10 @@ benchmarking = [ ] agents = [ - "fastapi==0.111.1", + "fastapi==0.112.2", "APScheduler==3.10.4", "prisma==0.13.1", - "google-ads==24.1.0", + "google-ads==25.0.0", "httpx==0.27.0", "uvicorn==0.30.6", "python-dotenv==1.0.1", @@ -104,14 +104,15 @@ agents = [ "pydantic==2.8.2", "tenacity==9.0.0", "prometheus-client==0.20.0", - "opentelemetry-distro==0.47b0", - "opentelemetry-instrumentation-fastapi==0.47b0", - "opentelemetry-instrumentation-logging==0.47b0", - "opentelemetry-exporter-otlp==1.26.0", + "opentelemetry-distro==0.48b0", + "opentelemetry-instrumentation-fastapi==0.48b0", + "opentelemetry-instrumentation-logging==0.48b0", + "opentelemetry-exporter-otlp==1.27.0", "openpyxl==3.1.5", "aiofiles==24.1.0", "fastagency[studio]@git+https://github.com/airtai/fastagency.git@main", "markdownify==0.13.1", + "python-multipart==0.0.9", ] dev = [ diff --git a/tests/ci/captn/captn_agents/backend/tools/test_campaign_creation_team_tools.py b/tests/ci/captn/captn_agents/backend/tools/test_campaign_creation_team_tools.py index ee112249..0f75d3d6 100644 --- a/tests/ci/captn/captn_agents/backend/tools/test_campaign_creation_team_tools.py +++ b/tests/ci/captn/captn_agents/backend/tools/test_campaign_creation_team_tools.py @@ -12,6 +12,7 @@ from captn.captn_agents.backend.toolboxes.base import Toolbox from captn.captn_agents.backend.tools._campaign_creation_team_tools import ( AdGroupAdForCreation, + GBBAdGroupAdForCreation, _remove_resources, create_campaign_creation_team_toolbox, ) @@ -309,3 +310,37 @@ def test_maximum_headline_string_length(self, headline, expected): final_url="https://www.example.com", status="ENABLED", ) + + +class TestGBBModels: + @pytest.mark.parametrize( + ("headlines", "expected"), + [ + (["H1", "H2", "H3", "H4"], None), + (["H1", "H2"], ValidationError), + (["H1", "H2", "H3", "H" * 31], ValueError), + ], + ) + def test_gbb_ad_group_ad_for_creation( + self, headlines: List[str], expected: Optional[Exception] + ) -> None: + if expected is None: + ad_group_ad = GBBAdGroupAdForCreation( + customer_id="2222", + headlines=headlines, + descriptions=["D1", "D2", "D3", "D4"], + final_url="https://www.example.com", + status="ENABLED", + ) + assert ad_group_ad.headlines == headlines + + else: + with pytest.raises(expected) as e: + GBBAdGroupAdForCreation( + customer_id="2222", + headlines=headlines, + descriptions=["D1", "D2", "D3", "D4"], + final_url="https://www.example.com", + status="ENABLED", + ) + print(f"Exception: {e}")