Explore Developer Center's New Chatbot! MongoDB AI Chatbot can be accessed at the top of your navigation to answer all your MongoDB questions.

MongoDB Developer
Python
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Languageschevron-right
Pythonchevron-right

Build an App With Python, Flask, and MongoDB to Track UFOs

SC
Shelby Carpenter15 min read • Published Feb 06, 2023 • Updated Feb 06, 2023
FlaskPython
Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty

Do You Want to Believe?

Have you ever looked up at the night sky and wondered what’s out there? Even as our knowledge of the cosmos expands — especially with the launch of the James Webb Space Telescope and the spectacular stream of photos it sends back — so many mysteries remain. A perpetual and existential question is whether there is other intelligent life out there.
While this question remains unanswered, there are plenty of citizen documentarians out there tracking appearances of unidentified flying objects (UFOs). The National UFO Reporting Center (NUFORC) collects reports of UFO sightings and stores them in a publicly accessible data bank.
To explore the capabilities of MongoDB and the Pymongo driver used with Python and Flask, I built a full-stack web application that allows users to look up reports of UFO sightings based on NUFORC data as well as submit a report back to a central database in the cloud with MongoDB Atlas.
You can access the full codebase for the app, but follow along for the rest of the tutorial to learn how to build this on your own!

Application requirements

To be successful with this tutorial, you should already have the following ready to go:

Upload data and organize MongoDB collection

To get started, you’ll need to have the data from NUFORC uploaded to MongoDB Atlas. To do this, download a free scrubbed CSV file of this data available on Kaggle.
Log into Atlas and copy your connection string. Then, open up MongoDB Compass on your computer and click the “New Connection” button to enter your Atlas connection string and connect to your Atlas database. From there, create a database called “ufos” and a collection in that database, also called “ufos”. When you click on the “ufos” collection, you’ll be taken to a screen where you will upload the CSV file of UFO reports you downloaded from Kaggle.
A view of the documents tab in MongoDB Compass
Now you have a collection of UFO reports in the cloud with Atlas that you can use as part of your application.

Set up Flask

Regardless of your chosen IDE and whether you’re working in a virtual environment or on your local machine, follow Flask best practices for organizing your workspace for building this app.
I’ve been exploring GitHub Codespaces lately and started building off of a sample Flask application there. But you may have the best experience using VS Code and the MongoDB VS Code Extension.
Create one folder for everything for your application called “ufo-spotter-app”. Within that folder, create one folder called static which will eventually contain the assets used by your templates. Create a second folder called templates within the ufo-spotter-app parent folder where your .html template pages will live.

Build your foundational templates and styling

Now that everything is set up in your development environment and you have your data uploaded to MongoDB, you’re ready to start coding! You’ll start by building out your templates. In Flask, templates contain static data as well as dynamic data that can be passed in with the help of the Jinja library in Flask. You can learn more about Flask templates in the Flask documentation.

Create layout.html

The first template you’ll build is layout.html. This template will serve as the basis of the other templates, with Jinja making it easier to build off of layout.html without having to write the same code again and again. See below for the code for layout.html, which establishes the document type as html, the language as English, the default CSS styling coming from Bootstrap but with a link to a second main.css file we’ll create next, and the navbar your users will rely on to navigate the website.
1<!DOCTYPE html>
2
3<html lang="en">
4
5 <head>
6
7 <meta charset="utf-8">
8 <meta name="viewport" content="initial-scale=1, width=device-width">
9
10 <!-- http://getbootstrap.com/docs/5.1/ -->
11 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
12 <link href="/static/main.css" rel="stylesheet">
13
14 <title> {% block title %} UFO Spotter {% endblock %}</title>
15
16 </head>
17
18 <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
19 <div class="container-fluid">
20 <a href="/" class="navbar-brand"> UFO Spotter
21 </a>
22 <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navbarCollapse">
23 <span class="navbar-toggler-icon"></span>
24 </button>
25 <div class="collapse navbar-collapse" id="navbarCollapse">
26 <div class="navbar-nav">
27 <a href="/" class="nav-item nav-link active">Sightings by City</a>
28
29 <div class="collapse navbar-collapse" id="navbarCollapse">
30 <a class="nav-item nav-link active">|</a>
31 <div class="navbar-nav">
32 <div class="collapse navbar-collapse" id="navbarCollapse">
33 <div class="navbar-nav">
34 <a href="/submit.html" class="nav-item nav-link active">Report a Sighting </a>
35 </div>
36 </div>
37 </nav>
38
39
40 <main class="container-fluid py-5 text-center">
41 {% block main %}
42 {% endblock %}
43
44 </main>
45</html>
The html in this section creates the navbar with clickable sections at the upper left that will be consistent across all pages:
UFO spotter

Create Main.css

Now, let’s add a little flair to the default CSS styling we already have from Bootstrap. Create a file called Main.css in the “static” folder with the following code:
1body {
2 margin: 0;
3 font-family: American Typewriter, serif
4}
5
6.small {
7 font-size: 0.75rem;
8}
9
10.h3 {
11 margin-bottom: 10px;
12
13}
14
15footer {
16 position: absolute;
17 bottom: 0;
18 width: 100%;
19 height: 2.5rem;
20}
The font choice of American Typewriter is intended to give off a minimalist and spooky vibe in line with the UFO theme, while still being easy to read.

Let users look up UFO sightings

Now we’re really getting into the meat of the application. The next thing we’re going to do is set up our web application to allow users to enter a U.S. city and state and get back statistics on UFO sightings as well as a list of the 10 most recent sightings. This way, they’ll know what to be on the lookout for.

Create city.html

Let’s make the html template that we’ll render to let users input a U.S. city and state. First you have to enter {% extends "layout.html" %} at the top to base this file off of layout.html. Then we’ve got a fun image (sourced from Flaticon), some text to tell website visitors how to use the page, and a form. The first section of the form lets a user enter text for the name of the city. The next uses a Jinja for loop to provide a select box for U.S. states based on a Python list of state abbreviations in the app.py file. After that, we just have the “Submit” button to trigger the form completion and a footer at the bottom to provide appropriate attribution for the UFO image.
1{% extends "layout.html" %}
2
3{% block title %}
4 Get UFO Reports
5{% endblock %}
6
7{% block main %}
8
9<img src="/static/ufo_icons/ufo7.png" width="100" height="100" alt="">
10
11 <h5>Enter City and State:</h5>
12 <form action="/" method="post">
13 <p>
14 <input autocomplete="off" autofocus name="city" placeholder="City" type="text" required>
15 </p>
16 <p>
17 <select class="mx-auto" name="state" placeholder="State" style="width:auto;">
18
19 {% for state in states %}
20
21 <option value="{{ state }}">{{ state }}</option>
22
23 {% endfor %}
24 </select>
25
26
27 </p>
28 <p>
29 <button type="submit" class="btn btn-primary">Submit</button>
30 </p>
31 </form>
32
33 <footer class="page-footer font-small blue">
34
35 <div class="footer-attribution text-center">
36 <a href="https://www.flaticon.com/free-icons/alien" title="alien icons">Alien icons created by Freepik - Flaticon</a>
37
38 </div>
39
40 </footer>
41{% endblock %}
Here’s what the page looks like when rendered:
The landing page on the UFO Spotter website where the website visitor can enter a U.S. city and state and look up reports of UFO sightings

Look up data with the MongoDB Query API in helpers.py

One of the great features of MongoDB is the document model, which gives you the flexibility to model your data as JSON-like documents that easily map to objects in your code. I’ve personally found this much easier than a relational approach using a myriad of different tables and managing table joins for different projects.
To support the main app.py file for this application, we will create a helpers.py file with two helper functions that pull data from the MongoDB Atlas database using the MongoDB Query API.
The first function, get_count(), uses the $match and $count aggregation stages in the Query API to find UFO reports with the same U.S. city and state as input by the user and returns the total number of UFO reports matching that city/state combination.
The second function, get_ufos(), uses the $match and $sort aggregation stages. This function also finds UFO reports with the same U.S. city and state as input by the user, and then returns all of those reports sorted by the date of the sighting from most recent to oldest.
1import requests
2
3
4from flask import redirect, render_template, request
5from pymongo import MongoClient
6
7
8client = MongoClient('YOUR_CONNECTION_STRING')
9
10
11def get_count(city, state):
12 """Count the UFO sightings for that city and state"""
13
14
15 city_count = client['ufos']['ufos'].aggregate([
16 {
17 '$match': {
18 'city': city
19 }
20 }, {
21 '$match': {
22 'state': state
23 }
24 }, {
25 '$count': 'ufo_count'
26 }
27 ])
28
29
30 return city_count
31
32
33def get_ufos(city, state):
34 """Gets report of UFO sightings for that city and state"""
35
36
37 recent_ufos = client['ufos']['ufos'].aggregate([
38 {
39 '$match': {
40 'city': city
41 }
42 }, {
43 '$match': {
44 'state': state
45 }
46 }, {
47 '$sort': {
48 'datetime': -1
49 }
50 },
51 ])
52
53
54 return recent_ufos

Create app.py

Now let’s take a look at the first portion of the app.py file. First you need to import re to allow for regular expressions. You’ll also need to import date from datetime to help with processing the dates related to sightings. You’ll get Flask for building your Flask app as well as render_template to help with displaying templates and request for taking user inputs from forms in your html templates. Finally, you’ll need to import the functions we built in helpers.py.
After a few more lines of code to set up your application, you’ll set up your client variable to connect to MongoDB Atlas with your connection string (make sure to substitute in your actual connection string for the placeholder in the code). And you’ll want to declare an array of U.S. state abbreviations to be displayed in city.html.
1import re
2from datetime import date
3import datetime
4
5from flask import Flask, render_template, request
6from pymongo import MongoClient
7from helpers import get_count, get_ufos
8
9app = Flask(__name__)
10
11if __name__ == "__main__":
12 app.run()
13
14client = MongoClient('YOUR_CONNECTION_STRING')
15db = client['ufos']
16ufos = db.ufos
17
18# Declare array of U.S. states to use in later functions
19states = ["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]
Now that you’ve set this Python file as the core file at the heart of your Flask application, you’ll create your city() function with a decorator that assigns the URL and allows this function to receive both GET and POST HTTP requests.
When receiving a GET request from the user, this function will display the city.html file we created earlier, passing in the states array for us in that file.
If the function is called with an HTTP POST request, we process the U.S. city and state input by the user once they hit the “Submit” button in city.html. This function also includes some error-handling and returns an appropriate error message to the user if the city name they submit includes a numeral or a special character, which it never should.
Using the .lower() method in Python, we convert the uppercase abbreviation for the U.S. state to lowercase to match the format of the UFO reports data set.
We are able to get the number of UFO reports in the state specified by the user with the .count_documents() method in PyMongo. This is a handy method for when you just need to count the number of documents matching along a specific field, versus having to build a full aggregation pipeline with $match and $count to get that result.
Next, we get the number of UFO reports for that city/state combination using our get_count() helper method and a list of UFO sightings for that area with the get_ufos() helper function. Then the number of sightings in that state is assigned to the variable state_count.
The number of sightings in that city/state combination is returned as a cursor with PyMongo, which we can later iterate over using a Jinja for loop. And finally, we get a cursor we’ll name recent_ufos (which we can also use to iterate over the group of sightings the cursor points to) that points to a list of sightings for that city/state. Then state_count, city_count, and recent_ufos are passed to the results.html template to be displayed to the user.
1@app.route("/", methods=["GET", "POST"])
2def city():
3
4 # Let user submit city and state to look up UFO sightings
5 if request.method == "GET":
6
7 return render_template("city.html", states=states)
8
9 # Return and display results
10 if request.method == "POST":
11
12 # Get city and state from user
13 city = request.form.get("city")
14 state = request.form.get("state")
15
16 # Define error message
17 message = "the name of a valid U.S. city"
18
19 # Return error message if user enters number in city name
20 if request.form.get("city").isnumeric() is True:
21 return render_template("error.html", message=message)
22
23 # Return error message if user enters special character in city name
24 # Attribution: Found way to check for special characters with regex here: https://www.geeksforgeeks.org/python-program-check-string-contains-special-character/
25 regex = re.compile('[@_!#$%^&*()<>?/\|}{~:]')
26 if regex.search(city) is not None:
27 message = "the name of a valid U.S. city"
28 return render_template("error.html", message=message)
29
30 # Convert city and state to lower case
31 state = state.lower()
32
33 # Count number of UFO sightings in state
34 state_count = ufos.count_documents({"state": state})
35
36 # Get number of UFO sightings in city and state as a list
37 city_count = get_count(city, state)
38
39 # Get list of recent UFO sightings
40 recent_ufos = get_ufos(city, state)
41
42 return render_template("results.html", state_count=state_count, city_count=city_count, recent_ufos=recent_ufos)

Create results.html

Now that we have our html page where users can input their city and state, a function in our app.py file to process that information from the user, and some helper functions to support looking up the relevant data, we’re ready to display results for the user. The results.html page is displayed as the result of a successful POST request to the city() function in app.py. This page extends the layout.html template and shows statistics and information on sightings for the U.S. city and state input by the user.
We’ll display the value of state_count passed in from the city view function for the total sightings in the state input by the user on this page. Next, we’ll use a Jinja for loop to loop over our list of dictionaries pointed to by the city_count cursor, and pull the city dict's "ufo_count" value to display in the page.
We’ll also use a Jinja for loop to loop through the list of dictionaries pointed to by the recent_ufos cursor. As we go through the loop, we can pull the specific values we’re looking to display for the sightings using Python's usual syntax for looking up a value in a dict.
1{% extends "layout.html" %}
2
3{% block title %}
4
5 UFOs in Your City and State
6
7{% endblock %}
8
9{% block main %}
10
11 <h3>Local Stats:</h3>
12 <p>
13 <b>Total sightings in your state:</b> {{state_count}}
14 </p>
15 <p>
16 <b>Total sightings in your city:</b>
17 {% for city in city_count %}
18 {{city["ufo_count"]}}
19 {% endfor %}
20 </p>
21
22
23 <br>
24
25 <h3>Recent UFO Sightings:</h3>
26
27 <div class="row mx-auto">
28
29 {% for ufo in recent_ufos %}
30
31 <div class="col-sm-6 mx-auto">
32 <div class="card text-white bg-secondary mb-3">
33 <div class="card-body">
34 <p>
35 <b>Date of Sighting: </b>{{ufo['datetime']}}
36 </p>
37 <p>
38 <b>Date Reported </b>{{ufo['date posted']}}
39 </p>
40 <p>
41 <b>Shape: </b>{{ufo['shape']}}
42 </p>
43 <p>
44 <b>Duration (hours/minutes): </b>{{ufo['duration (hours/min)']}}
45 </p>
46 <p>
47 <b>Description: </b>{{ufo['comments']}}
48 </p>
49 </div>
50 </div>
51 </div>
52
53 {% endfor %}
54
55{% endblock %}
Here’s how this page looks after searching for UFO reports in Birmingham, Alabama:
Statistics and a list of UFO sightings for the U.S. city and state the website visitor submitted through the form

Create error.html

The last thing we’ll need to do in this section is create our error.html file, which the user sees if they don’t enter any text for the city name or a numeric or special character. This is a very simple html file with the error message passed in to it from app.py.
1{% extends "layout.html" %}
2
3{% block title %}
4 Error
5{% endblock %}
6
7{% block main %}
8 <body>
9 You must submit {{message}}.
10 </body>
11{% endblock %}
The next step we’ll take to build this out even further is adding functionality for users to input their own UFO sightings to the database for others to reference in the future.

Submit new UFO sighting and write to database

At this point, we have a fully functional Flask web application where users can submit a city and state, read from the MongoDB Atlas database, and get statistics and a list of sightings back. Now, let’s add functionality to write to the database with a function and supporting html pages that let users add their own UFO sightings.

Add a new function to App.py

Similar to the our city() function we’ve already created in app.py, our new submit() function will take both GET and POST requests.
The first thing we’ll set up in this function is processing our GET request. A GET request here leads to the display of the submit.html page, which will display a form with the relevant fields for the user to submit their sighting. We’ll pass in the array of U.S. states we used earlier for the state select field in the form.
For our POST request, the first thing we’ll do is create an empty Python dictionary called ufo_report to hold the report the user is submitting.
Next, we’ll use the request.form.get() function to pull the values the user added to the form and assign them to variables. Using date.today(), we can pull today’s month, day, and year to get the date of the report submission without the user having to manually enter it. Then, using today.strftime(), we put it in the right format to match the rest of the data set.
One important thing to note is that it is generally best practice to store date and time data with Python datetime.datetime objects (PyMongo will save these as native MongoDB date types) rather than as a string as we do here. However, for simplicity in working with the public data set from NUFORC, we will be storing this information as strings instead. This way, you won’t need to download the data from NUFORC and convert all of the strings from the data set into the proper object type for use in this tutorial.
Similar to our function that lets our users look up sightings by city and state, we’ll want to check for incorrect entries in the state field in the form. We’ll use isnumeric() to check if any numbers have been entered in the city name and a regular expression to check for special characters. We’ll then display an error message if anything is amiss.
Now that we have our variables pulled from the form, we will combine them in our empty python dictionary with the assignment operator and specify the appropriate keys for each value. Since this application only looks at UFO sightings in the U.S. (for now), we’ll manually set the country abbreviation as “us”. Once our dictionary for the UFO report is complete, we insert it into our ufos collection in our MongoDB Atlas database with ufos.insert_one(ufo_report).
After our report has been added, we’ll display a simple thank-you message to the user in thank_you.html.
1@app.route("/submit.html", methods=["GET", "POST"])
2def submit():
3
4 # Display form for user to submit report of UFO sighting
5 if request.method == "GET":
6
7 return render_template("submit.html", states=states)
8
9 # Get data on UFO sighting from form and add to MongoDB
10 if request.method == "POST":
11
12 # Create empty Python dictionary to hold UFO report submitted by form
13 ufo_report = {}
14
15 # Get UFO report information from user form submission
16 city = request.form.get("city")
17 state = request.form.get("state").lower()
18 shape = request.form.get("shape")
19 duration_seconds = request.form.get("duration_seconds")
20 duration_minutes = request.form.get("duration_minutes")
21 comments = request.form.get("comments")
22 sighting_date = request.form.get("datetime")
23 latitude = request.form.get("latitude")
24 longitude = request.form.get("longitude")
25
26 # convert string style date into datetime format
27 sighting_date = datetime.datetime.strptime(sighting_date, "%Y-%m-%dT%H:%M")
28
29 # Get date that user submitted the form
30 # Attribution: Found this way to convert time of form submission here: https://www.programiz.com/python-programming/datetime/current-datetime
31 today = date.today()
32 today = today.strftime("%m/%d/%y")
33
34 # Return error message if user enters number in city name
35 if request.form.get("city").isnumeric() is True:
36 return render_template("error.html", message=message)
37
38 # Return error message if user enters special character in city name
39 # Attribution: Found way to check for special characters with regex here: https://www.geeksforgeeks.org/python-program-check-string-contains-special-character/
40 regex = re.compile('[@_!#$%^&*()<>?/\|}{~:]')
41 if regex.search(city) is not None:
42 message = "the name of a valid U.S. city"
43 return render_template("error.html", message=message)
44
45 # Compile report details into Python dictionary
46 ufo_report["datetime"] = sighting_date
47 ufo_report["city"] = city
48 ufo_report["state"] = state
49 ufo_report["shape"] = shape
50 ufo_report["duration (seconds)"] = duration_seconds
51 ufo_report["duration (hours/min)"] = duration_minutes
52 ufo_report["comments"] = comments
53 ufo_report["country"] = "us"
54 ufo_report["date posted"] = today
55 ufo_report["latitude"] = latitude
56 ufo_report["longitude"] = longitude
57
58 # Add UFO sighting report to MongoDB Atlas database
59 ufos.insert_one(ufo_report)
60
61 # Return thank-you message after report submission
62 return render_template("thank_you.html")
If you wanted to do some extra credit, you could also model the latitude and longitude values as a GeoJSON Point type and index it for GIS queries. See how in the MongoDB documentation.

Create submit.html

Next, we’ll create the html page that’s displayed when the user submits a GET request to the submit() function. This page displays a form where the users can submit a record of their own UFO sighting. The design of the form is largely drawn from Bootstrap. As we did the city.html page, we’ll pass in the states array and create a Jinja loop to allow users to select a state from that array.
1{% extends "layout.html" %}
2
3{% block title %}
4 Submit UFO Sighting Report
5{% endblock %}
6
7{% block main %}
8<h5>Report a UFO Sighting</h5>
9
10<br>
11
12<form action="/submit.html" method="post">
13 <div class="form-group">
14 <b>City:</b> <input autocomplete="off" autofocus name="city" id="city" type="text" required>
15 </div>
16
17 <br>
18
19 <div class="form-group">
20
21 <b>State:</b>
22 <select class="mx-auto" name="state" id="state" placeholder="State" style="width:auto;">
23
24 {% for state in states %}
25
26 <option value="{{ state }}">{{ state }}</option>
27
28 {% endfor %}
29 </select>
30 </div>
31
32 <br>
33
34 <div class="form-group">
35 <b>Latitude:</b> <input autocomplete="off" autofocus id="latitude" name="latitude" type="numeric" required>
36 <b>Longitude:</b> <input autocomplete="off" autofocus id="longitude" name="longitude" type="numeric" required>
37 </div>
38 <p>
39 Don't know your latitude and longitude? <a href="https://www.latlong.net/">Look it up here.</a>
40 </p>
41
42 <br>
43
44 <div class="form-group">
45 <b>Duration (seconds):</b> <input autocomplete="off" autofocus id="duration_seconds" name="duration_seconds" type="numeric">
46 </div>
47
48 <br>
49
50 <div class="form-group">
51 <b>Duration (hours/minutes):</b> <input autocomplete="off" autofocus id="duration_minutes" name="duration_minutes" type="text" required>
52 </div>
53
54 <br>
55
56 <div class="form-group">
57 <b>Shape:</b> <input autocomplete="off" autofocus id="shape" name="shape" type="text" required>
58 </div>
59
60 <br>
61
62 <div class="form-group">
63 <label><b>Date and Time:</b></label>
64 <input placeholder="datetime" name="datetime" type="datetime-local" required>
65 </div>
66
67 <br>
68
69 <div class="row d-flex justify-content-center">
70 <div class="form-group" style="width:50%">
71 <label><b>Comments:</b></label>
72 <textarea class="form-control" rows="2" name="comments" id="comments"></textarea>
73 </div>
74 </div>
75
76 <br>
77
78 <button type="submit" class="btn btn-primary">Submit</button>
79</form>
80{% endblock %}
Here’s how this page looks when rendered:
A web page displaying a form where the website visitor can submit a report of a UFO sightings

Create Thank_You.html

This page uses Jinja to extend the layout.html template and display a simple (and fun) text thank-you message after the user successfully submits a UFO sighting report.
1{% extends "layout.html" %}
2
3{% block title %}
4 Thank You
5{% endblock %}
6
7{% block main %}
8
9<p>
10 Thank you for submitting your report. Live long and prosper. 🖖
11</p>
12{% endblock %}

Conclusion

We may not be able to verify that aliens are out there in space. But we can track UFOs in cyberspace with MongoDB, Python, and Flask.
With the ease of use of Python and Flask, and the flexibility of MongoDB’s document model, we’ve now built an app to let users find statistics about UFO sightings in their area, get recent UFO sighting reports, and submit a sighting if they are lucky (or unlucky) enough to have an alien encounter of their own.
See the full codebase for this tutorial on GitHub. If you thought this material was valuable, be sure to rate this tutorial below and share a link on social!
Thank you to Shubham Ranjan for contributing edits and bug fixes to this tutorial and supporting code.

Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Tutorial

Testing and Packaging a Python Library


Aug 14, 2024 | 8 min read
Code Example

Example Application for Dog Care Providers (DCP)


Jul 12, 2024 | 3 min read
Tutorial

How to Optimize LLM Applications With Prompt Compression Using LLMLingua and LangChain


Jun 18, 2024 | 13 min read
Article

Discover Latent Semantic Structure With Vector Clustering


Oct 11, 2024 | 10 min read
Table of Contents