Skip to content

Commit 16bf9f1

Browse files
authored
Merge pull request #1908 from oracle-devrel/matsliwins-patch-3
ADK weather project
2 parents 459d841 + 3721584 commit 16bf9f1

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# OCI Weather Assistant API
2+
3+
A FastAPI-based service that integrates with Oracle Cloud Infrastructure's Generative AI Agent and uses OpenWeather API to provide real-time weather forecasts. The agent invokes the `get_weather` tool automatically when weather-related questions are asked.
4+
5+
## Features
6+
7+
- FastAPI backend with async support
8+
- OCI Generative AI Agent integration
9+
- Weather tool using OpenWeather API
10+
- `.env` configuration for secrets
11+
12+
## Setup
13+
14+
1. Clone the repo & install dependencies:
15+
16+
```bash
17+
git clone https://github.com/your-username/oci-weather-assistant.git
18+
cd oci-weather-assistant
19+
pip install -r requirements.txt
20+
21+
## Create a .env file in the root directory:
22+
23+
OCI_AI_AGENT_ENDPOINT_ID=ocid1.generativeaiendpoint.oc1..example
24+
OCI_CONFIG_PROFILE=DEFAULT
25+
OCI_REGION=us-chicago-1
26+
OPENWEATHER_API_KEY=your_openweather_api_key
27+
28+
## Run the app
29+
30+
uvicorn main:app --reload --port 8000
31+
32+
## UI
33+
34+
To test the API via a simple UI, use the frontend from this repository:
35+
🔗 https://github.com/ralungei/oci-genai-agent-blackbelt
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
OCI_AI_AGENT_ENDPOINT_ID=ocid1.generativeaiendpoint.oc1..example
2+
OCI_CONFIG_PROFILE=DEFAULT
3+
OCI_REGION=us-chicago-1
4+
OPENWEATHER_API_KEY=your_openweather_api_key
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
from __future__ import annotations
2+
3+
import os
4+
from typing import Dict, Optional
5+
6+
import requests
7+
from dotenv import load_dotenv
8+
from oci.addons.adk import Agent, AgentClient, tool
9+
from fastapi import FastAPI
10+
from fastapi.middleware.cors import CORSMiddleware
11+
from pydantic import BaseModel
12+
13+
# ---------------------------------------------------------------------------
14+
# Environment setup
15+
# ---------------------------------------------------------------------------
16+
17+
load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), ".env"))
18+
19+
OCI_AI_AGENT_ENDPOINT_ID = os.getenv("OCI_AI_AGENT_ENDPOINT_ID")
20+
OCI_CONFIG_PROFILE = os.getenv("OCI_CONFIG_PROFILE", "DEFAULT")
21+
OCI_REGION = os.getenv("OCI_REGION", "us-chicago-1")
22+
OPENWEATHER_API_KEY = os.getenv("OPENWEATHER_API_KEY", "")
23+
24+
25+
# ---------------------------------------------------------------------------
26+
# Tool definition
27+
# ---------------------------------------------------------------------------
28+
29+
@tool
30+
def get_weather(location: str, units: str = "metric") -> Dict[str, str]:
31+
"""Return the current weather for *location* using OpenWeatherMap.
32+
33+
Args:
34+
location: City name (e.g. "Seattle" or "Seattle,US").
35+
units: Measurement system – "metric" (°C), "imperial" (°F), or
36+
"standard" (Kelvin). Defaults to "metric".
37+
38+
Returns:
39+
A dict ready for the agent response, containing temperature, unit,
40+
humidity, wind speed and a short description.
41+
"""
42+
43+
base_url = "https://api.openweathermap.org/data/2.5/weather"
44+
params = {
45+
"q": location,
46+
"appid": OPENWEATHER_API_KEY,
47+
"units": units,
48+
}
49+
50+
try:
51+
resp = requests.get(base_url, params=params, timeout=10)
52+
resp.raise_for_status()
53+
except requests.RequestException as exc:
54+
raise RuntimeError(f"Weather service unavailable: {exc}") from exc
55+
56+
data = resp.json()
57+
58+
main = data["main"]
59+
weather = data["weather"][0]
60+
wind = data.get("wind", {})
61+
62+
unit_symbol = {"metric": "°C", "imperial": "°F", "standard": "K"}.get(units, "°?")
63+
64+
return {
65+
"location": location,
66+
"temperature": main["temp"],
67+
"unit": unit_symbol,
68+
"description": weather["description"],
69+
"humidity_percent": main.get("humidity"),
70+
"wind_speed_mps": wind.get("speed"),
71+
}
72+
73+
74+
# ---------------------------------------------------------------------------
75+
# FastAPI setup
76+
# ---------------------------------------------------------------------------
77+
app = FastAPI()
78+
app.add_middleware(
79+
CORSMiddleware,
80+
allow_origins=["*"],
81+
allow_credentials=True,
82+
allow_methods=["*"],
83+
allow_headers=["*"],
84+
)
85+
86+
# ---------------------------------------------------------------------------
87+
# Agent setup (reuse from main)
88+
# ---------------------------------------------------------------------------
89+
if not OCI_AI_AGENT_ENDPOINT_ID:
90+
raise SystemExit("OCI_AI_AGENT_ENDPOINT_ID is not set. Check your .env file.")
91+
92+
client = AgentClient(
93+
auth_type="api_key",
94+
profile=OCI_CONFIG_PROFILE,
95+
region=OCI_REGION,
96+
)
97+
98+
agent = Agent(
99+
client=client,
100+
agent_endpoint_id=OCI_AI_AGENT_ENDPOINT_ID,
101+
instructions=(
102+
"You are a helpful assistant that answers weather questions. "
103+
"Always invoke the get_weather tool when the user asks about the forecast."
104+
),
105+
tools=[get_weather],
106+
)
107+
108+
agent.setup()
109+
110+
# ---------------------------------------------------------------------------
111+
# API request/response models
112+
# ---------------------------------------------------------------------------
113+
class ChatRequest(BaseModel):
114+
question: str
115+
execute_functions: Optional[bool] = True
116+
session_id: Optional[str] = None
117+
118+
# ---------------------------------------------------------------------------
119+
# /chat endpoint
120+
# ---------------------------------------------------------------------------
121+
@app.post("/chat")
122+
async def chat(request: ChatRequest):
123+
try:
124+
response = await agent.run_async(request.question)
125+
return {
126+
"answer": response.final_output,
127+
"session_id": request.session_id or "session123"
128+
}
129+
except Exception as e:
130+
return {"answer": str(e), "session_id": request.session_id or "session123"}
131+
132+
133+
if __name__ == "__main__":
134+
main()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fastapi==0.111.0
2+
uvicorn==0.29.0
3+
requests==2.31.0
4+
python-dotenv==1.0.1
5+
oci==2.114.1

0 commit comments

Comments
 (0)