SERVER NOTE:
GPU not found.
Falling back to hope, a single vCPU and 4GB RAM.
Like good BBQ, LLM responses on the VPS can take time.
* Known cold-start issue: the first request can fail while the model
loads. Try once more. Fix in progress and notes below in 'journal'. *
Skills & Stack
Technical Skills
- Web & Backend Development
-
- Languages: Python, JavaScript, HTML5, CSS3
- Frameworks: Node.js, Express.js, Flask, FastAPI, Django
- REST API Design and Integration
- Server-Side Application Development
- Artificial Intellegence & Machine Learning
-
- Model Development & Evaluation
- Data Preprocessing & Feature Engineering
- PyTorch, TensorFlow, Scitkit-Learn, Pandas, Numpy
- Data Visualization: Matplotlib, Seaborn, Plotly
- LLM Applications & Retrieval Systems
-
- Retrieval-Augmented Generation (RAG) Architecture
- LangChain, LangGraph, Ollama
- Embedding Pipelines & Vector Storage
- LLM Integration & API Development
- Rule-Based & LLM Powered Systems
- Infrastructure & Deployment
-
- Linux (Ubuntu), NGINX, PM2, systemd
- Docker, Azure Container Apps, VPS Hosting
- Git, GitHub, CI/CD
- Database Intergration
- Server Configuration & Application Deployment
It's Me!
Applied Systems
onebadev.com - VPS Infrastructure & Deployment
The portfolio site itself is not hosted on a managed platform, it
runs on a self-configured Ubuntu VPS, handled end-to-end from
initial setup through production deployment. This includes
provisioning the server environment, configuring NGINX as a
reverse proxy to route traffic to a Node.js backend (Python in
development), and managing the application processes with PM2 to
ensure uptime and automatic restarts on failure.
SSL/TLS termination is handled at the NGINX layer via Let's
Encrypt, keeping the backend service unexposed to the public
internet. Static assets are served directly through NGINX while
API traffic is proxied to the appropriate internal port.
The server also runs UFW-based firewall rules with only necessary
ports exposed, and auth.log monitoring as an ongoing exercise in
understanding what a live public-facing server actually looks like
under real traffic conditions.
- OS & Hosting: Ubuntu VPS, self-managed
- Web Server: NGINX - reverse proxy, static asset serving, SSL termination
- Process Management: PM2 - process persistence, auto-restart, log management
- Security: UFW firewall, Let's Encrypt (Certbot)
- Backend: Node.js + Express proxied via NGINX
BadBot: Production RAG Chatbot (onebadev.com)
Originally developed as a rule-based Python chatbot for a Natural
Language Processing course, this assistant began as a structured
Q&A system built to recognize predefined prompts and return custom
responses. While the early version relied on pattern matching and
scripted logic, the broader goal became a bit more ambitious:
evolve the chatbot into a system capable of intelligently
answering questions about my background, projects, and technical
experience.
To support that idea, the project was rewritten in JavaScript to
align with my website's backend architecture. This transition
established the foundation for integrating large language models
and retrieval-based techniques, with the long-term objective of
building a Retrieval-Augmented Generation (RAG) system. The intent
is for the chatbot to move beyond fixed responses and instead
dynamically retrieve relevant information about my work,
education, and portfolio, enabling a more natural, accurate, and
context-aware interactions. At its core, the project represents a
shift from static question-answer logic toward an intelligent,
searchable knowledge assistant built around my personal technical
ecosystem.
- Backend:Node.js + Express.js
- LLM:Ollama (Gemma model)
- Ingestion:DirectoryLoader (PDFLoader + TextLoader)
- Chunking / Retrieval:RecursiveCharacterTextSplitter + Top-k retrieval
- Embeddings:OllamaEmbeddings
- Vector Store:FAISS vector store, with on-disk persistence
Journal | Notes:
- The site itself has been up and running (and will continue to be), but after deploying BadBot to my VPS I have encountered a performance bottleneck. While responses were fast on my personal PC, the minimal, CPU only server (no GPU) has been struggling under the load. The model, Gemma3:1b, is too heavy for the available hardware, pushing the CPU to max out causing response times to rise. To hopefully solve this, I am currently downsizing the LLM to a leaner Gemma3:270M and reimplementing a lightweight, rule-based system to handle common questions quicker. In this hybrid setup, the AI model is only invoked for more complex queries, helping balance model capability with hardware constraints, keeping the site fast and responsive. Barring any issues with the updated model, (or anything else) upcoming improvements include lightweight in-session memory to further improve flow while maintaining hardware efficiency.
- It has been a while but after continuing to work through the limitations of CPU-bound performance on the VPS, the approach has recently shifted towards cloud-based models. The current model is still Gemma3 but has been upgraded to 27b-cloud, trying to ease the hardware bottleneck that had been limiting response quality and speed. The local model experiments, showed that lighter models had a tendency to hallucinate more frequently while heavier ones pushed the vCPU to its limits. Additional improvements include a server-side response cache to help reduce redundant calls for repeated questions and refined document chunking with natural text boundary separators for cleaner retrieval.
-
Currently exploring model quantization as another approach
to running LLMs within the limited CPU and memory resources
of the VPS. Rather than only reducing model size by moving
to models with fewer parameters, quantization reduces the
numerical precision used to represent a models's weights,
such as converting higher-precision weights to 8-bit or
4-bit representations.
The goal is to better understand the tradeoff between model size, memory usage, inference speed, and response quality. For BadBot, this could potentially allow a more capable model to run locally without the same resource requirements as its higher-precision version. I'm currently experimenting with different quantzation levels and learning how formats such as GGUF and Ollama's model ecosystem fit into that process.