One Twenty Three Cloud Street

One Twenty Three Cloud Street

Share this post

One Twenty Three Cloud Street
One Twenty Three Cloud Street
The sun never sets on 5pm - Part 1
Copy link
Facebook
Email
Notes
More

The sun never sets on 5pm - Part 1

Failing Fast and Building Real Applications with Prompts

Will Laws's avatar
Will Laws
Oct 24, 2023
∙ Paid

Share this post

One Twenty Three Cloud Street
One Twenty Three Cloud Street
The sun never sets on 5pm - Part 1
Copy link
Facebook
Email
Notes
More
Share

Manifest

Part 0 - Introduction
Part 1 - Failing Fast (Building with prompts) *You are Here 💁‍♀️
Part 2 - MVP and Deployments
Part 3 - MVPolish
Part 4 - So what.

be sure to read Part 0 for the “why”

Getting Started

(For those who prefer not to read the text in the images, rest assured, I'll continue to provide a summary of the progress after each visual update.)

My initial goal is to make a lambda function that will use a timezone database (which I did not specify any details about), compare the current time to the database and return the location, longitude and latitude of the result. I first try to ask GPT-4 to do this like I was writing comments in a python file.

# this is a python file that finds a place where it is currently between 5pm and 5:59pm local time and returns the latitude and longitude of that place.  # It uses the timezone database to find the current timezone and then uses the timezone to find the current time. It then uses the timezone to find the latitude and longitude of the place.  # It then returns the latitude and longitude of the place. # this will run as a lambda function  ChatGPT To create a Python file that finds a place where it is currently between 5 PM and 5:59 PM local time and returns the latitude and longitude of that place, you can use the 'pytz' library to work with time zones and the 'geopy' library to get latitude and longitude.  First, make sure you have installed the required libraries:  bash Copy code pip install pytz geopy Now, create a Python script (e.g., find_location.py) with the following code:
The first foray
import datetime import pytz from geopy.geocoders import Nominatim  def get_location_with_time_between_5_and_6():     geolocator = Nominatim(user_agent="myGeocoder")      current_utc_time = datetime.datetime.utcnow()     for tz in pytz.all_timezones:         try:             local_time = current_utc_time.astimezone(pytz.timezone(tz))             if local_time.hour == 17:  # Check if the local time is between 5 PM and 5:59 PM                 location = geolocator.timezone(tz)                 return {                     "latitude": location.latitude,                     "longitude": location.longitude,                     "timezone": tz,                 }         except Exception as e:             pass      return None  if __name__ == "__main__":     location_data = get_location_with_time_between_5_and_6()     if location_data:         print(f"Latitude: {location_data['latitude']}, Longitude: {location_data['longitude']}, Timezone: {location_data['timezone']}")     else:         print("No location found where the time is between 5 PM and 5:59 PM.") To use this script as an AWS Lambda function, you'll need to create a deployment package with the script and its dependencies. Here's how to do that:  Create a new directory for the package, e.g., find_location_package. Copy the find_location.py script into the new directory. Install the required libraries within the package directory: bash Copy code pip install pytz geopy -t find_location_package Zip the contents of the package directory: bash Copy code cd find_location_package zip -r ../find_location_package.zip . Upload the find_location_package.zip file to your AWS Lambda function. Set the Lambda function's handler to find_location.get_location_with_time_between_5_and_6. Now you should be able to run the Lambda function and get the latitude and longitude of a location where it's currently between 5 PM and 5:59 PM local time.

First Fail Fast

Ah, our initial query is also a pivotal realization in our AI-powered odyssey. Indeed, approaching tasks with LLMs like GPT-4 requires a different mindset. Asking too much in one go is a common pitfall, and it's one that I've just encountered firsthand.

Helpfully, ChatGPT has used nominatim which is a nice library - however, its purpose is to find places by their name or address and turn them into GPS Coordinates like “New York” → 40°42′46″N 74°00′22″W. It can also take a longitude and latitude and turn them into the nearest address like 36°49′25.6″S 139°51′47.5″E → 17 Princes Hwy, Kingston SE SA 5275 Australia.

I want to turn the time into a place and I don’t know where that place is or what its address is.

To attempt this - ChatGPT has taken the current time, iterated over all the timezones provided by the pytz library (converting to UTC), finds the (doesn’t handle the case were there are multiple “named” timezones where its 5pm) singular timezone where its 5pm and then finds the singular longitude and latitude of the timezone. Can you even do that?

I’ve obviously not explained myself well.

So, the key is to break tasks into bite-sized, ordered steps. This approach mitigates reduces the chance of GPT-4 'hallucinating' - an AI's tendency to generate outputs that are coherent but detached from reality or the provided data. Let's recalibrate and proceed with this refined approach.

i want the lambda function to be fronted by api-gateway and to programmatically return the result for an api  ChatGPT To use AWS Lambda with API Gateway, you'll need to make a few changes to the code and set up the API Gateway in the AWS Console.  First, modify the find_location.py script to use the AWS Lambda handler format and return the API Gateway-compatible response:
I want to also return the name of the city   ChatGPT To return the name of the city, you can use the reverse method from the geopy.geocoders library, which returns the address information for a given latitude and longitude. Update the find_location.py script as follows:
how do i run a test in the lambda console for this?  ChatGPT To test your Lambda function in the AWS Management Console, follow these steps:  Sign in to the AWS Management Console. Navigate to the AWS Lambda Console. Choose the Lambda function you've created for the location finder script. On the function's configuration page, click the Test button in the upper right corner. A "Configure test event" dialog will appear. Since your Lambda function doesn't require any specific input, you can create a new test event with any event template. Select the Hello World template from the "Event template" dropdown list. Provide a name for the test event (e.g., "EmptyEvent") and click Create. With the new test event selected, click the Test button again to run the Lambda function with the test event as input. After the Lambda function executes, the "Execution result" panel will appear below the function code, displaying the result, including the response, request ID, and other information. Since your Lambda function doesn't rely on the input event, the test event's content doesn't matter. It will still execute the function and return the latitude, longitude, timezone, and city name of a location where it's currently between 5 PM and 5:59 PM local time.

Fixing the first error

Remember - I can’t test this code, yet, I know it's wrong. I just told you it's wrong too - but I must push on since I need to give ChatGPT the error the code generates and allow it to make changes.

I quickly get an error - after those initial questions we have the following code for the inaugural lambda function:

import datetime
import pytz
from geopy.geocoders import Nominatim
import json

def get_location_with_time_between_5_and_6():
    geolocator = Nominatim(user_agent="myGeocoder")

    current_utc_time = datetime.datetime.utcnow()
    for tz in pytz.all_timezones:
        try:
            local_time = current_utc_time.astimezone(pytz.timezone(tz))
            if local_time.hour == 17:  # Check if the local time is between 5 PM and 5:59 PM
                location = geolocator.timezone(tz)
                city_info = geolocator.reverse((location.latitude, location.longitude), language='en')
                city = city_info.raw.get('address', {}).get('city', '')
                return {
                    "latitude": location.latitude,
                    "longitude": location.longitude,
                    "timezone": tz,
                    "city": city
                }
        except Exception as e:
            pass

    return None

def lambda_handler(event, context):
    location_data = get_location_with_time_between_5_and_6()

    if location_data:
        response_body = {
            "latitude": location_data["latitude"],
            "longitude": location_data["longitude"],
            "timezone": location_data["timezone"],
            "city": location_data["city"],
        }
        status_code = 200
    else:
        response_body = {"error": "No location found where the time is between 5 PM and 5:59 PM."}
        status_code = 404

    return {
        "statusCode": status_code,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps(response_body),
    }

Finally something I can pass back to Chat GPT to iterate on - I passed the error into the prompt and the soon to be classic response “My apologies for the confusion…”

I got this error:  Test Event Name test  Response {   "errorMessage": "get_location_with_time_between_5_and_6() takes 0 positional arguments but 2 were given",   "errorType": "TypeError",   "requestId": "3bc1f15a-5ba9-47ed-8e4a-63b4ae410d90",   "stackTrace": [     "  File \"/var/runtime/awslambdaric/bootstrap.py\", line 149, in handle_event_request\n    response = request_handler(event, lambda_context)\n"   ] }  ChatGPT My apologies for the confusion. The error occurred because the Lambda function expects the lambda_handler to accept two arguments, event and context. However, the get_location_with_time_between_5_and_6() function was defined to take no arguments. I mistakenly used the get_location_with_time_between_5_and_6() function as the handler in my previous responses.  Please update the Lambda function's handler in the AWS Lambda Console to find_location.lambda_handler. This should resolve the error.  To update the handler, follow these steps:  Sign in to the AWS Management Console. Navigate to the AWS Lambda Console. Choose the Lambda function you've created for the location finder script. In the "Function code" panel, find the "Handler" input field. Update the handler value to find_location.lambda_handler. Click the Deploy button in the upper right corner to save the changes. Now, you can re-run the test in the Lambda console, and it should work without any issues.
This could be a really long night.
The Santa Clause (1993)

If you’re familiar with Lambda, you know that the lambda_handler function looks like this in python:

def lambda_handler(event, context):

It has been shown the door.

In its place, we're charting a less-traveled path - defining a custom lambda handler function name.

This decision, while it certainly dials up the complexity quotient, might seem like an exercise in masochism. Especially when we're also keeping a function named 'lambda_handler' in the code and not using it as the lambda handler, setting up a veritable obstacle course for future readability.

But sometimes, in the pursuit of innovation, conventional wisdom is tossed to the wind, and we are made to navigate the labyrinthine I hope you’re studying for the SAT intricacies of code. This is one of those times?

I update the lambda function to use the find_location.lambda_handler, as poorly prescribed, and move on.

Now, with two 'lambda_handlers' we push ahead. Changing gears, I contemplate simplifying our function. I've planned on using a DynamoDB table to store the list of cities and timezones, but the data source is still unclear. Instead of the DynamoDB table, could a Python library be the answer? I just need latitude, longitude, name, and timezone. Let's delve into Python's rich ecosystem and see if it already has what we need.

is there a python library that has a huge list of cities and which timezones they are in?  ChatGPT  2 / 2  Yes, there's a Python library called timezonefinder that allows you to find the timezone for     User how do i do the reverse? I want to know a list of cities in a timezone  ChatGPT To get a list of cities in a specific timezone, you can use the cities package. First, you need to install it:  bash Copy code pip install cities Then, you can use the following code to get a list of cities in a specific timezone:  python Copy code from cities import data import pytz  def get_cities_in_timezone(target_timezone):     cities_in_timezone = []      for city_id, city_data in data.CITIES.items():         city_timezone = city_data.get('timezone')         if city_timezone == target_timezone:             city_name = city_data.get('name')             cities_in_timezone.append(city_name)      return cities_in_timezone  if __name__ == "__main__":     timezone = "America/New_York"     cities_list = get_cities_in_timezone(timezone)     print(f"Cities in {timezone}:")     for city in cities_list:         print(city) In this example, the get_cities_in_timezone function takes a target timezone as an argument and returns a list of cities in that timezone. The cities package provides a dictionary of cities and their related information, including the timezone.  Please note that the cities package might not have a comprehensive list of all cities in a timezone, but it should cover most major cities. If you require more exhaustive city data, you can consider using the GeoNames database, which provides extensive geographical data, including city names and timezones. You can download the database, parse it, and filter the results based on the timezone.

My lucky day. A pre-built library that does exactly what I need. I’m overjoyed with enthusiasm as I have GPT-4 update my lambda to use this newly discovered library. Why hadn’t it been suggested to me previously?

In this example, the get_cities_in_timezone function takes a target timezone as an argument and returns a list of cities in that timezone. The cities package provides a dictionary of cities and their related information, including the timezone.

now have it randomly select a single city from that list and return the latitude and longitude of the selected city, as well as the timezone and city name  ChatGPT To randomly select a single city from the list and return the latitude and longitude of the selected city along with the timezone and city name, you can update the find_location.py script as follows:

I have it update the script to randomly select a city from the list and also return the longitude and latitude.

Another much longer function emerges. I test for the second time.

i got this error "{   "errorMessage": "Unable to import module 'find_location': No module named 'cities'",   "errorType": "Runtime.ImportModuleError",   "requestId": "216b6ced-11a7-4686-b158-54bb7d1e25f7",   "stackTrace": [] }"  ChatGPT I apologize for the confusion. It seems that the cities package is not compatible with AWS Lambda. Instead, you can use the citytimezones package, which contains timezone information for major cities worldwide.  First, replace the cities package with citytimezones in your Python script. Update your find_location.py script as follows:

My test can’t find the cities module. ChatGPT claims that I’m facing compatibility issues between a Python package and Lambda?

That's unusual.

I've also spared you from reading quite a few interactions in which GPT-4 assisted me in packaging a zip file for Lambda deployment. It guided me through creating a virtual environment and installing a few packages - pytz, cities, and geopy.

Even with the best tools at our disposal, We still encounter stumbling blocks. It's all part of the journey, reminding us that problem-solving is an integral part of any coding expedition - being human or AI for that matter.

I’m pretty sure the problem is that there is no such thing as cities or citytimezones packages - but I’m not allowed to say that.

I break my first rule and strike gold

i don't think there is a package in python called "citytimezones"  ChatGPT I apologize for the confusion, and you're right. There isn't a package called citytimezones. My mistake.  An alternative solution is to use the GeoNames database. It provides a file containing cities and their timezones. You can download the cities1000.zip file from here, which contains cities with a population of 1,000 or more. Unzip the file to obtain cities1000.txt.  Next, create a Python script to parse the file and generate a JSON file with city names, timezones, and coordinates. Name the script parse_geonames.py:

I had to break the rule.

I was stuck for at least 30 min and could not discover a way forward here without being suggestive. I hated doing this, but I needed wanted progress.

Instead ChatGPT suggests that we use the GeoNames Database! They curate lists of cities and timezones!

I check and the GeoNames Database is real! The provided URL works and this dataset has exactly what I need.


What’s more is that the output of the script parse_geoname.py is actually pretty good - Spoiler alert: by the end of the project I’m still using some of this code.

GPT-4 then suggests that I update my code for the lambda to use the resulting json file and query it. After 3 errors it starts returning something; although its slow (due to locally processing a rather large json file, but I’m not supposed to know this) typically 8-10 seconds to get an answer. I ask it how I can understand which parts are slow. It suggests I print the time it takes after each section to discover this from the logs:

print(f"Time taken to load cities: {time.time() - start_time:.2f} seconds")

I’m going to speed this part up a bit as there are a lot of prompts, back and forth’s and otherwise boring yet helpful interactions, over the course of this project I asked 443 questions in this chat alone! There’s not enough time and let’s be honest, you’re not interested enough to read all of those messages (if you are a paid subscriber you can read the whole chat log in the paid content section at the end of this post.)

  • I ask if an AWS service can do this instead of time

    • Suggests X-Ray

  • I ask to implement X-Ray

    • Implements X-Ray in the lambda

  • I give it the logs from x-ray and CodeGuru Profile (which it implemented too)

    • It determines which areas in the functions take the longest (but outputs fictitious times)

  • I ask if I can use DynamoDB to store the json instead - There I go again breaking the rules

    • Yes you can

  • Write a script that can do that

    • Outputs Script !! using a Lambda Function!

    • Script uses Provisioned Capacity (more expensive than I’m willing to tolerate for a test so I ask it to use PAY_PER_REQUEST, I know, I know, I’m bad)

    • The Lambda function takes 10 minutes to run at the largest Lambda Size 🥵

  • 8 different questions about why the table isn’t populating

    • 7 different wrong answers

    • “stop using floats” - ChatGPT - this works.

  • 2 questions about failed hydration

    • track duplicate cities (there are none 😉 but I decide not to tell it this)

  • 22 questions to update the Lambda to use the DynamoDB table instead of the json file

    • working now!

I remind it another 10 times I don’t want provisioned capacity and we have to fix the float issue again and again until it works (it kept either reverting the code or not implementing strings in the right places). And it’s still slow, maybe 10seconds? (Its slow because we’re doing table scans instead of using a GSI in our DynamoDB table)

Here is the code for the lambda at this stage:

def lambda_handler(event, context):
    all_timezones = pytz.all_timezones

    five_pm_timezones = [
        timezone for timezone in all_timezones
        if 17 <= datetime.now(pytz.timezone(timezone)).hour < 18
    ]

    random_timezone = random.choice(five_pm_timezones)

    try:
        response = table.scan(
            FilterExpression=Key('timezone').eq(random_timezone)
        )
    except ClientError as e:
        print(e.response['Error']['Message'])
        return {
            'statusCode': 500,
            'body': 'An error occurred while fetching data from DynamoDB.'
        }

    if not response['Items']:
        return {
            'statusCode': 404,
            'body': f'No cities found in timezone: {random_timezone}'
        }

    random_city = random.choice(response['Items'])

    local_time = datetime.now(pytz.timezone(random_city['timezone'])).strftime('%Y-%m-%d %H:%M:%S')

    return {
        'statusCode': 200,
        'body': {
            'city': random_city['city_name'],
            'local_time': local_time,
            'latitude': random_city['latitude'],
            'longitude': random_city['longitude'],
            'timezone': random_city['timezone']
        }
    }

Here's a step-by-step explanation of what it does:

  1. Initialize all_timezones: It takes all the time zones available through the pytz library and stores them in the all_timezones list.

    all_timezones = pytz.all_timezones
  2. Find 5 PM Timezones: It filters all_timezones to create a new list, five_pm_timezones, containing only the timezones where the current local time is between 5 PM and 6 PM.

    five_pm_timezones = [
        timezone for timezone in all_timezones
        if 17 <= datetime.now(pytz.timezone(timezone)).hour < 18
    ]
    
  3. Random Timezone Selection: It randomly selects one timezone from five_pm_timezones.

    random_timezone = random.choice(five_pm_timezones)
  4. Query DynamoDB: It queries an AWS DynamoDB table using the table.scan method, filtering records where the 'timezone' key matches the random_timezone.

try:
    response = table.scan(
        FilterExpression=Key('timezone').eq(random_timezone)
    )
except ClientError as e:
    # Error handling for DynamoDB client error
  1. Handle Errors: If there is a client error with DynamoDB, it prints the error message and returns a response with status code 500.

  2. Check Response: It checks if the query returned any items (response['Items']). If not, it returns a response with status code 404 and a message saying no cities were found in the random_timezone.

if not response['Items']:
    return {
        'statusCode': 404,
        'body': f'No cities found in timezone: {random_timezone}'
    }
  1. Random City Selection: If there are cities found in the random_timezone, it randomly picks one.

random_city = random.choice(response['Items'])
  1. Local Time: It finds the local time in the timezone of the randomly picked city and formats it.

local_time = datetime.now(pytz.timezone(random_city['timezone'])).strftime('%Y-%m-%d %H:%M:%S')
  1. Return Data: Finally, it returns the response with status code 200 and the details of the randomly picked city, including its name, local time, latitude, longitude, and timezone.

    return {
        'statusCode': 200,
        'body': {
            'city': random_city['city_name'],
            'local_time': local_time,
            'latitude': random_city['latitude'],
            'longitude': random_city['longitude'],
            'timezone': random_city['timezone']
        }
    }

IT’S WORKING!

ok the find_location(the one that gives us an output like this {   "statusCode": 200,   "body": {     "city": "Waitangi",     "local_time": "2023-03-26 17:12:12",     "latitude": -43.95353,     "longitude": -176.55973,     "timezone": "Pacific/Chatham"   } })  lambda is working well now. I want to put api-gateway infront of the lambda so i can have a static webpage show this information with a map showing the location and the current time there
I broke down and asked for two things at once, the current message cap(25/3hr) is getting to me.

We now have a Lambda function, and a DynamoDB instance returning a random place in the world where it is between 5:00 PM and 5:59:59 PM- now to build the first version of the front end and make some IaC.

To get to this point I’ve only reviewed 1/7 of my chat logs with you.

In the next part I’ll tackle my MVP and Infrastructure as code.


Manifest

Part 0 - Introduction
Part 1 - Failing Fast (Building with prompts) *You are Here 💁‍♀️
Part 2 - MVP and Deployments
Part 3 - MVPolish
Part 4 - So what.

Share

I’m sure you want to see each and every prompt; but there are hundreds if not thousands of prompts and I couldn’t possibly paste them here…. oh, ChatGPT has link sharing - as a special offer for paid subscribers, you can access the enthralling conversation below

Keep reading with a 7-day free trial

Subscribe to One Twenty Three Cloud Street to keep reading this post and get 7 days of free access to the full post archives.

Already a paid subscriber? Sign in
© 2025 Will Laws
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share

Copy link
Facebook
Email
Notes
More