{ "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 }