Skip to content

Commit ebeb47d

Browse files
dmoonatDeepak Moonatlavinigam-gcp
authored
update retail-ai-location-strategy agent (#755)
Co-authored-by: Deepak Moonat <dmoonat@google.com> Co-authored-by: Lavi Nigam <lavinigam@google.com>
1 parent cd08b56 commit ebeb47d

File tree

27 files changed

+2377
-564
lines changed

27 files changed

+2377
-564
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ downloads/
1818
eggs/
1919
.eggs/
2020
lib/
21+
!**/frontend/lib/
2122
lib64/
2223
parts/
2324
sdist/
@@ -142,6 +143,7 @@ env.bak/
142143
venv.bak/
143144
.env*
144145
!.env.example
146+
!.env.local.example
145147

146148
# Spyder project settings
147149
.spyderproject

python/agents/retail-ai-location-strategy/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ ag-ui-install:
2828
@echo "Installing AG-UI backend dependencies..."
2929
pip install -r app/frontend/backend/requirements.txt
3030
@echo "Installing AG-UI frontend dependencies..."
31-
cd app/frontend && npm install --legacy-peer-deps
31+
cd app/frontend && npm install
3232
@if [ ! -f app/frontend/.env.local ]; then \
3333
cp app/frontend/.env.local.example app/frontend/.env.local; \
3434
echo "Created app/frontend/.env.local from example"; \

python/agents/retail-ai-location-strategy/README.md

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,35 @@ A multi-agent AI pipeline for retail site selection, built with [Google Agent De
99
</tr>
1010
</thead>
1111
<tbody>
12-
<tr>
13-
<td>🏗️</td>
14-
<td><strong>Production-Ready:</strong> Built with ADK for seamless deployment to <a href="https://cloud.google.com/run">Google Cloud Run</a> and <a href="https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/overview">Vertex AI Agent Engine</a>.</td>
15-
</tr>
1612
<tr>
1713
<td>🔍</td>
18-
<td><strong>Multi-Agent Pipeline:</strong> 7 specialized agents for market research, competitor mapping, gap analysis, strategy recommendations, and report generation.</td>
14+
<td><strong>Multi-Agent Pipeline:</strong> 7 specialized agents for market research, competitor mapping, gap analysis, strategy synthesis, and report generation.</td>
1915
</tr>
2016
<tr>
2117
<td>🗺️</td>
22-
<td><strong>Real-World Data:</strong> Integrates Google Maps Places API for competitor mapping and live web search for market research.</td>
18+
<td><strong>Real-World Data:</strong> Integrates Google Maps Places API for competitor mapping and Google Search for live market research.</td>
19+
</tr>
20+
<tr>
21+
<td>🐍</td>
22+
<td><strong>Code Execution:</strong> Python/pandas analysis for quantitative gap analysis with viability scoring.</td>
23+
</tr>
24+
<tr>
25+
<td>🎨</td>
26+
<td><strong>AI-Generated Outputs:</strong> Executive HTML reports and infographics via Gemini's native image generation.</td>
27+
</tr>
28+
<tr>
29+
<td>🖥️</td>
30+
<td><strong>AG-UI Frontend:</strong> Optional interactive dashboard with <a href="https://docs.ag-ui.com/">AG-UI Protocol</a> and <a href="https://docs.copilotkit.ai/">CopilotKit</a> for real-time pipeline visualization.</td>
31+
</tr>
32+
<tr>
33+
<td>🏗️</td>
34+
<td><strong>Production-Ready:</strong> Deploy to <a href="https://cloud.google.com/run">Cloud Run</a> or <a href="https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/overview">Vertex AI Agent Engine</a> via <a href="https://goo.gle/agent-starter-pack">Agent Starter Pack</a>.</td>
2335
</tr>
2436
</tbody>
2537
</table>
2638

2739
<p align="center">
28-
<img src="assets/images/hero-image.png" alt="Retail AI Location Strategy - Multi-Agent Pipeline" width="700">
40+
<img src="assets/images/main-intro-image.png" alt="Retail AI Location Strategy - System Architecture" width="800">
2941
</p>
3042

3143
## What It Does
@@ -38,10 +50,6 @@ Given a location and business type, this pipeline automatically:
3850
- Generates strategic recommendations with extended reasoning
3951
- Produces an HTML executive report and visual infographic
4052

41-
<p align="center">
42-
<img src="assets/images/simplified-pipeline.png" alt="7-Stage Pipeline Flow" width="700">
43-
</p>
44-
4553
---
4654

4755
## Getting Started: From Zero to Running Agent in 5 Minutes
@@ -263,6 +271,10 @@ This starts:
263271

264272
Open `http://localhost:3000` to see the interactive dashboard.
265273

274+
<p align="center">
275+
<img src="assets/gifs/ag-ui-demo.gif" alt="AG-UI Frontend Demo" width="700">
276+
</p>
277+
266278
<details>
267279
<summary>Manual Setup (Alternative)</summary>
268280

@@ -275,7 +287,7 @@ python main.py
275287

276288
# Terminal 2: Start the frontend
277289
cd app/frontend
278-
npm install --legacy-peer-deps
290+
npm install
279291
cp .env.local.example .env.local
280292
npm run dev
281293
# Runs at http://localhost:3000
@@ -325,38 +337,52 @@ Each agent reads from and writes to a shared session state, enabling seamless da
325337

326338
```
327339
retail-ai-location-strategy/
328-
├── Makefile # Build and run commands
329-
├── pyproject.toml # Dependencies and package config
330-
├── .env.example # Environment template
331-
├── README.md # This file
332-
├── DEVELOPER_GUIDE.md # Detailed developer documentation
340+
├── Makefile # Build and run commands
341+
├── pyproject.toml # Dependencies and package config
342+
├── .env.example # Environment template
343+
├── README.md # This file
344+
├── DEVELOPER_GUIDE.md # Detailed developer documentation
333345
334-
├── notebook/ # Original Gemini API notebook
346+
├── notebook/ # Original Gemini API notebook
335347
│ └── retail_ai_location_strategy_gemini_3.ipynb
336348
337-
└── app/ # Agent package (exported as root_agent)
338-
├── __init__.py # Exports root_agent for ADK discovery
339-
├── agent.py # SequentialAgent pipeline definition
340-
├── config.py # Model selection and retry config
341-
├── .env # Environment variables (from .env.example)
349+
└── app/ # Agent package (exported as root_agent)
350+
├── __init__.py # Exports root_agent for ADK discovery
351+
├── agent.py # SequentialAgent pipeline definition
352+
├── config.py # Model selection and retry config
353+
├── .env # Environment variables (from .env.example)
342354
343-
├── sub_agents/ # 7 specialized agents
344-
│ ├── intake_agent.py
345-
│ ├── market_research.py
346-
│ ├── competitor_mapping.py
347-
│ ├── gap_analysis.py
348-
│ ├── strategy_advisor.py
349-
│ ├── report_generator.py
350-
│ └── infographic_generator.py
355+
├── sub_agents/ # 7 specialized agents
356+
│ ├── competitor_mapping/
357+
│ │ ├── __init__.py
358+
│ │ └── agent.py
359+
│ ├── gap_analysis/
360+
│ │ ├── __init__.py
361+
│ │ └── agent.py
362+
│ ├── infographic_generator/
363+
│ │ ├── __init__.py
364+
│ │ └── agent.py
365+
│ ├── intake_agent/
366+
│ │ ├── __init__.py
367+
│ │ └── agent.py
368+
│ ├── market_research/
369+
│ │ ├── __init__.py
370+
│ │ └── agent.py
371+
│ ├── report_generator/
372+
│ │ ├── __init__.py
373+
│ │ └── agent.py
374+
│ └── strategy_advisor/
375+
│ ├── __init__.py
376+
│ └── agent.py
351377
352-
├── tools/ # Custom function tools
353-
│ ├── places_search.py # Google Maps Places API
354-
│ ├── html_report_generator.py # Executive report generation
355-
│ └── image_generator.py # Infographic generation
378+
├── tools/ # Custom function tools
379+
│ ├── places_search.py # Google Maps Places API
380+
│ ├── html_report_generator.py # Executive report generation
381+
│ └── image_generator.py # Infographic generation
356382
357-
├── schemas/ # Pydantic output schemas
358-
├── callbacks/ # Pipeline lifecycle callbacks
359-
└── frontend/ # AG-UI interactive dashboard (optional)
383+
├── schemas/ # Pydantic output schemas
384+
├── callbacks/ # Pipeline lifecycle callbacks
385+
└── frontend/ # AG-UI interactive dashboard
360386
```
361387

362388
---

python/agents/retail-ai-location-strategy/app/agent.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,22 @@
4747
"""
4848

4949
from google.adk.agents import SequentialAgent
50+
from google.adk.agents.llm_agent import Agent
51+
from google.adk.tools.agent_tool import AgentTool
5052

51-
from .sub_agents import (
52-
intake_agent,
53-
market_research_agent,
54-
competitor_mapping_agent,
55-
gap_analysis_agent,
56-
strategy_advisor_agent,
57-
report_generator_agent,
58-
infographic_generator_agent,
59-
)
6053

54+
from .sub_agents.intake_agent.agent import intake_agent
55+
from .sub_agents.market_research.agent import market_research_agent
56+
from .sub_agents.competitor_mapping.agent import competitor_mapping_agent
57+
from .sub_agents.gap_analysis.agent import gap_analysis_agent
58+
from .sub_agents.strategy_advisor.agent import strategy_advisor_agent
59+
from .sub_agents.infographic_generator.agent import infographic_generator_agent
60+
from .sub_agents.report_generator.agent import report_generator_agent
6161

62-
# Root agent orchestrating the complete location strategy pipeline
63-
root_agent = SequentialAgent(
62+
from .config import FAST_MODEL, APP_NAME
63+
64+
# location_strategy_pipeline
65+
location_strategy_pipeline = SequentialAgent(
6466
name="LocationStrategyPipeline",
6567
description="""Comprehensive retail location strategy analysis pipeline.
6668
@@ -72,15 +74,14 @@
7274
5. Professional HTML executive report
7375
6. Visual infographic summary
7476
75-
To use, provide:
76-
- target_location: Geographic area to analyze (e.g., "Indiranagar, Bangalore")
77-
- business_type: Type of business (e.g., "coffee shop", "bakery", "gym")
77+
To use, get the following details:
78+
- target_location: {target_location}
79+
- business_type: {business_type}
7880
7981
The analysis runs automatically through all stages and produces artifacts
8082
including JSON report, HTML report, and infographic image.
8183
""",
8284
sub_agents=[
83-
intake_agent, # Part 0: Parse user request
8485
market_research_agent, # Part 1: Market research with search
8586
competitor_mapping_agent, # Part 2A: Competitor mapping with Maps
8687
gap_analysis_agent, # Part 2B: Gap analysis with code exec
@@ -90,4 +91,18 @@
9091
],
9192
)
9293

93-
94+
# Root agent orchestrating the complete location strategy pipeline
95+
root_agent = Agent(
96+
model=FAST_MODEL,
97+
name=APP_NAME,
98+
description='A strategic partner for retail businesses, guiding them to optimal physical locations that foster growth and profitability.',
99+
instruction="""Your primary role is to orchestrate the retail location analysis.
100+
1. Start by greeting the user.
101+
2. Check if the `TARGET_LOCATION` (Geographic area to analyze (e.g., "Indiranagar, Bangalore")) and `BUSINESS_TYPE` (Type of business (e.g., "coffee shop", "bakery", "gym")) have been provided.
102+
3. If they are missing, **ask the user clarifying questions to get the required information.**
103+
4. Once you have the necessary details, call the `IntakeAgent` tool to process them.
104+
5. After the `IntakeAgent` is successful, delegate the full analysis to the `LocationStrategyPipeline`.
105+
Your main function is to manage this workflow conversationally.""",
106+
sub_agents=[location_strategy_pipeline],
107+
tools = [AgentTool(intake_agent)], # Part 0: Parse user request
108+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Backend URL - the FastAPI server running the ADK agent
2+
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Utility to extract code blocks from markdown content.
3+
* Used primarily for parsing gap_analysis output which contains both code and results.
4+
*/
5+
6+
export interface CodeBlock {
7+
language: string;
8+
code: string;
9+
}
10+
11+
export interface ParsedContent {
12+
codeBlocks: CodeBlock[];
13+
textContent: string; // content with code blocks removed
14+
}
15+
16+
/**
17+
* Parses markdown content to extract code blocks and remaining text.
18+
* Handles fenced code blocks with language specifiers (```python, ```js, etc.)
19+
*/
20+
export function parseCodeBlocks(content: string): ParsedContent {
21+
if (!content) {
22+
return { codeBlocks: [], textContent: "" };
23+
}
24+
25+
const codeBlocks: CodeBlock[] = [];
26+
27+
// Regex to match fenced code blocks: ```language\ncode\n```
28+
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
29+
30+
let match;
31+
while ((match = codeBlockRegex.exec(content)) !== null) {
32+
codeBlocks.push({
33+
language: match[1] || "text",
34+
code: match[2].trim(),
35+
});
36+
}
37+
38+
// Remove code blocks from content to get text-only content
39+
const textContent = content
40+
.replace(codeBlockRegex, "")
41+
.replace(/\n{3,}/g, "\n\n") // Clean up extra newlines
42+
.trim();
43+
44+
return { codeBlocks, textContent };
45+
}
46+
47+
/**
48+
* Extracts just the Python code from content (for gap analysis).
49+
*/
50+
export function extractPythonCode(content: string): string {
51+
const { codeBlocks } = parseCodeBlocks(content);
52+
53+
// Find Python code blocks
54+
const pythonBlocks = codeBlocks.filter(
55+
(block) => block.language.toLowerCase() === "python"
56+
);
57+
58+
if (pythonBlocks.length > 0) {
59+
return pythonBlocks.map((b) => b.code).join("\n\n");
60+
}
61+
62+
// Fallback: return all code blocks
63+
return codeBlocks.map((b) => b.code).join("\n\n");
64+
}
65+
66+
/**
67+
* Gets the text content without code blocks.
68+
*/
69+
export function getTextContent(content: string): string {
70+
const { textContent } = parseCodeBlocks(content);
71+
return textContent;
72+
}

0 commit comments

Comments
 (0)