๐ Live Demo: https://randomtask2000.github.io/WebLLMChat/
A privacy-first AI assistant with powerful document analysis capabilities that runs entirely in your browser, built with SvelteKit, Skeleton UI and WebLLM. Features include RAG (Retrieval-Augmented Generation) capabilities, multiple theme support, and persistent chat history.
^0.2.75
- WebLLM library for running LLMs in browser^11.11.1
- Syntax highlighting for code blocks^1.9.1
- DOCX to HTML conversion^3.11.174
- PDF text extraction and rendering^1.7.2
- Floating UI positioning engine^7.4.2
- Cross-platform native runtime^7.4.2
- Capacitor command-line interface^7.4.2
- iOS platform support^5.1.9
- Reactive UI framework^2.8.0
- Full-stack framework^3.0.5
- Static site adapter^4.0.0
- Vite plugin for Svelte^5.4.8
- Fast build tool and dev server^2.10.2
- Svelte UI toolkit^0.4.0
- Tailwind plugin for Skeleton^3.4.14
- Utility-first CSS framework^0.5.9
- Form styling plugin^0.5.15
- Typography plugin^1.29.0
- Syntax highlighting library^1.9.0
- Additional Prism themes^8.4.47
- CSS post-processor^10.4.20
- CSS vendor prefixing^2.1.3
- Unit testing framework^2.1.3
- Vitest UI interface^1.48.0
- End-to-end testing^25.0.1
- DOM implementation for testing^5.6.3
- TypeScript compiler^4.0.4
- Svelte type checker^9.14.0
- JavaScript linter^8.13.0
- TypeScript ESLint plugin^8.13.0
- TypeScript ESLint parser^2.44.1
- Svelte ESLint plugin^9.1.0
- Prettier ESLint config^3.3.3
- Code formatter^3.2.7
- Svelte Prettier plugin^2.8.1
- TypeScript runtime helpers^22.9.0
- Node.js type definitions^1.26.4
- Prism.js type definitions^9.12.4
- Highlight.js type definitions#Install dependencies
npm install
#Start development server
npm run dev
#Run tests
npm run test
#Run integration tests
npm run test:integration
#Type checking
npm run check
#Build for production
npm run build
#Preview production build
npm run preview
src/
โโโ lib/
โ โโโ components/ # Svelte components
โ โ โโโ ChatInterface.svelte
โ โ โโโ ChatMessage.svelte
โ โ โโโ DocumentManager.svelte
โ โ โโโ DragDropZone.svelte
โ โ โโโ FeatureToggle.svelte
โ โ โโโ FileUpload.svelte
โ โ โโโ MobileLayout.svelte
โ โ โโโ ModelDropdown.svelte
โ โ โโโ ModelManager.svelte
โ โ โโโ RAGContext.svelte
โ โ โโโ Sidebar.svelte
โ โ โโโ ThemeSwitcher.svelte
โ โ โโโ WelcomeGuide.svelte
โ โโโ config/ # Configuration files
โ โ โโโ features.ts
โ โโโ services/ # Service layer
โ โ โโโ embedding-service.ts
โ โ โโโ rag-service.ts
โ โ โโโ vector-store.ts
โ โโโ stores/ # Svelte stores for state management
โ โ โโโ chat.ts
โ โ โโโ documents.ts
โ โ โโโ models.ts
โ โ โโโ theme.ts
โ โโโ types/ # TypeScript type definitions
โ โ โโโ index.ts
โ โ โโโ rag.ts
โ โโโ utils/ # Utility functions
โ โโโ document-processor.ts
โ โโโ mobile.ts
โ โโโ model-loading.ts
โ โโโ timeFormat.ts
โ โโโ tokenCount.ts
โ โโโ webllm.ts
โโโ routes/ # SvelteKit routes
โ โโโ +layout.svelte
โ โโโ +layout.ts
โ โโโ +page.svelte
โโโ app.css # Global styles
โโโ app.html # Main HTML template
tests/
โโโ unit/ # Unit tests
โ โโโ document-processor-advanced.test.ts
โ โโโ document-processor.test.ts
โ โโโ stores.test.ts
โโโ integration/ # Playwright integration tests
โโโ chat-flow.test.ts
static/ # Static assets
โโโ _headers
โโโ favicon.ico
โโโ manifest.json
The app includes a powerful client-side RAG system that enhances AI responses with your uploaded documents.
Upload Documents:
Ask Questions: The AI will automatically search your documents and use relevant content to answer
View RAG Context: Click the RAG Context button (right sidebar) to see:
Access settings in the RAG Context panel:
Use the /find
command to search for exact sentences:
/find tree
/find [term]
/find any term
Or use natural language:
For more detailed RAG usage instructions, see RAG_USAGE_GUIDE.md
Requires a modern browser with WebGPU support:
The application follows a client-side architecture where all processing happens in the browser:
graph TB
User([User]) --> UI[Chat Interface]
UI --> ChatStore[Chat Store]
UI --> DocStore[Document Store]
UI --> ModelStore[Model Store]
subgraph "Frontend Layer"
UI
ChatStore
DocStore
ModelStore
ThemeStore[Theme Store]
end
subgraph "Service Layer"
ModelManager[Model Manager]
RAGService[RAG Service]
EmbeddingService[Embedding Service]
VectorStore[Vector Store]
DocProcessor[Document Processor]
end
subgraph "WebLLM Engine"
WebLLMCore[WebLLM Core]
WebGPU[WebGPU Runtime]
ModelCache[Model Cache]
end
subgraph "Storage Layer"
IndexedDB[(IndexedDB)]
LocalStorage[(Local Storage)]
BrowserCache[(Browser Cache)]
end
subgraph "Document Processing"
PDFParser[PDF.js Parser]
DOCXParser[Mammoth.js Parser]
TextParser[Text Parser]
MDParser[Markdown Parser]
end
ChatStore --> ModelManager
DocStore --> RAGService
ModelStore --> ModelManager
ModelManager --> WebLLMCore
RAGService --> EmbeddingService
RAGService --> VectorStore
RAGService --> DocProcessor
DocProcessor --> PDFParser
DocProcessor --> DOCXParser
DocProcessor --> TextParser
DocProcessor --> MDParser
WebLLMCore --> WebGPU
WebLLMCore --> ModelCache
ModelManager --> IndexedDB
VectorStore --> IndexedDB
RAGService --> IndexedDB
ChatStore --> LocalStorage
ThemeStore --> LocalStorage
ModelCache --> BrowserCache
style User fill:#e1f5fe
style WebGPU fill:#fff3e0
style IndexedDB fill:#f3e5f5
style LocalStorage fill:#f3e5f5
style BrowserCache fill:#f3e5f5
classDiagram
class ChatInterface {
-messages: ChatMessage[]
-inputText: string
-isLoading: boolean
+sendMessage(text: string): void
+clearChat(): void
+handleFileUpload(files: File[]): void
}
class ModelManager {
-currentModel: string
-availableModels: ModelInfo[]
-loadingProgress: number
+loadModel(modelId: string): Promise~void~
+switchModel(modelId: string): void
+getModelInfo(): ModelInfo
}
class RAGService {
-vectorStore: VectorStore
-embeddingService: EmbeddingService
+addDocument(doc: Document): Promise~void~
+search(query: string): Promise~SearchResult[]~
+updateSettings(settings: RAGSettings): void
}
class VectorStore {
-embeddings: Map~string, Vector~
-documents: Map~string, DocumentChunk~
+addEmbedding(id: string, vector: Vector): void
+findSimilar(query: Vector, k: number): SearchResult[]
+clear(): void
}
class EmbeddingService {
-model: EmbeddingModel
+generateEmbedding(text: string): Promise~Vector~
+batchEmbed(texts: string[]): Promise~Vector[]~
}
class DocumentProcessor {
+processFile(file: File): Promise~ProcessedDocument~
+extractText(buffer: ArrayBuffer, type: string): Promise~string~
+chunkDocument(text: string, options: ChunkOptions): DocumentChunk[]
}
class WebLLMCore {
-engine: MLCEngine
-config: EngineConfig
+initializeEngine(): Promise~void~
+chat(messages: Message[]): Promise~string~
+streamChat(messages: Message[]): AsyncGenerator~string~
}
class ChatStore {
-sessions: ChatSession[]
-currentSession: ChatSession
+addMessage(message: ChatMessage): void
+createSession(): ChatSession
+loadSession(id: string): void
+saveToLocalStorage(): void
}
class DocumentStore {
-documents: Document[]
-chunks: DocumentChunk[]
+addDocument(doc: Document): void
+removeDocument(id: string): void
+getChunksByDocument(docId: string): DocumentChunk[]
}
class ThemeStore {
-currentTheme: string
-availableThemes: Theme[]
+setTheme(theme: string): void
+getTheme(): Theme
}
ChatInterface --> ChatStore : uses
ChatInterface --> ModelManager : uses
ChatInterface --> RAGService : uses
ChatInterface --> DocumentProcessor : uses file upload
ModelManager --> WebLLMCore : manages
RAGService --> VectorStore : stores vectors
RAGService --> EmbeddingService : generates embeddings
RAGService --> DocumentStore : retrieves documents
DocumentProcessor --> DocumentStore : stores processed docs
ChatStore --> WebLLMCore : sends messages
VectorStore --> IndexedDB : persists data
DocumentStore --> IndexedDB : persists data
ChatStore --> LocalStorage : persists sessions
ThemeStore --> LocalStorage : persists theme
class IndexedDB {
<<external>>
+put(store: string, data: any): Promise~void~
+get(store: string, key: string): Promise~any~
+delete(store: string, key: string): Promise~void~
}
class LocalStorage {
<<external>>
+setItem(key: string, value: string): void
+getItem(key: string): string
+removeItem(key: string): void
}
sequenceDiagram
participant User
participant ChatInterface
participant ChatStore
participant ModelManager
participant WebLLMCore
participant WebGPU
participant BrowserCache
User->>ChatInterface: Types message and sends
ChatInterface->>ChatStore: addMessage(userMessage)
ChatStore->>ChatStore: Save to LocalStorage
ChatInterface->>ModelManager: checkModelLoaded()
alt Model not loaded
ModelManager->>WebLLMCore: initializeEngine()
WebLLMCore->>BrowserCache: Check for cached model
alt Model cached
BrowserCache-->>WebLLMCore: Return cached model
else Model not cached
WebLLMCore->>WebLLMCore: Download model from CDN
WebLLMCore->>BrowserCache: Cache model
end
WebLLMCore->>WebGPU: Load model to GPU
WebGPU-->>WebLLMCore: Model ready
WebLLMCore-->>ModelManager: Engine initialized
end
ChatInterface->>ChatStore: getConversationHistory()
ChatStore-->>ChatInterface: Return messages[]
ChatInterface->>ModelManager: generateResponse(messages)
ModelManager->>WebLLMCore: streamChat(messages)
WebLLMCore->>WebGPU: Process tokens
loop Streaming response
WebGPU-->>WebLLMCore: Generated tokens
WebLLMCore-->>ModelManager: Token stream
ModelManager-->>ChatInterface: Update response
ChatInterface->>ChatInterface: Display streaming text
end
ChatInterface->>ChatStore: addMessage(aiResponse)
ChatStore->>ChatStore: Save to LocalStorage
ChatInterface-->>User: Display complete response
sequenceDiagram
participant User
participant ChatInterface
participant DocumentProcessor
participant RAGService
participant EmbeddingService
participant VectorStore
participant DocumentStore
participant IndexedDB
Note over User,ChatInterface: Document Upload Flow
User->>ChatInterface: Uploads document
ChatInterface->>DocumentProcessor: processFile(file)
alt PDF Document
DocumentProcessor->>DocumentProcessor: PDF.js extraction
else DOCX Document
DocumentProcessor->>DocumentProcessor: Mammoth.js conversion
else Text/Markdown
DocumentProcessor->>DocumentProcessor: Direct text processing
end
DocumentProcessor->>DocumentProcessor: chunkDocument(text, options)
DocumentProcessor->>DocumentStore: addDocument(processedDoc)
DocumentStore->>IndexedDB: persistDocument()
DocumentProcessor->>RAGService: indexDocument(chunks)
loop For each chunk
RAGService->>EmbeddingService: generateEmbedding(chunkText)
EmbeddingService->>EmbeddingService: TF-IDF calculation
EmbeddingService-->>RAGService: Return vector
RAGService->>VectorStore: addEmbedding(chunkId, vector)
end
VectorStore->>IndexedDB: persistEmbeddings()
RAGService-->>ChatInterface: Document indexed
ChatInterface-->>User: Show upload success
Note over User,ChatInterface: Query with RAG Flow
User->>ChatInterface: Sends question
ChatInterface->>RAGService: search(userQuery)
RAGService->>EmbeddingService: generateEmbedding(query)
EmbeddingService-->>RAGService: Query vector
RAGService->>VectorStore: findSimilar(queryVector, k)
VectorStore->>VectorStore: Calculate cosine similarity
VectorStore-->>RAGService: Top k chunks
RAGService->>DocumentStore: getChunkDetails(chunkIds)
DocumentStore->>IndexedDB: fetchChunks()
IndexedDB-->>DocumentStore: Chunk data
DocumentStore-->>RAGService: Enriched chunks
RAGService->>RAGService: Format context
RAGService-->>ChatInterface: SearchResults + Context
ChatInterface->>ChatInterface: Augment prompt with context
ChatInterface->>ModelManager: generateResponse(augmentedPrompt)
Note right of ModelManager: Continue with LLM flow
ChatInterface-->>User: Display response with sources
To customize the app name and branding for your own deployment, you'll need to update several configuration files:
src/app.config.json
(Line 2) - Main app title source
{
"title": "Your App Name",
"description": "Your app description"
}
Mobile App Configuration - capacitor.config.ts
(Line 5)
appName: 'Your App Name',
Progressive Web App Manifest - static/manifest.json
(Lines 2-3)
{
"name": "Your App Name",
"short_name": "Your App Name",
"description": "Your app description"
}
Package Configuration - package.json
(Line 2)
"name": "your-app-name"
src/app.config.json
configuration automatically updates most UI references through the {appConfig.title}
systemMIT License - feel free to use this project as a starting point for your own applications.