A Retrieval-Augmented Generation (RAG) chatbot application that answers questions about airline travel policies for major airlines. This chatbot uses LangChain to process airline policy documents, stores vector embeddings in PostgreSQL with pgvector, and provides a conversational interface powered by OpenAI's GPT models.
This chatbot application was designed to demonstrate deployment to Akamai App Platform using Linode Kubernetes Engine (LKE). It showcases a complete RAG (Retrieval-Augmented Generation) pipeline that:
- Processes airline policy documents (PDF, HTML, TXT) from Linode Object Storage
- Generates vector embeddings using OpenAI's embedding models
- Stores embeddings in PostgreSQL with pgvector extension for semantic search
- Maintains conversation history using LangGraph with PostgreSQL checkpointing
- Provides a web-based chat interface for querying airline policies
- Uses OpenAI's chat completion API for generating contextual responses
- Backend: FastAPI (Python 3.11)
- RAG Framework: LangChain, LangGraph
- Vector Database: PostgreSQL with pgvector extension
- Conversation State: PostgreSQL with LangGraph checkpointing
- Document Storage: Linode Object Storage (S3-compatible)
- AI/ML: OpenAI API (embeddings and chat completions)
- Deployment: Akamai App Platform on Linode Kubernetes Engine
- Infrastructure: Terraform for Linode resource provisioning
- Create an Akamai Cloud account here with API token (we have a $300 credit just for you)
- OpenAI API key
- Terraform installed
- kubectl installed
- s3cmd installed (for uploading documents)
Clone the repository to your local machine to get started with the deployment process.
git clone <repository-url> project
cd projectIn the Akamai Cloud Console, create a Linode API key with read/write permissions for databases, Linodes, Kubernetes, and object storage, and read permissions for events.
(Go to high-resolution screencast)
Copy the terraform/terraform.tfvars.example file as terraform.tfvars and edit it to add your Linode API key and make any other desired non-default configurations.
cp terraform/terraform.tfvars.example terraform/terraform.tfvars
# Edit terraform.tfvars with your API key and settings
(Go to high-resolution screencast)
Run Terraform to provision the required infrastructure (PostgreSQL database for vectors, PostgreSQL database for conversation state, LKE cluster, object storage bucket for knowledge base documents).
cd terraform
terraform init
terraform plan
terraform apply
(Go to high-resolution screencast)
Capture the Terraform outputs to a JSON file for easy access, but keep this file secure since it contains sensitive information like database connection strings and API keys.
terraform output -json > terraform.output.json
(Go to high-resolution screencast)
Use s3cmd to upload files in the documents/ folder to the Linode Object Storage bucket created by Terraform.
export S3_BUCKET=$(terraform output -raw S3_BUCKET_NAME)
export S3_ENDPOINT=$(terraform output -raw S3_ENDPOINT)
export S3_ACCESS_KEY=$(terraform output -raw S3_ACCESS_KEY)
export S3_SECRET_KEY=$(terraform output -raw S3_SECRET_KEY)
s3cmd sync ../documents/ s3://${S3_BUCKET}/ \
--host=${S3_ENDPOINT} \
--host-bucket=${S3_ENDPOINT} \
--access_key=${S3_ACCESS_KEY} \
--secret_key=${S3_SECRET_KEY}
(Go to high-resolution screencast)
When the App Platform endpoint is available, use kubectl and the generated kubeconfig to get App Platform credentials for accessing your Kubernetes cluster.
export KUBECONFIG=./kubeconfig.yaml
kubectl get secret platform-admin-initial-credentials \
-n keycloak \
--template={{.data.username}} \
| base64 -d
kubectl get secret platform-admin-initial-credentials \
-n keycloak \
--template={{.data.password}} \
| base64 -d
(Go to high-resolution screencast)
Sign in to Akamai App Platform using your credentials. You'll be prompted to create a new password.
(Go to high-resolution screencast)
Allow App Platform to create the necessary object storage buckets by providing your Linode API key and specifying a region for the buckets. For optimal performance, select the same region you used with Terraform to provision resources.
(Go to high-resolution screencast)
Install the Harbor container registry app in App Platform to store your container images.
(Go to high-resolution screencast)
Switch to the Team view in App Platform.
(Go to high-resolution screencast)
Generate a public/private key pair to serve as your GitHub deploy key, so that App Platform can access your repository securely. Important: Do not add a passphrase to your key.
ssh-keygen -t rsa -b 4096 -C "your.email@example.com" -f my-github-key
(Go to high-resolution screencast)
Add the public key to your GitHub repository's list of deploy keys in settings.
(Go to high-resolution screencast)
Add the private key as a Sealed Secret in App Platform.
(Go to high-resolution screencast)
Add a code repository in App Platform, connecting it to your GitHub repository using the Sealed Secret you created.
(Go to high-resolution screencast)
Build the container image using the Dockerfile in the repository.
(Go to high-resolution screencast)
Add the following Sealed Secrets in App Platform to securely store sensitive information.
OpenAI API key, used for making embeddings and chat completion API calls.
Create an API key at OpenAI. Copy it.
Create a Sealed Secret in App Platform to store it.
(Go to high-resolution screencast)
PostgreSQL database connection strings for both the vector database and conversation state database (found in your terraform outputs JSON file).
(Go to high-resolution screencast)
Linode Object Storage access key and secret key for accessing document storage (found in your terraform outputs JSON file).
(Go to high-resolution screencast)
Admin API key for authenticating admin endpoints like database initialization and document indexing.
Specify an API key value and store it directly as a Sealed Secret.
(Go to high-resolution screencast)
Add network policies to give outbound access to the two managed PostgreSQL databases from your application pods. Retrieve the database server URLs from the connections strings found in your terraform outputs JSON file.
(Go to high-resolution screencast)
Create a workload using the chart template in charts/workflow.example.yaml, configuring it with your container image repository URL and object storage configurations. Sensitive information references the Sealed Secrets you created.
(Go to high-resolution screencast)
Create a service to expose your application for public acces
(Go to high-resolution screencast)
Send a health check request with curl to verify the application is running and responding correctly.
curl http://<your-service-endpoint>/api/health
(Go to high-resolution screencast)
Send an admin request with curl to initialize databases, creating the necessary tables and extensions.
curl \
-X POST \
--header "x-api-key: <your-admin-api-key>" \
http://<your-service-endpoint>/api/admin/initialize_databases
(Go to high-resolution screencast)
Send an admin request with curl to index documents, which will process all documents in Object Storage and create vector embeddings.
curl \
-X POST \
--header "x-api-key: <your-admin-api-key>" \
http://<your-service-endpoint>/api/admin/index_documentsNote: This initiates a background job and then returns a job ID. Check the status with:
curl \
-X GET \
--header "x-api-key: <your-admin-api-key>" \
http://<your-service-endpoint>/api/admin/index_documents/<job-id>
(Go to high-resolution screencast)
Open your browser to the service endpoint to test the final chatbot application and interact with it through the web interface.
(Go to high-resolution screencast)
- FastAPI Application: Main web server handling HTTP requests
- RAG Pipeline: LangChain-based retrieval and generation system
- Vector Store: PostgreSQL with pgvector for semantic search
- Conversation Memory: LangGraph with PostgreSQL checkpointing
- Document Loader: Custom S3-compatible loader for PDF, HTML, and TXT files
- Admin API: Endpoints for database initialization and document indexing
- Chat API: Endpoints for conversational interactions
GET /api/health- Health check endpoint (optional?services=truefor detailed checks)POST /api/chat- Chat endpoint for user queriesPOST /api/admin/initialize_databases- Initialize database schemasPOST /api/admin/index_documents- Trigger background document indexingGET /api/admin/index_documents/{job_id}- Check indexing job statusGET /api/admin/list_documents- List documents in Object Storage
The application uses environment variables for configuration. Key variables include:
OPENAI_API_KEY- OpenAI API key for embeddings and chatVECTOR_DB_CONNECTION_STRING- PostgreSQL connection for vector storageCONVERSATION_DB_CONNECTION_STRING- PostgreSQL connection for conversation stateS3_ENDPOINT- Linode Object Storage endpointS3_BUCKET_NAME- Linode Object Storage bucket nameS3_ACCESS_KEY- Linode Object Storage access keyS3_SECRET_KEY- Linode Object Storage secret keyADMIN_API_KEY- Admin API key for authentication
Documents should be uploaded to Object Storage in the root of the bucket. A metadata.csv file can be included with the following columns:
file_name- Name of the fileairline- Airline namereference_url- Reference URL for the documentdocument_date- Document datedescription- Description of the document