Picky is an online image gallery designed to manage and search through a user's extensive library of digital photos. The app's unique selling point is its ability to search and filter images based on natural language queries, including the names of people in the images. Picky delivers relevant images quickly and accurately by leveraging a combination of advanced concepts and AI tools, such as machine vision, vector or graph databases, and Large Language Models (LLMs). Each user has their own private account and gallery, ensuring a personalized and secure experience.
I wanted to give a talk to my local AI meetup group about using AI at every step of the development process. For this talk, I created this challenge:
- Use AI-assisted tools from conception to delivery
- Go from a basic idea to a running, end-to-end proof-of-concept
- Not write a single line of code!!! 🤯
- Use modern technologies that I am NOT familiar with:
- Full-stack Next.js project
- IDE with AI capabilities
- Vector database
- Document the process along the way
- Do all of this in ~1 week
Picky was the use case I settled on. You can check out the resulting slide deck I presented.
- Using a IDE with integrated AI capabilities (Cursor) to 💯% create, refactor, and troubleshoot code
- Using a LLM (Claude 3.5 Sonnet) to generate various artifacts through the project, e.g. project plans, architectural design, code, documentation
- Using a LLM (GPT-4o) + accompanying prompt engineering for the computer vision tasks needed to analyze images
- Using a LLM (OpenAI) for generating embeddings for semantic search
- Using a vector database (pgvector in Supabase) for storing and querying embeddings
- Next.js full-stack app with Tailwind CSS
- Supabase with pgvector
The full scope is shown below, but time constraints limited what I was able to implement.
-
User Authentication: Users can sign up, log in, and reset their passwords. Each user has their own private gallery.
-
Image Upload: Users can select and add images to their personal gallery.
-
Image Analysis: Each uploaded image is analyzed for:
- Objects (including text, inanimate objects, people, landmarks)
- Scene detection
- Qualitative aspects (description of what the image is showing)
-
Manual Metadata: Users can manually add additional metadata, such as:Geolocation where the photo was takenNames of people appearing in the photo
-
Data Persistence: All image data is stored in an optimal database for natural language searching (e.g., vector database for RAG-style querying).
-
Facial Recognition: The system can perform facial recognition to:Match faces with known people in the datastoreAutomatically tag people in new photos
-
Gallery View: A user interface allows browsing through all images in a masonry-style layout within the user's private gallery.
-
Semantic Search: Users can
speak ortype requests, and the system will:- Execute a semantic search
- Identify images matching the query
- Display a filtered list in a masonry-style layout
-
User Account Management: Users can manage their account settings, update profile information, and control privacy settings.
Pre-requisites:
- Git installed locally
- Node.js + NPM installed on your local machine
- A free Supabase account
- An OpenAI account
-
Create a new base directory for your code projects, e.g. 'Code'.
-
From a terminal go into that 'Code' directory and pull down the code via
git clone https://github.com/tsekula/Picky-Next.git
This will create a new sub-directory named 'Picky-Next'.
-
Go into that 'Picky-Next' directory and install the app + its dependencies by running this command:
npm install
-
Create a new Supabase project by following the steps at https://database.new/. Name the project
Picky
.While it's setting up the project, copy-and-paste these values into your local
/.env
file and save:NEXT_PUBLIC_SUPABASE_URL=XXXXXXXXX // 'Project URL' in Supabase NEXT_PUBLIC_SUPABASE_ANON_KEY=XXXXXX // 'anon public' Project API Keys in Supabase
You can find these values via the 'Project Settings' -> 'API' section in the Supabase dashboard for your project
-
Set up the Supabase storage
- From the Supabase dashboard for your project click on 'Storage' in the left nav bar.
- In the upper-left, click the 'New Bucket' button and enter 'images' as the name of the bucket. Click 'Save'
- Create another bucket named 'thumbnails', important: set this bucket to 'Public bucket'!
-
Set up the Supabase database.
- From the Supabase dashboard for your project click on 'SQL Editor' in the left nav bar
- In the upper-left, next to the 'Search queries...' input box, click the '+' symbol and then click 'Create a new snippet'.
- Create the tables: In the text editor window, copy-and-paste the script from the 'Create Tables' section of this page. Click the green 'Run' button to execute the script. You should see a
Success. No rows returned
message confirming the action. - Create the indexes: In the same text editor window, delete the existing text. Copy-and-paste the script from the 'Create Indexes' section of this page. Run the script. You should see a
Success. No rows returned
message confirming the action. - Create the match function: In the same text editor window, delete the existing text. Copy-and-paste the script from the 'Create Functions' section of this page. Run the script. You should see a
Success. No rows returned
message confirming the action. - Create the Row Level Security (RLS) policies: In the same text editor window, delete the existing text. Copy-and-paste the script from the 'Create RLS Policies' section of this page. Run the script. You should see a
Success. No rows returned
message confirming the action. - Create the Storage policies: In the same text editor window, delete the existing text. Copy-and-paste the script from the 'Create Storage Policies' section of this page. Run the script. You should see a
Success. No rows returned
message confirming the action.
-
Set up your image gallery sign-in account in Supabase
- From the Supabase dashboard for your project click on 'Authentication' in the left nav bar.
- On the 'Users' screen, click the green 'Add user' button on the far right, then 'Create new user'. Enter an email address and password that you will use to login to your image gallery. Click 'Create User'.
- In the left nav bar click 'Table Editor', then click on the 'user_roles' table name. Click the green 'Insert' button, then 'Insert row'. For the 'user_id' field, click 'Select record', then in the pop-up choose the 1 and only record shown. Set 'can_upload' to
TRUE
. Click 'Save'.
-
Add your OpenAI API key
- Create a new API key via the OpenAI dashboard. Make sure permissions are set to 'All'.
- Copy-and-paste the new API key into your local
/.env
file and save:OPENAI_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXX
To start the app's backend server, run this command from the /Picky-Next folder:
npm run dev
Open http://localhost:3000 with your browser to see the result.
Upon launching the app, you will be redirected to the login page. Use the 'sign-in account' you created in the setup steps above to log in.
Once logged in, you'll see the image gallery. By default it will be empty, so you'll need to upload some images. Click on the '+' button in the nav and the upload area will appear. You can use it to upload 1 or more images at once.
After uploading images, the gallery will refresh to display the newly uploaded images. You can click any image to see a larger version, along with the current metadata. Important: Only basic info about the image (name, date uploaded, file type) will appear at this point.
To perform the full computer vision analysis, you have to manually trigger it. Click on the purple 🪄 button to initiate the analysis of all unprocessed images. This analysis will take 2-10 seconds for each 1 image, so be patient. There is no indicator that the analysis is complete 😳 (I just didn't implement it -- sorry). You can go check the 'images' table in Supabase to see the status for each image change 'unprocessed' -> 'pending' -> 'complete'.
To check the result of the computer vision analysis, click on an image to see a larger version. The metadata will be updated with the results of the computer vision analysis.
Now you can conduct a semantic search. Enter a search query in the text box and click 'Search' to see a filtered list of images that match the search query. Click the 'X' to reset the search.