No cloud services. No API subscriptions. No data leaves your machine.
The only recurring cost is electricity.
Use case: Deploy a local private chatbot that answers questions using documents stored in your local vector database. All documents remain within your network and are never sent to or hosted by third-party services. If the retrieved information is insufficient to answer a question, the chatbot responds with "I don't know."
Some random ideas for future exploration:
- Training the model to have a "persona" so that no system instruction is needeed
- Training the model on the documentation directly
- 100% local inference using
llama.cpp - 100% local document indexing and retrieval
- No OpenAI, Anthropic, Google, or other API dependencies
- OpenAI-compatible local endpoint
- Simple document upload workflow
- Works offline after initial setup
- Supports custom GGUF models
- Designed for small businesses, homelabs, and privacy-focused users
Both clients (WPF and React Web UI) communicate exclusively with the FastAPI Backend Server (on port 8000). The backend server handles document loading, indexing, vector searching, and queries the local LLM running via llama-server (on port 8080).
graph TB
%% Clients
subgraph Clients [Clients]
WPF[WPF Client App: WPFAIChat]
WebUI[React/Vite Frontend Web App]
end
%% Application Backend
subgraph AppServer [Application Server]
FastAPI[FastAPI Backend Server]
DocProc[Document Processor]
Embeds[Embeddings Manager]
VecStore[Vector Store Client]
LLMConn[LLM Connector]
end
%% Database & Monitoring Stack
subgraph DBStack ["Data & Monitoring Services (Docker)"]
Qdrant[(Qdrant Vector DB)]
Prometheus[Prometheus Metrics]
Grafana[Grafana Dashboards]
end
%% Inference Engine
subgraph LocalLLMSub [Inference Engine]
LlamaServer[llama-server / llama.cpp]
GGUF[(Local GGUF Model)]
end
%% Connections
WebUI <-->|HTTP / SSE Stream| FastAPI
WPF <-->|HTTP / SSE Stream| FastAPI
FastAPI --> DocProc
FastAPI --> Embeds
FastAPI --> VecStore
FastAPI --> LLMConn
VecStore <-->|Dense/Sparse Queries| Qdrant
LLMConn <-->|OpenAI-Compatible API| LlamaServer
LlamaServer <-->|Local Inference| GGUF
%% Monitoring connections
Qdrant -.->|Export Metrics| Prometheus
Prometheus -.->|Pull Metrics| Grafana
Note
There is no direct connection/network path between the Clients and the Inference Engine. All traffic, prompt context compilation, and Server-Sent Events (SSE) streaming flow through the FastAPI backend server to ensure safety and orchestration.
When a user uploads a document, the system splits, embeds, and indexes it into the local database:
flowchart TD
%% Source
Doc([Raw Document: PDF/DOCX/TXT/MD]) --> Upload[API Endpoint: /api/documents/upload]
%% Processing
Upload --> DocLoader[LangChain Document Loaders]
DocLoader --> Chunking[RecursiveCharacterTextSplitter]
%% Embedding
Chunking --> ChunkText[Document Chunks]
subgraph VectorGeneration [Vector Generation]
ChunkText --> DenseGen[Dense Embedding: Hugging Face]
ChunkText --> SparseGen[Sparse Embedding: FastEmbed SPLADE]
end
%% Database Storage
DenseGen -->|Dense Vector| QdrantPush[Qdrant Collection]
SparseGen -->|Sparse Vector| QdrantPush
- Loaders: Converts PDF, DOCX, TXT, and Markdown files into raw text chunks.
- Splitters: Recursively splits chunks with overlaps to maintain passage coherence.
- Hybrid Embeddings: Generates both a Dense Vector (for semantic concept search) and a Sparse Vector (for exact keyword/lexical search) and writes them to the local Qdrant collection.
When a user submits a query, the system retrieves context, reranks the best matches, compiles a prompt, and streams the answer from the local LLM:
flowchart TD
%% User input
Query([User Query]) --> APIQuery[API Endpoint: /api/chat]
%% Vector generation for search
APIQuery --> DenseEmbed[Generate Dense Query Embeddings]
APIQuery --> SparseEmbed[Generate Sparse Query Embeddings]
%% Vector Database Hybrid Search
subgraph Retrieval [Vector Retrieval]
DenseEmbed --> QdrantSearch[(Qdrant DB)]
SparseEmbed --> QdrantSearch
QdrantSearch -->|Hybrid Retrieve| Candidates[Top 12 Candidates]
end
%% Reranking & Compression
Candidates --> Reranker[FlashRank Cross-Encoder Reranker]
Reranker -->|Re-scored & Sorted| TopK[Top 4 Reranked Context Chunks]
%% Generation
TopK --> PromptBuilder[Prompt Template Assembly]
Query --> PromptBuilder
PromptBuilder -->|Context + Query| LlamaInference[llama-server]
LlamaInference -->|Stream SSE Tokens| UserResponse[User Interface Response]
- Hybrid Search: Dense & sparse retrieval are executed against the Qdrant DB. 12 candidates are retrieved.
- FlashRank Cross-Encoder: Reranks base candidates based on exact semantic relevance to the query, filtering it down to the top 4 chunks.
- Context Generation: Assembles the prompt context and sends it to the local
llama-server. The response is streamed token-by-token using SSE (Server-Sent Events) back to the UI.
No internet connection is required after setup.
This project uses llama.cpp as the inference engine.
Using a dedicated Conda environment helps isolate dependencies and keeps your local LLM setup organized.
Install one of the following:
- Anaconda
- Miniconda (recommended)
Verify Conda is installed:
conda --versionExample output:
conda 25.x.x
Create a new environment:
conda create -n LocalLLM python=3.11 -yActivate it:
conda activate LocalLLMVerify the environment:
conda info --envsThe active environment will be marked with *.
llama.cpp is distributed through Conda-Forge.
Add the repository:
conda config --add channels conda-forgeEnable strict channel priority:
conda config --set channel_priority strictThis helps prevent dependency conflicts.
Install the package:
conda install llama.cppConda will automatically install all required dependencies.
Verify the installation completed successfully:
llama-server --helpor
llama-cli --helpYou should see a list of available command-line options.
You can also verify the package directly:
conda list llama.cppDepending on the installed version, the Conda package may include:
| Tool | Purpose |
|---|---|
llama-server |
OpenAI-compatible API server |
llama-cli |
Command-line inference |
llama-quantize |
Model quantization |
llama-bench |
Performance benchmarking |
llama-perplexity |
Perplexity testing |
llama-batched |
Batch inference examples |
Download a GGUF model from a model repository.
Recommended starter models:
- Phi-4 Mini Instruct
- Qwen 3
- Gemma 3
- Llama 3.2
Create a model directory:
C:\LLMModels\
~/LLMModels/
Place your downloaded .gguf files in this directory.
Example:
llama-server \
-m "/path/to/model.gguf" \
-c 8192 \
--host 0.0.0.0 \
--port 8080| Parameter | Description |
|---|---|
-m |
Path to the GGUF model |
-c |
Context window size |
--host |
Network interface to bind to |
--port |
API server port |
After startup, the API will be available locally:
http://localhost:8080
There's a web UI that's similar to chatgpt at http://localhost:8080/
The endpoint is compatible with:
- C#
- Python
- JavaScript
- LangChain
- LlamaIndex
- Open WebUI
- Custom RAG applications
The LocalLLM folder contains two scripts.
Run this once to install Conda, create the LocalLLM environment, and install llama.cpp:
cd LocalLLM
.\install.ps1This script will:
- Verify that Conda is available in your PATH.
- Create (or reuse) the
LocalLLMConda environment with Python 3.11. - Add the
conda-forgechannel and installllama.cpp. - Verify the installation by running
llama-server --version.
After installing, edit the model path inside the script, then run it:
.\startLocalLLM.ps1This script:
- Activates the
LocalLLMConda environment. - Starts
llama-serverwith sensible defaults (8192 context, full GPU offload). - Exposes an OpenAI-compatible API on
http://localhost:8080.
Before running: Download a GGUF model. We recommend starting with Microsoft's Phi-4 Mini Instruct (Q8_0):
Save the downloaded file to
C:\LLMModels\and update the-mpath instartLocalLLM.ps1.
- llama.cpp setup
- Local API endpoint
- Automatic document ingestion (using LangChain loaders)
- Hybrid Chunking pipeline (Recursive Character Splitting)
- Local embedding generation (Dense + FastEmbed Sparse)
- Vector storage (Qdrant)
- Semantic & Lexical Hybrid search (Dense + Sparse/BM25)
- Contextual Reranking (FlashRank Cross-Encoder)
- Web UI
- Drag-and-drop document uploads
- Chat history
- Source citations with score ratings
- A test benchmark evaluation suite for the RAG pipeline and local models - kinda
- Multi-user support - The end goal is switching from llama-cpp to using either SGLang or vLLM. However, these two frameworks doesn't support AMD GPU on Windows so can't mess around with it yet.
- Authentication
- Docker deployment - kinda
- Monitoring - Prometheus + Grafana
A fully local, premium-designed RAG (Retrieval-Augmented Generation) dashboard with Qdrant, FastAPI, and React/Vite is available in the LocalRAG folder.
- Install all dependencies:
Run the automated PowerShell installer:
cd LocalRAG .\install.ps1
- Start the local LLM:
Launch
llama-serverwith embedding support enabled (e.g., using.\startLocalLLM.ps1in theLocalLLMfolder). - Launch the RAG subsystem & database:
Run the startup orchestrator. This will automatically check and start the Docker Compose stack (Qdrant, Prometheus, and Grafana), launch the backend, and open the React dashboard:
.\start_rag.ps1
For detailed guides, component diagrams, and RAG tuning options, please check the LocalRAG README.
A native Windows desktop chat and configuration client built in C# / WPF (.NET 9) is available in the WPFAIChat folder.
- Ensure the LocalRAG backend server is running (
.\start_rag.ps1inLocalRAG/). - Run the desktop application from the CLI:
cd WPFAIChat dotnet run
For advanced features and code structure, see the WPFAIChat README.
Ensure Conda is installed and available in your system PATH.
Update Conda:
conda update -n base -c defaults condaThen retry the installation.
Verify:
conda activate LocalLLMCheck:
- NVIDIA drivers are installed
- CUDA-compatible build is available
- Your model launch configuration includes GPU offloading settings
The goal of hoboLocalLLM is to make local AI accessible to anyone.
The intended user experience is simple:
- Start the model.
- Upload documents.
- Ask questions.
- Receive answers.
No cloud infrastructure. No API keys. No subscriptions. No vendor lock-in.
Just a local AI assistant that runs entirely on your own hardware.
