avatarFS Ndzomga

Summary

The article outlines the process of integrating a PostgreSQL database with vector embedding capabilities into a fastapi application for a RAG (Red, Amber, Green) system.

Abstract

The article is the third in a series focusing on the development of a RAG system using fastapi. It details the enhancement of the application by incorporating a PostgreSQL database capable of handling vector embeddings for similarity search. The author emphasizes the use of defensive programming and the open-closed principle to ensure code robustness and extensibility. The database schema is designed to index uploaded files and store text chunks with corresponding embeddings. The article provides instructions on necessary software installations, including PostgreSQL, pgvector, and Python packages like sqlalchemy and psycopg2. A Python script is introduced to automate database creation, utilizing SQLAlchemy for interaction with the database. The script is designed to work with environment variables for security and flexibility. The author plans to discuss file detail storage, file chunk creation, and embedding generation as background tasks in the next article, using celery and redis for time-consuming operations.

Opinions

  • The author values the ease of extending the application's functionality, as evidenced by the use of the open-closed principle in the codebase.
  • There is an emphasis on the importance of defensive programming to strengthen the application against potential issues.
  • The author shows a preference for SQLAlchemy as a toolkit for SQL database interaction, highlighting its power and flexibility.
  • The use of pgvector for storing and querying text embeddings indicates the author's interest in leveraging advanced database features for machine learning applications.
  • The author suggests a cost-effective alternative to ChatGPT Plus (GPT-4), named ZAI.chat, indicating a belief in the value of more affordable AI services.
  • The author's sign-off, "Stay tuned!" and "Happy coding!", conveys enthusiasm and a commitment to providing future insights on the topic.

Building A Simple RAG System With Fastapi (3)

Photo by Campaign Creators on Unsplash

The goal of this series of articles is to build a RAG system with fastapi. In the first article, I designed a fastapi application that gives users the ability to upload documents. These documents are then parsed and stored locally for later usage.

In the second article, I refactored my code to make the application stronger using defensive programming strategies. I also used the open closed principle to make sure my application can be easily extended to support new functionalities.

In this article, I will focus on adding a PostgreSQL database to my application.

But I won’t just add any basic PostgreSQL database. I want my DB to be able to store vector embeddings that I will later on use for similarity search.

Here is a basic representation of our future database schema:

Each file uploaded by the user will be indexed in the “files” table of our database. In the background, we will also add a mechanism to create text chunks from the content of each file and their corresponding embeddings. We will store these chunks in the file_chunks table of our database.

You will need to have PostgreSQL and pgvector installed on your system.

You will also need to install sqlalchemy and psycopg.

pip install sqlalchemy psycopg2 sqlalchemy-utils

Finally, since we want to store text embeddings and be able to query them and manipulate them using cosine similarity, you will need to install pgvector’s python package.

pip install pgvector

To make things a bit industrial, I decided to create a python script to handle the database creation for us. We will only need to add the necessary information in our .env file for the script to work.

Your .env file should at least look like this:

POSTGRES_USERNAME = 'your_username'
POSTGRES_PASSWORD = 'your_password'

Here is the code to create our database. It utilizes SQLAlchemy, a powerful and flexible toolkit for SQL database interaction in Python. The script starts by importing necessary modules from SQLAlchemy for database connection (create_engine), table and column definitions (Column, Integer, String, Text, ForeignKey), and ORM base class creation (declarative_base). It also imports sessionmaker for managing database sessions and text for executing raw SQL commands.

Environment variables are loaded using dotenv, ensuring sensitive information such as database credentials is not hard-coded into the script. These credentials—username, password, host, port, and database name—are retrieved from environment variables and used to construct the database URL. The password is URL-encoded to handle special characters.

An SQLAlchemy engine is created with the database URL. This engine is a core component of SQLAlchemy that provides a source of database connectivity and behavior. The script checks if the database exists and, if not, creates it using database_exists and create_database utilities.

The database models (tables) are defined using SQLAlchemy ORM’s declarative system, where File and FileChunk classes represent tables in the database. The File class defines a table for storing file information, while FileChunk includes an additional embedding_vector column using Vector from pgvector.sqlalchemy, indicating advanced vector data handling, likely for machine learning or similar applications.

A database session is created and used to execute the SQL command for enabling the vector extension, essential for the embedding_vector column in FileChunk. Finally, Base.metadata.create_all(engine) is called within a try-except block to create these tables in the database, with error handling to catch and print any issues that occur during table creation.

That’s it for today.

In the next article, I will explain how to save file details in the DB after each upload. I will also explain how to create file chunks and embeddings for these chunks. Since the embeddings creation can be time consuming, we will do it as a background task using celery and redis.

Stay tuned!

And remember, whatever the challenges you are currently experiencing in your life, it won’t be eternal !

Happy coding!

Python
Rag
Fastapi
OpenAI
Postgresql
Recommended from ReadMedium