Skip to content

tylerking/ai-chatbot

Repository files navigation

RAG Chatbot Backend

FastAPI service that powers an AI chatbot using RAG (Retrieval-Augmented Generation) to answer questions based on content from a CMS.

Tech Stack

  • FastAPI: REST API framework
  • OpenAI: Embeddings (text-embedding-3-small) & Chat (gpt-4o-mini)
  • Supabase: PostgreSQL database with pgvector for vector similarity search
  • Sanity CMS: Headless CMS for content management
  • Python Requests: HTTP client for fetching content from Sanity API

Setup

1. Install Dependencies

python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -r requirements.txt

2. Configure Environment

Create a .env file in the root directory with the following variables:

# OpenAI
OPENAI_API_KEY=your_openai_api_key

# Supabase
SUPABASE_URL=your_supabase_url
SUPABASE_KEY=your_supabase_anon_key

# Sanity CMS
SANITY_PROJECT_ID=your_sanity_project_id
SANITY_DATASET=production

# API Configuration
ALLOWED_ORIGINS=http://localhost:5173,https://yourdomain.com
RATE_LIMIT_PER_MINUTE=10

# Model Configuration
EMBEDDING_MODEL=text-embedding-3-small
CHAT_MODEL=gpt-4o-mini
TEMPERATURE=0.7
MAX_TOKENS=500

3. Set Up Supabase Database

Run this SQL in your Supabase SQL editor:

-- Enable pgvector extension
create extension if not exists vector;

-- Create documents table
create table documents (
  id bigserial primary key,
  title text not null,
  content text not null,
  source text not null,
  metadata jsonb,
  embedding vector(1536),
  created_at timestamp with time zone default now()
);

-- Create vector similarity search function
create or replace function match_documents (
  query_embedding vector(1536),
  match_threshold float,
  match_count int
)
returns table (
  id bigint,
  title text,
  content text,
  source text,
  metadata jsonb,
  similarity float
)
language sql stable
as $$
  select
    documents.id,
    documents.title,
    documents.content,
    documents.source,
    documents.metadata,
    1 - (documents.embedding <=> query_embedding) as similarity
  from documents
  where 1 - (documents.embedding <=> query_embedding) > match_threshold
  order by similarity desc
  limit match_count;
$$;

-- Create index for faster vector search
create index on documents using ivfflat (embedding vector_cosine_ops)
with (lists = 100);

4. Sync Content

Sync content from Sanity CMS to Supabase:

python sync_sanity.py

This will:

  • Fetch content from Sanity
  • Generate embeddings
  • Store in Supabase

Run this script whenever you update content in Sanity.

5. Run Development Server

uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

API will be available at: http://localhost:8000

API Endpoints

POST /qa

Ask a question based on your content.

Request:

{
  "question": "What projects are available?"
}

Response:

{
  "answer": "Based on the content, here are the projects...",
  "sources": [
    {
      "title": "Project Name",
      "source": "projects"
    }
  ]
}

GET /health

Health check endpoint.

GET /

Service info.

Rate Limiting

Default: 10 requests per minute per IP address.

Configure in .env:

RATE_LIMIT_PER_MINUTE=10

Content Management

Content is managed in Sanity CMS and synced to Supabase.

To sync updated content:

source venv/bin/activate
python sync_sanity.py

This will:

  1. Clear existing documents from Supabase
  2. Fetch fresh content from Sanity
  3. Convert Portable Text to plain text
  4. Generate embeddings
  5. Store in Supabase with metadata

Deployment

Deploy to any Python hosting platform:

  • Railway
  • Render
  • Fly.io
  • AWS Lambda (with Mangum adapter)
  • Google Cloud Run

Make sure to set environment variables in your deployment platform.

About

FastAPI service that powers an AI chatbot using RAG

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published