Kani-18 commited on
Commit
914954d
·
1 Parent(s): 424f9ef

Initial commit with agent code and project structure

Browse files
multi_tool_agent/__pycache__/agent.cpython-311.pyc CHANGED
Binary files a/multi_tool_agent/__pycache__/agent.cpython-311.pyc and b/multi_tool_agent/__pycache__/agent.cpython-311.pyc differ
 
multi_tool_agent/agent.py CHANGED
@@ -1,69 +1,136 @@
1
- from google.adk.agents import LlmAgent
2
- from google.adk.tools import google_search
3
  from firecrawl import FirecrawlApp
4
- import google.genai as genai
5
  from dotenv import load_dotenv
6
- import os
7
- import json
8
- import time
9
 
10
- # Load environment variables
11
  load_dotenv()
12
  FIRECRAWL_API_KEY = os.getenv("FIRECRAWL_API_KEY")
13
-
14
- # Setup Firecrawl
15
  firecrawl_app = FirecrawlApp(api_key=FIRECRAWL_API_KEY)
16
 
17
- # Setup Gemini model
18
- genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
19
- gemini_model = genai.GenerativeModel("gemini-2.0-pro")
 
 
 
 
 
 
 
20
 
21
- # Define a custom function to scrape and combine content
22
- def scrape_multiple_sites(urls):
23
- combined_content = ""
 
 
 
 
 
 
 
 
 
 
 
 
24
  for url in urls:
25
  try:
26
- response = firecrawl_app.scrape_url(
27
- url=url,
28
- formats=["markdown"],
29
- only_main_content=True,
30
- timeout=120000
31
- )
32
- if hasattr(response, 'markdown') and response.markdown:
33
- combined_content += f"\n\n---\n\n# {url}\n\n" + response.markdown
34
- time.sleep(2) # to respect rate limits
35
  except Exception as e:
36
- print(f"Failed to scrape {url}: {str(e)}")
37
- return combined_content
38
-
39
- # Define a custom tool to wrap this logic as a callable tool
40
- def plan_trip_with_scraping(user_prompt):
41
- # Step 1: Use Google search to get relevant URLs
42
- search_results = google_search(user_prompt)
43
- urls = [r["url"] for r in search_results[:5]]
44
-
45
- # Step 2: Scrape each URL using Firecrawl
46
- scraped_content = scrape_multiple_sites(urls)
47
-
48
- if not scraped_content:
49
- return "Sorry, couldn't find enough information."
50
-
51
- # Step 3: Use Gemini to generate a travel plan
52
- response = gemini_model.generate_content([
53
- "You are a travel planner. Based on the scraped content below, generate a helpful day-wise travel itinerary.",
54
- f"User Prompt: {user_prompt}",
55
- f"Scraped Content: {scraped_content}"
56
- ])
57
- return response.text
58
-
59
- # Final agent definition
60
- agent = LlmAgent(
61
- name="travel_planner",
62
- description="Suggests travel plans using live Google Search results and content scraped from the top sites.",
63
- instruction="Use google_search to find top URLs. Use Firecrawl to scrape the pages. Combine and use Gemini to create travel plan.",
64
- tools=[google_search, plan_trip_with_scraping],
65
- model="gemini-2.0-flash"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  )
67
 
68
- root_agent = agent
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
 
1
+ from google.adk.agents import Agent, LlmAgent
 
2
  from firecrawl import FirecrawlApp
 
3
  from dotenv import load_dotenv
4
+ from pydantic import BaseModel
5
+ from typing import List
6
+ import os, time, re
7
 
8
+ # 🔹 Load API key from .env
9
  load_dotenv()
10
  FIRECRAWL_API_KEY = os.getenv("FIRECRAWL_API_KEY")
 
 
11
  firecrawl_app = FirecrawlApp(api_key=FIRECRAWL_API_KEY)
12
 
13
+ # 🔹 Search Result Schema
14
+ class SearchResult(BaseModel):
15
+ urls: List[str]
16
+
17
+ # 🔹 Search Agent
18
+ search_agent = LlmAgent(
19
+ name="SearchAgent",
20
+ model="gemini-2.0-flash",
21
+ instruction="""
22
+ You are a helpful web assistant. Given a travel prompt, return exactly 5 valid URLs relevant to that query.
23
 
24
+ Only return this format:
25
+ {"urls": ["https://site1.com", "https://site2.com", ...]}
26
+
27
+ Do not include any description or explanation.
28
+ """,
29
+ output_schema=SearchResult,
30
+ output_key="search_urls"
31
+ )
32
+
33
+ # 🔹 Scrape and Summarize Logic
34
+ def scrape_and_summarize(user_prompt: str, urls: List[str]) -> str:
35
+ if not user_prompt or not urls:
36
+ return "Missing user_prompt or urls."
37
+
38
+ combined = ""
39
  for url in urls:
40
  try:
41
+ res = firecrawl_app.scrape_url(url=url, formats=["markdown"], only_main_content=True)
42
+ if hasattr(res, "markdown") and res.markdown:
43
+ combined += f"\n\n---\n# {url}\n\n{res.markdown}"
44
+ else:
45
+ print(f"No markdown content found at: {url}")
46
+ time.sleep(1.5)
 
 
 
47
  except Exception as e:
48
+ print(f"Failed to scrape {url} - {e}")
49
+
50
+ if not combined.strip():
51
+ return "Scraping failed or returned no usable data."
52
+
53
+ # Remove links to simplify text for LLM
54
+ trimmed = re.sub(r'\[.*?\]\(.*?\)', '', combined)[:6000]
55
+
56
+ return f"User Prompt: {user_prompt}\n\nScraped Content:\n{trimmed}"
57
+
58
+ # 🔹 Scraper Agent
59
+ scraper_agent = Agent(
60
+ name="ScraperAgent",
61
+ model="gemini-2.0-flash",
62
+ instruction="""
63
+ You are a strict itinerary planner. You must generate a structured 3-day travel itinerary using ONLY the scraped content provided.
64
+
65
+ DO NOT:
66
+ - Write introductions or summaries like "Let's plan your trip..."
67
+ - Mention assumptions like "I’ll assume you’re interested in..."
68
+ - Ask the user for more information
69
+ - Add personal opinions or suggestions
70
+
71
+ DO:
72
+ - Only use scraped content
73
+ - Follow this exact format:
74
+
75
+ Title: "3-Day Trip to <Destination> under ₹<Budget>"
76
+
77
+ Day 1: <Title>
78
+ Morning:
79
+ - <Activity>
80
+ Afternoon:
81
+ - <Activity>
82
+ Evening:
83
+ - <Activity>
84
+ Night:
85
+ - <Activity>
86
+ Estimated Day 1 Spend: ₹<Amount>
87
+
88
+ Day 2: ...
89
+ Day 3: ...
90
+
91
+ Budget Breakdown:
92
+ - Transport: ₹<amount>
93
+ - Food: ₹<amount>
94
+ - Accommodation: ₹<amount>
95
+ - Sightseeing: ₹<amount>
96
+ - Total: ₹<amount>
97
+
98
+ Only generate this format. If content is missing, say: "Not enough data to generate a valid itinerary."
99
+ """
100
  )
101
 
102
+
103
+ # 🔹 Root Agent
104
+ class TravelRootAgent(Agent):
105
+ def run(self, user_prompt: str):
106
+
107
+ # STEP 1: Get 5 travel URLs
108
+ search_result = search_agent.run(user_prompt)
109
+ urls = search_result.get("urls", [])
110
+
111
+ for u in urls: print(" -", u)
112
+
113
+ if not urls:
114
+ return "Search failed — no URLs returned."
115
+
116
+ # STEP 2: Scrape and summarize
117
+ scraped_content = scrape_and_summarize(user_prompt, urls)
118
+ print("\n Scraped Content Preview:\n", scraped_content[:1000])
119
+
120
+ # STEP 3: Send to ScraperAgent
121
+ payload = f"""
122
+ user_prompt: {user_prompt}
123
+
124
+ scraped_content:
125
+ {scraped_content}
126
+ """
127
+
128
+ return scraper_agent.run(payload)
129
+
130
+ # ✅ Instantiate root agent
131
+ root_agent = TravelRootAgent(
132
+ name="TravelRootAgent",
133
+ model="gemini-2.0-flash",
134
+ instruction="Plan a 3-day travel itinerary using external scraped travel content."
135
+ )
136