A modern WPF desktop application for AI-powered conversations with advanced RAG, document analysis, and enterprise-grade security. Built with .NET 10, featuring offline-first design, local embedding models, and hybrid retrieval.
Features • Quick Start • Architecture • Documentation • Testing • Contributing
Screenshot: Chat interface with RAG debug panel showing retrieval metrics
- Real-time streaming responses from LLMs
- Multiple conversation management with history
- Markdown rendering support
- RAG Debug Panel with sources, scores, and latency metrics
- Hybrid Retrieval: Vector search + FTS5 keyword search with RRF fusion
- Import documents (.txt, .md, .json, .csv, .pdf, .docx)
- Configurable TopK, similarity threshold, retrieval mode
- Full pipeline transparency with Flight Recorder
The "black box" for your RAG pipeline - understand exactly why the model responded the way it did:
| Tab | What it shows |
|---|---|
| 📄 Sources | Selected chunks with Vec/KW/RRF scores and content preview |
| 📊 Candidates | All evaluated chunks (not just selected), with ranking and token counts |
| ⏱️ Timings | Visual breakdown: EmbedQuery, VectorSearch, KeywordSearch, Merge+Rerank |
Summary Cards show at a glance:
- Total pipeline time (ms)
- Selected/Total chunks ratio
- Vector matches count
- Keyword matches count
Formula: RRF(k=60) - Reciprocal Rank Fusion combining vector and keyword results
- Analyze documents and transcripts for insights
- Summary: TL;DR of content
- Detected Intents: Customer/user intentions with confidence scores
- Red Flags: Risk detection with severity levels
- Compliance Checklist: Automatic verification of required items
- Suggested Response: Draft professional replies
- Download and run embedding models locally (ONNX)
- Support for multilingual E5 models (Small/Base/Large/Instruct)
- No API costs for embeddings
- Privacy-first: your data stays on your machine
- Clean dark theme with accent colors
- Multi-language support: English, Polski (more coming)
- Status bar with offline/encryption/network indicators
- RAG Debug panel with professional metrics display
- AES-256-GCM encryption for data at rest
- DPAPI key protection tied to Windows user
- Offline mode indicator
- Network calls counter (transparency)
- Zero telemetry, zero data leakage
Architecture inspired by RAG frameworks like LlamaIndex, implemented natively in .NET for offline mode.
┌─────────────────────────────────────────────────────────────────┐
│ UI Layer (WPF) │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐ │
│ │ Chat │ │Knowledge│ │ Document │ │Embeddings│ │ Settings │ │
│ │ View │ │ Base │ │ Analysis │ │ View │ │ View │ │
│ └────┬────┘ └────┬────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │ │
│ ┌────┴───────────┴───────────┴────────────┴────────────┴────┐ │
│ │ ViewModels (MVVM) │ │
│ │ IAsyncEnumerable<string> for streaming responses │ │
│ │ Update UI via Dispatcher (only in UI layer) │ │
│ └────────────────────────────┬───────────────────────────────┘ │
└───────────────────────────────┼──────────────────────────────────┘
│
┌───────────────────────────────┼──────────────────────────────────┐
│ Application Layer │
│ ┌────────────────┐ ┌─────────────────┐ ┌──────────────────────┐ │
│ │ ChatOrchestrator│ │IngestionPipeline│ │ RagQueryEngine │ │
│ │ (ChatService) │ │ (Channel<T>) │ │ (Hybrid Retrieval) │ │
│ └────────────────┘ └─────────────────┘ └──────────────────────┘ │
│ ┌────────────────┐ ┌─────────────────┐ ┌──────────────────────┐ │
│ │DocumentAnalysis│ │ StatusService │ │ LocalizationService │ │
│ └────────────────┘ └─────────────────┘ └──────────────────────┘ │
└───────────────────────────────┬──────────────────────────────────┘
│
┌───────────────────────────────┼──────────────────────────────────┐
│ Core Interfaces │
│ IEmbedder │ IVectorIndex │ IRetriever │ ILLM │ IEncryptor │
└───────────────────────────────┬──────────────────────────────────┘
│
┌───────────────────────────────┼──────────────────────────────────┐
│ Infrastructure Layer │
│ ┌─────────────────┐ ┌─────────────────┐ ┌────────────────────┐ │
│ │ SQLite + FTS5 │ │ ONNX Runtime │ │ DPAPI + AES-GCM │ │
│ │ (vector + text) │ │ (CPU/DirectML) │ │ (encryption) │ │
│ └─────────────────┘ └─────────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
| Decision | Rationale |
|---|---|
| Hybrid Retrieval (FTS5 + Vectors) | Combines keyword precision with semantic understanding via RRF fusion |
| Channel<T> Ingestion Queue | Backpressure, cancellation, retry - enterprise-grade document processing |
| DPAPI + AES-256-GCM | Windows-native key protection, industry-standard encryption |
| Offline-First Design | Data never leaves device, zero external dependencies for core features |
| IAsyncEnumerable Streaming | Token-by-token response delivery without blocking UI |
| Technology | Purpose |
|---|---|
| .NET 10.0 | Runtime |
| WPF | UI Framework |
| CommunityToolkit.Mvvm | MVVM implementation |
| SQLite + FTS5 | Local database with full-text search |
| ONNX Runtime | Local model inference |
| AES-GCM + DPAPI | Enterprise encryption |
- Windows 10/11 (64-bit)
- .NET 10.0 SDK
- ~2GB disk space for embedding models (optional)
Option 1: Microsoft Store (Recommended)
Option 2: Build from Source
# Clone the repository
git clone https://github.com/DamianTarnowski/WPFLLM.git
cd WPFLLM
# Build and run
dotnet run- Configure API → Settings → Enter OpenAI/OpenRouter API key
- Start Chatting → Chat tab → Create conversation → Send message
- Enable RAG (optional) → Knowledge Base → Add documents → Generate embeddings
- Go Offline (optional) → Embeddings → Download local model
# Self-contained executable
dotnet publish -c Release -r win-x64 --self-contained -o ./publish
# Framework-dependent (smaller)
dotnet publish -c Release -r win-x64 -o ./publish%LOCALAPPDATA%\WPFLLM\
├── wpfllm.db # Encrypted database
└── models/ # Downloaded embedding models
├── multilingual-e5-small/
├── multilingual-e5-base/
└── multilingual-e5-large/
| Provider | Endpoint |
|---|---|
| OpenAI | https://api.openai.com/v1 |
| Azure OpenAI | https://{resource}.openai.azure.com/ |
| OpenRouter | https://openrouter.ai/api/v1 |
| Ollama | http://localhost:11434/v1 |
| LM Studio | http://localhost:1234/v1 |
| Model | Dimensions | Size | Quality | RAM |
|---|---|---|---|---|
| E5 Small | 384 | ~470MB | ★★★☆☆ | 1-2 GB |
| E5 Base | 768 | ~1.1GB | ★★★★☆ | 2-3 GB |
| E5 Large | 1024 | ~2.2GB | ★★★★★ | 4-6 GB |
All models support 100+ languages including Polish, English, German, French, and more.
| Document | Description |
|---|---|
| Architecture | System design, MVVM patterns, service layer |
| Embeddings | Local embedding models, Rust tokenizer, E5 setup |
| Store Publishing | Microsoft Store submission guide |
| Privacy Policy | Privacy policy for Store compliance |
| Contributing | How to contribute, code style, commit conventions |
| Changelog | Version history and release notes |
| Service | Responsibility |
|---|---|
LlmService |
OpenAI-compatible API, streaming, embeddings |
RagService |
Document chunking, hybrid retrieval (FTS5 + vectors) |
ChatService |
Conversation management, message history |
LocalEmbeddingService |
ONNX model inference, Rust tokenizer |
EncryptionService |
AES-256-GCM encryption, DPAPI key protection |
IngestionService |
Background document processing queue |
The project includes 317 tests with comprehensive coverage:
| Category | Tests | Description |
|---|---|---|
| Unit Tests | 184 | Services, models, utilities |
| Integration Tests | 120 | Database, RAG, chat workflows |
| Real API Tests | 13 | Live OpenRouter API validation |
# All tests (mocked, no API key needed)
dotnet test
# With verbose output
dotnet test --logger "console;verbosity=normal"
# Only real API tests
dotnet test --filter "TestCategory=RealApi"To run tests against the real OpenRouter API:
# Option 1: Environment variable
$env:OPENROUTER_API_KEY = "sk-or-v1-your-key-here"
dotnet test --filter "TestCategory=RealApi"
# Option 2: Create WPFLLM.Tests/.env file
echo "OPENROUTER_API_KEY=sk-or-v1-your-key-here" > WPFLLM.Tests/.env
dotnet test --filter "TestCategory=RealApi"Note: The
.envfile is gitignored. Tests are automatically skipped if no API key is found.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Damian Tarnowski
- GitHub: @DamianTarnowski
Made with ❤️ and .NET