Skip to content
Last updated

🔨 In Development — This section is still being developed and may change.
This comprehensive example demonstrates how to build an intelligent weather reporting assistant using Freddy's function calling capabilities.

Overview

We'll create a workflow that:

  1. Accepts natural language weather queries
  2. Extracts location and date information
  3. Calls external weather APIs
  4. Formats and presents the weather data
  5. Handles errors and edge cases

Prerequisites

  • Freddy API account with function calling enabled
  • Weather API key (we'll use OpenWeatherMap in this example)
  • Basic understanding of Python/Node.js

Step 1: Define the Weather Function

First, let's create a function that fetches weather data:

import requests
import json
from datetime import datetime

def get_weather_data(location: str, date: str = None) -> dict:
    """
    Get weather data for a specific location and date.

    Args:
        location: City name or coordinates (e.g., "New York" or "40.7128,-74.0060")
        date: Date in YYYY-MM-DD format (optional, defaults to current date)

    Returns:
        Dictionary containing weather information
    """
    api_key = "YOUR_OPENWEATHERMAP_API_KEY"  # Store in environment variables

    try:
        # Geocoding API to get coordinates
        geo_url = f"http://api.openweathermap.org/geo/1.0/direct?q={location}&limit=1&appid={api_key}"
        geo_response = requests.get(geo_url)
        geo_data = geo_response.json()

        if not geo_data:
            return {"error": f"Location '{location}' not found"}

        lat = geo_data[0]['lat']
        lon = geo_data[0]['lon']

        # Current weather API
        weather_url = f"https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={api_key}&units=metric"
        weather_response = requests.get(weather_url)
        weather_data = weather_response.json()

        # Format the response
        return {
            "location": geo_data[0]['name'],
            "country": geo_data[0]['country'],
            "temperature": weather_data['main']['temp'],
            "feels_like": weather_data['main']['feels_like'],
            "humidity": weather_data['main']['humidity'],
            "description": weather_data['weather'][0]['description'],
            "wind_speed": weather_data['wind']['speed'],
            "timestamp": datetime.now().isoformat()
        }

    except Exception as e:
        return {"error": f"Failed to fetch weather data: {str(e)}"}
const axios = require('axios');

async function getWeatherData(location, date = null) {
    const apiKey = process.env.OPENWEATHERMAP_API_KEY;

    try {
        // Geocoding API to get coordinates
        const geoUrl = `http://api.openweathermap.org/geo/1.0/direct?q=${encodeURIComponent(location)}&limit=1&appid=${apiKey}`;
        const geoResponse = await axios.get(geoUrl);
        const geoData = geoResponse.data;

        if (!geoData || geoData.length === 0) {
            return { error: `Location '${location}' not found` };
        }

        const { lat, lon } = geoData[0];

        // Current weather API
        const weatherUrl = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric`;
        const weatherResponse = await axios.get(weatherUrl);
        const weatherData = weatherResponse.data;

        // Format the response
        return {
            location: geoData[0].name,
            country: geoData[0].country,
            temperature: weatherData.main.temp,
            feels_like: weatherData.main.feels_like,
            humidity: weatherData.main.humidity,
            description: weatherData.weather[0].description,
            wind_speed: weatherData.wind.speed,
            timestamp: new Date().toISOString()
        };

    } catch (error) {
        return { error: `Failed to fetch weather data: ${error.message}` };
    }
}

Step 2: Create the Weather Assistant

Now let's create a Freddy assistant that uses this weather function:

import os
from freddy import Freddy

# Initialize Freddy client
freddy = Freddy(api_key=os.getenv("FREDDY_API_KEY"))

# Create the assistant
assistant = freddy.assistants.create(
    name="Weather Assistant",
    instructions="""You are a helpful weather assistant. When users ask about weather:

1. Extract the location from their message
2. Determine if they want current weather or a forecast
3. Use the get_weather_data function to fetch information
4. Provide a clear, formatted response with temperature, conditions, and other relevant details
5. If the location is unclear, ask for clarification
6. Handle errors gracefully and provide helpful error messages

Always be friendly and provide context-appropriate responses.""",
    model="gpt-4",
    tools=[
        {
            "type": "function",
            "function": {
                "name": "get_weather_data",
                "description": "Get current weather information for a specified location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name or coordinates to get weather for (e.g., 'New York' or '40.7128,-74.0060')"
                        },
                        "date": {
                            "type": "string",
                            "description": "Date in YYYY-MM-DD format (optional, defaults to current date)"
                        }
                    },
                    "required": ["location"]
                }
            }
        }
    ]
)

Step 3: Create a Weather Thread

# Create a thread for the weather conversation
thread = freddy.threads.create()

# Send a message asking for weather
message = freddy.threads.messages.create(
    thread_id=thread.id,
    role="user",
    content="What's the weather like in Tokyo today?"
)

# Run the assistant
run = freddy.threads.runs.create(
    thread_id=thread.id,
    assistant_id=assistant.id
)

# Wait for completion and get the response
while run.status not in ["completed", "failed", "cancelled"]:
    run = freddy.threads.runs.retrieve(thread_id=thread.id, run_id=run.id)

if run.status == "completed":
    # Get the latest message
    messages = freddy.threads.messages.list(thread_id=thread.id)
    latest_message = messages.data[-1]

    print("Weather Assistant:", latest_message.content[0].text.value)
else:
    print(f"Run failed with status: {run.status}")

Step 4: Handle the Response

The assistant will automatically call your weather function and provide a natural language response:

Weather Assistant: The current weather in Tokyo shows it's 22°C with scattered clouds. It feels like 25°C, and there's 65% humidity with a light wind of 3.2 m/s from the southeast. Overall, it's a pleasant day for outdoor activities!

Advanced Features

Adding Weather Forecasting

Extend the function to support forecasts:

def get_weather_forecast(location: str, days: int = 3) -> dict:
    """Get weather forecast for the next few days."""
    # Implementation for multi-day forecast
    pass

Location Detection

Enhance the assistant to detect locations from context:

# In your assistant instructions
"""
If no location is specified, ask the user for clarification.
If the user mentions 'current location' or 'here', ask them to provide their location.
Remember the user's location for follow-up questions.
"""

Error Handling

# In your weather function
def get_weather_data(location: str, date: str = None) -> dict:
    try:
        # ... implementation ...
    except requests.exceptions.RequestException:
        return {"error": "Unable to connect to weather service. Please try again later."}
    except KeyError:
        return {"error": "Invalid response from weather service."}
    except Exception as e:
        return {"error": "An unexpected error occurred while fetching weather data."}

Testing the Workflow

  1. Create the assistant with your weather function
  2. Start a conversation: "How's the weather in London?"
  3. Try different queries: "What's the temperature in NYC?", "Will it rain tomorrow in Paris?"
  4. Test error cases: "Weather in Atlantis", "Current conditions in"

Best Practices

  1. Environment Variables: Never hardcode API keys
  2. Error Handling: Provide meaningful error messages
  3. Rate Limiting: Respect API rate limits
  4. Caching: Cache weather data to avoid unnecessary API calls
  5. Units: Allow users to specify preferred units (°C/°F)
  6. Localization: Support multiple languages and regions

Next Steps

  • Add more weather APIs for redundancy
  • Implement weather alerts and notifications
  • Add historical weather data
  • Create weather-based recommendations
  • Integrate with calendar for event planning

Troubleshooting

Function not being called: Check that the function name and parameters match exactly in your assistant configuration.

API errors: Verify your weather API key is valid and has sufficient quota.

Location not found: The geocoding service might not recognize the location format. Try major city names first.

For more help, check the Function Calling Guide or API Reference.