RAG-powered serverless API that answers questions about me and my work. It uses a lightweight in-memory vector store loaded from precomputed embeddings and Google Gemini for both embeddings and generation.
Just like Sabrina sings about wanting something real β this API delivers context-rich answers about my portfolio instead of the same old chatbot nonsense. π΅
- π€ RAG answers: Retrieves relevant snippets from contact details/profile/project documents
- π§ Gemini models:
text-embedding-004for search, configurable chat model for generation - π Simple API:
POST /api/chat-ragwith optional conversation history - βοΈ Serverless ready: Vercel functions with permissive CORS headers
- π Vector similarity search: Cosine similarity-based document retrieval
- π‘οΈ Health monitoring: Built-in health check endpoints
- Runtime: Node.js 18+ (ES Modules)
- Framework: Express (for local dev), Vercel Functions (deployment)
- AI/ML:
@google/generative-ai - Vector Store: Custom in-memory implementation with Gemini embeddings
- Deployment: Vercel
- Database: File-based embeddings storage
Before running this project, make sure you have:
- Node.js 18+ (recommended)
- A Google Gemini API key
- Create
.env.localin the project root with:GEMINI_API_KEY=your_api_key_here # optional, defaults to gemini-2.0-flash-lite GEMINI_MODEL=gemini-2.0-flash-lite
# Clone the repository
git clone https://github.com/jgchoti/jgchoti-api.git
cd jgchoti-api
# Install dependencies
npm installTwo options available:
npm run dev
# -> http://localhost:3000The dev server logs available endpoints on start.
http://localhost:3000/api
Health check and basic info.
curl -s http://localhost:3000/api/health | jqResponse:
{
"status": "healthy",
"message": "Choti's Portfolio API is running!",
"endpoints": {
"chat": "/api/chat-rag",
"health": "/api/health"
},
"timestamp": "2025-09-08T17:44:01.845Z"
}Root API info and usage documentation.
curl -s http://localhost:3000/api/Response:
{
"message": "Welcome to Choti's Portfolio API! π€",
"description": "RAG-powered chatbot API for portfolio inquiries",
"endpoints": {
"chat": "/api/chat-rag - POST - Chat with Choti's AI agent",
"health": "/api/health - GET - Health check"
},
"usage": {
"method": "POST",
"url": "/api/chat-rag",
"body": {
"message": "Your question here",
"conversationHistory": "Optional previous messages"
}
},
"portfolio": "https://jgchoti.github.io",
"github": "https://github.com/jgchoti"
}Chat with the RAG agent about Choti. Returns model text and debug metadata.
Example Request:
curl -s -X POST https://jgchoti-api.vercel.app/api/chat-rag \
-H 'Content-Type: application/json' \
-d '{
"message": "Summarize Choti'\''s international experience.",
"conversationHistory": []
}'Response Structure:
{
"response": "Choti has a truly global perspective, having lived and worked in nine countries, including Thailand, Switzerland, and the UK. This international experience gives her a unique edge in cross-cultural collaboration and understanding global markets. You can see how she applies this in her data projects here: https://jgchoti.github.io/data. What kind of role are you looking to fill?",
"metadata": {
"model": "gemini-2.0-flash-lite",
"ragEnabled": true,
"vectorUsed": true,
"vectorDebugInfo": {
"resultsUsed": 3,
"topSimilarity": 0.6907635643942781,
"types": ["profile", "contact", "profile"],
"similarities": [
0.6907635643942781, 0.6208553455982836, 0.5978628425932092
]
},
"contextLength": 3803,
"timestamp": "2025-09-08T17:48:34.895Z"
}
}Notes:
conversationHistoryis optional; items should be{ type: 'user' | 'assistant', content: string }- If embeddings are missing or the vector store is not ready, the endpoint falls back to a small default context
The vector store (lib/HybridVectorStore.js) loads from data/embeddings-gemini.json and uses cosine similarity to retrieve relevant snippets. Query embeddings are computed on-the-fly using Gemini text-embedding-004, so GEMINI_API_KEY is required both to generate embeddings and to serve queries.
The system automatically enriches portfolio data through:
- GitHub API integration (
scripts/generate-github.js) that discovers and analyzes repositories and content extraction from README files and repository metadata - Career path relevance scoring for data engineering, data science, ML engineering, and backend development roles
npm run generate-embeddingsThis script builds content from:
data/profileData.jsdata/projectData.jsdata/contactInfo.jsdata/github_portfolio_data.json
Creates embeddings with Gemini and writes:
data/embeddings-gemini.jsondata/embeddings-gemini-metadata.json
Create a .env.local file in the project root:
# Required: Google Gemini API key
GEMINI_API_KEY=your_api_key_here
# Optional: Gemini model for generation (defaults to gemini-2.0-flash-lite)
GEMINI_MODEL=gemini-2.0-flash-liteFor Vercel deployment: Set these in the project's Environment Variables dashboard.
jgchoti-api/
βββ api/ # Serverless endpoints for Vercel
β βββ chat-rag.js # Main RAG chat endpoint (POST)
β βββ health.js # Health check (GET)
β βββ index.js # Root API info (GET)
βββ data/ # Data and generated embeddings
β βββ profileData.js # Profile information
β βββ projectData.js # Project data
β βββ contactInfo.js # Contact information
β βββ embeddings-gemini.json # Generated embeddings
β βββ embeddings-gemini-metadata.json # Embedding metadata
βββ lib/
β βββ HybridVectorStore.js # In-memory vector store using Gemini embeddings
βββ scripts/
β βββ generate-embeddings.js # Builds embeddings from profile/projects
βββ dev-server.js # Local Express server that proxies to handlers
βββ vercel.json # Vercel config (headers, rewrites, function settings)
βββ package.json # Scripts and dependencies
βββ .env.local # Environment variables (create this)
βββ README.md
-
Login and link project:
vercel login vercel link
-
Set environment variables:
vercel env add GEMINI_API_KEY vercel env add GEMINI_MODEL # optional -
Deploy:
npm run deploy # or vercel --prod
- Connect your GitHub repository to Vercel
- Set environment variables in the dashboard
- Deploy automatically on git push
401/Authentication Error
- Ensure
GEMINI_API_KEYis set correctly in.env.local(local) and Vercel dashboard (production) - Verify your Gemini API key is valid and has proper permissions
Vector Store Not Ready
- Run
npm run generate-embeddingsto createdata/embeddings-gemini.json - Ensure all required data files exist in the
data/directory
Port Already in Use
- Change the port in
dev-server.jsor kill the process using port 3000 - Check for other running Node.js processes
Missing Dependencies
- Run
npm installto ensure all dependencies are installed - Check Node.js version (18+ required)
Chat with the deployed bot at: https://jgchoti.github.io/
Professional AI that actually understands context and delivers responses that make sense β no generic chatbot nonsense here. β¨
