{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "18772359",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ok\n"
]
}
],
"source": [
"print(\"ok\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "68b7c55e",
"metadata": {},
"outputs": [],
"source": [
"from dotenv import load_dotenv"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a0255cca",
"metadata": {},
"outputs": [],
"source": [
"from langchain_groq import ChatGroq"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "a73c057d",
"metadata": {},
"outputs": [],
"source": [
"llm=ChatGroq(model=\"deepseek-r1-distill-llama-70b\")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ec4c38f3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AIMessage(content='\\n\\n\\n\\nHello! How can I assist you today? 😊', additional_kwargs={}, response_metadata={'token_usage': {'completion_tokens': 16, 'prompt_tokens': 4, 'total_tokens': 20, 'completion_time': 0.084725173, 'prompt_time': 6.0159e-05, 'queue_time': 0.053524741, 'total_time': 0.084785332}, 'model_name': 'deepseek-r1-distill-llama-70b', 'system_fingerprint': 'fp_1bbe7845ec', 'finish_reason': 'stop', 'logprobs': None}, id='run--8b091ea3-0a7d-4058-9e8b-2a68094cc078-0', usage_metadata={'input_tokens': 4, 'output_tokens': 16, 'total_tokens': 20})"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm.invoke(\"hi\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0215d359",
"metadata": {},
"outputs": [],
"source": [
"from langchain.tools import tool"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "d81ac345",
"metadata": {},
"outputs": [],
"source": [
"@tool\n",
"def multiply(a: int, b: int) -> int:\n",
" \"\"\"\n",
" Multiply two integers.\n",
"\n",
" Args:\n",
" a (int): The first integer.\n",
" b (int): The second integer.\n",
"\n",
" Returns:\n",
" int: The product of a and b.\n",
" \"\"\"\n",
" return a * b"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "1f79ae97",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"StructuredTool(name='multiply', description='Multiply two integers.\\n\\nArgs:\\n a (int): The first integer.\\n b (int): The second integer.\\n\\nReturns:\\n int: The product of a and b.', args_schema=, func=)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"multiply"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2927babf",
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.tools import StructuredTool"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "03483480",
"metadata": {},
"outputs": [],
"source": [
"class WeatherInput(BaseModel):\n",
" city: str"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "28d0a2ca",
"metadata": {},
"outputs": [],
"source": [
"def get_weather(city: str) -> str:\n",
" \"\"\"\n",
" Get the weather for a given city.\n",
"\n",
" Args:\n",
" city (str): The name of the city.\n",
"\n",
" Returns:\n",
" str: A string describing the weather in the city.\n",
" \"\"\"\n",
" return f\"The weather in {city} is sunny.\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b45850a3",
"metadata": {},
"outputs": [],
"source": [
"weather_tool = StructuredTool.from_function(\n",
" func=get_weather,\n",
" name=\"get_weather\",\n",
" description=\"Fetches real-time weather data for a city\",\n",
" args_schema=WeatherInput, \n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e36ee4d6",
"metadata": {},
"outputs": [],
"source": [
"class WeatherInput(BaseModel):\n",
" city: str = Field(..., description=\"City name\")\n",
" units: str = Field(\"metric\", description=\"metric or imperial\")\n",
"\n",
"class GetWeatherTool(StructuredTool):\n",
" name: ClassVar[str] = \"get_weather\" \n",
" description: ClassVar[str] = (\n",
" \"Fetches weather data for a city\"\n",
" )\n",
" args_schema: ClassVar[Type[BaseModel]] = WeatherInput\n",
"\n",
" def _run(self, city: str, units: str = \"metric\") -> str:\n",
" return get_weather(city, units)"
]
},
{
"cell_type": "markdown",
"id": "647b5794",
"metadata": {},
"source": [
"## SmartTrip AI API Key Diagnostics\n",
"\n",
"This section checks whether each external service key works without printing secret values. It tests weather, places, Tavily, exchange-rate, the configured LLM, and finally the full LangGraph agent."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "4a2fe847",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Project root: f:\\hugging_face_host_projects\\smarttrip_ai\n",
"\n",
"Environment key presence:\n",
"MODEL_PROVIDER SET\n",
"MODEL_NAME SET\n",
"MODEL_BASE_URL SET\n",
"OLLAMA_API_KEY SET\n",
"OPENWEATHERMAP_API_KEY SET\n",
"FOURSQUARE_API_KEY SET\n",
"TAVILY_API_KEY SET\n",
"EXCHANGE_RATE_API_KEY SET\n"
]
}
],
"source": [
"import os\n",
"import sys\n",
"from pathlib import Path\n",
"\n",
"PROJECT_ROOT = Path.cwd()\n",
"if PROJECT_ROOT.name == \"notebook\":\n",
" PROJECT_ROOT = PROJECT_ROOT.parent\n",
"\n",
"sys.path.insert(0, str(PROJECT_ROOT))\n",
"os.chdir(PROJECT_ROOT)\n",
"\n",
"from dotenv import load_dotenv\n",
"load_dotenv()\n",
"\n",
"required_keys = {\n",
" \"MODEL_PROVIDER\": os.getenv(\"MODEL_PROVIDER\"),\n",
" \"MODEL_NAME\": os.getenv(\"MODEL_NAME\"),\n",
" \"MODEL_BASE_URL\": os.getenv(\"MODEL_BASE_URL\"),\n",
" \"OLLAMA_API_KEY\": os.getenv(\"OLLAMA_API_KEY\"),\n",
" \"OPENWEATHERMAP_API_KEY\": os.getenv(\"OPENWEATHERMAP_API_KEY\"),\n",
" \"FOURSQUARE_API_KEY\": os.getenv(\"FOURSQUARE_API_KEY\"),\n",
" \"TAVILY_API_KEY\": os.getenv(\"TAVILY_API_KEY\"),\n",
" \"EXCHANGE_RATE_API_KEY\": os.getenv(\"EXCHANGE_RATE_API_KEY\"),\n",
"}\n",
"\n",
"print(\"Project root:\", PROJECT_ROOT)\n",
"print(\"\\nEnvironment key presence:\")\n",
"for key, value in required_keys.items():\n",
" print(f\"{key:24} {'SET' if value else 'MISSING'}\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "a1ecbf2d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"API connectivity tests:\n",
"\n",
"PASS | OpenWeatherMap | status=200, city=Goa\n",
"FAIL | Foursquare | status=401, results=0\n",
"PASS | Tavily | answer_length=537\n",
"FAIL | ExchangeRate | status=403, USD_INR=None\n",
"PASS | LLM direct | SmartTrip OK\n"
]
}
],
"source": [
"import requests\n",
"from langchain_tavily import TavilySearch\n",
"from langchain_openai import ChatOpenAI\n",
"from langchain_core.messages import HumanMessage\n",
"\n",
"\n",
"def check_result(name, ok, detail):\n",
" status = \"PASS\" if ok else \"FAIL\"\n",
" print(f\"{status:4} | {name:18} | {detail}\")\n",
"\n",
"\n",
"print(\"API connectivity tests:\\n\")\n",
"\n",
"# 1. OpenWeatherMap\n",
"try:\n",
" weather_key = os.getenv(\"OPENWEATHERMAP_API_KEY\")\n",
" response = requests.get(\n",
" \"https://api.openweathermap.org/data/2.5/weather\",\n",
" params={\"q\": \"Goa\", \"appid\": weather_key, \"units\": \"metric\"},\n",
" timeout=20,\n",
" )\n",
" data = response.json()\n",
" check_result(\n",
" \"OpenWeatherMap\",\n",
" response.status_code == 200,\n",
" f\"status={response.status_code}, city={data.get('name', 'n/a')}\",\n",
" )\n",
"except Exception as exc:\n",
" check_result(\"OpenWeatherMap\", False, repr(exc))\n",
"\n",
"# 2. Foursquare\n",
"try:\n",
" fsq_key = os.getenv(\"FOURSQUARE_API_KEY\")\n",
" response = requests.get(\n",
" \"https://api.foursquare.com/v3/places/search\",\n",
" headers={\"Accept\": \"application/json\", \"Authorization\": fsq_key},\n",
" params={\"query\": \"tourist attraction\", \"near\": \"Goa\", \"limit\": 3},\n",
" timeout=20,\n",
" )\n",
" data = response.json()\n",
" result_count = len(data.get(\"results\", [])) if isinstance(data, dict) else 0\n",
" check_result(\n",
" \"Foursquare\",\n",
" response.status_code == 200 and result_count > 0,\n",
" f\"status={response.status_code}, results={result_count}\",\n",
" )\n",
"except Exception as exc:\n",
" check_result(\"Foursquare\", False, repr(exc))\n",
"\n",
"# 3. Tavily\n",
"try:\n",
" tavily = TavilySearch(topic=\"general\", include_answer=\"advanced\")\n",
" result = tavily.invoke({\"query\": \"top attractions in Goa India\"})\n",
" answer = result.get(\"answer\") if isinstance(result, dict) else str(result)\n",
" check_result(\"Tavily\", bool(answer), f\"answer_length={len(str(answer))}\")\n",
"except Exception as exc:\n",
" check_result(\"Tavily\", False, repr(exc))\n",
"\n",
"# 4. ExchangeRate API\n",
"try:\n",
" exchange_key = os.getenv(\"EXCHANGE_RATE_API_KEY\")\n",
" response = requests.get(\n",
" f\"https://v6.exchangerate-api.com/v6/{exchange_key}/latest/USD\",\n",
" timeout=20,\n",
" )\n",
" data = response.json()\n",
" rate = data.get(\"conversion_rates\", {}).get(\"INR\") if isinstance(data, dict) else None\n",
" check_result(\n",
" \"ExchangeRate\",\n",
" response.status_code == 200 and rate is not None,\n",
" f\"status={response.status_code}, USD_INR={rate}\",\n",
" )\n",
"except Exception as exc:\n",
" check_result(\"ExchangeRate\", False, repr(exc))\n",
"\n",
"# 5. LLM direct call\n",
"try:\n",
" llm = ChatOpenAI(\n",
" model=os.getenv(\"MODEL_NAME\"),\n",
" base_url=os.getenv(\"MODEL_BASE_URL\"),\n",
" api_key=os.getenv(\"OLLAMA_API_KEY\") or os.getenv(\"MODEL_API_KEY\"),\n",
" )\n",
" response = llm.invoke(\"Reply with exactly: SmartTrip OK\")\n",
" check_result(\"LLM direct\", bool(response.content), response.content[:120])\n",
"except Exception as exc:\n",
" check_result(\"LLM direct\", False, repr(exc))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "2dd6a18b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Building graph...\n",
"[ModelLoader] Loading LLM — provider: ollama\n",
"Invoking full agent with tools...\n",
"Agent response length: 11007\n",
"\n",
"Preview:\n",
"\n",
"## 5‑Day Goa Getaway for **2 people** – **₹ 10,000** total \n",
"*(≈ ₹ 2,000 per day – very budget‑friendly)* \n",
"\n",
"--- \n",
"\n",
"### 1️⃣ QUICK OVERVIEW \n",
"\n",
"| Item | Approx. Cost (INR) | Notes |\n",
"|------|-------------------|-------|\n",
"| **Accommodation** (5 nights, budget guesthouse/hostel) | **₹ 4,000** | ~₹ 800 per night for a double‑bed dorm or private room in Panaji/Anjuna |\n",
"| **Food** (local shacks, street‑food, small restaurants) | **₹ 1,500** | ~₹ 150 per person per main meal (breakfast + dinner) + cheap snacks |\n",
"| **Local transport** (state buses, shared autos, occasional scooter rent) | **₹ 800** | Bus fares ₹ 10‑₹ 30, scooter rent ₹ 250 / day for 2 days (optional) |\n",
"| **Entry & activity fees** (temples, forts, waterfalls, market entry) | **₹ 800** | Mostly ₹ 20‑₹ 100 per site |\n",
"| **Miscellaneous / Buffer** | **₹ 900** | Souvenirs, occasional water‑sport try‑out, emergency cash |\n",
"| **Total** | **₹ 10,000** | ✔ Fits the budget |\n",
"\n",
"> **Tip:** All prices are 2026 averages; book early on sites like *Hostelworld* or *Airbnb* for the cheapest rooms, and pay for food & transport in cash to avoid extra card fees.\n",
"\n",
"---\n",
"\n",
"## 2️⃣ WEATHER (May 2026)\n",
"\n",
"| Parameter | Typical Range |\n",
"|-----------|---------------|\n",
"| **Temperature** | 30 °C – 34 °C (day) / 26 °C – 28 °C (night) |\n",
"| **Rainfall** | Pre‑monsoon showers, ~30 mm total, usually brief afternoon thunders |\n",
"| **What to pack** | Light cotton/linen clothes, a hat, sunscreen (SPF ≥ 30), a compact rain‑poncho, comfortable walking shoes or flip‑flops. |\n",
"\n",
"---\n",
"\n",
"## 3️⃣ ITINERARY – **Plan A (Main Tourist Highlights)** \n",
"\n",
"| Day | Morning | Mid‑Day | Evening | Suggested Stay (Budget) |\n",
"|-----|----------|--------|---------|--------------------------|\n",
"| **1 – Arrival & Panaji** | Arrive at Dabolim Airport or bus‑station. Take a local bus to **Panaji** (₹ 20). | Check‑in, freshen up. Walk around **Fontainhas** (Portuguese‑style lanes). Lunch at **Café Mambo** – fish thali ₹ 150 pp. | Sunset at **Miramar Beach**; dinner at **Vinayak Family Restaurant** – Goan fish curry ₹ 120 pp. | **Hostel “Zostel Panaji”** – mixed dorm, ₹ 800/night (double). |\n",
"| **2 – Old Goa & Fort Aguada** | Breakfast at **Ritz Café** – poha & tea ₹ 70 pp.
Bus to **Old Goa** (₹ 10). Visit **Basilica of Bom Jesus** (free) and **Se Cathedral** (free). | Lunch at **Martin’s Corner (Mapusa)** – chicken xacuti ₹ 180 pp. | Evening bus to **Fort Aguada** (₹ 20). Explore fort & lighthouse (free). Dinner at **Susegado** (rice & fish Curry) ₹ 120 pp. | Same hostel. |\n",
"| **3 – No\n"
]
}
],
"source": [
"from agent.agentic_workflow import GraphBuilder\n",
"\n",
"prompt = \"Plan a 5-day trip to goa for 2 people with a budget of inr 10000\"\n",
"\n",
"print(\"Building graph...\")\n",
"graph = GraphBuilder(model_provider=os.getenv(\"MODEL_PROVIDER\", \"ollama\"))()\n",
"\n",
"print(\"Invoking full agent with tools...\")\n",
"output = graph.invoke({\"messages\": [HumanMessage(content=prompt)]})\n",
"answer = output[\"messages\"][-1].content\n",
"\n",
"print(\"Agent response length:\", len(answer))\n",
"print(\"\\nPreview:\\n\")\n",
"print(answer[:2500])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "trip_env (3.12.9)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}