- TypeScript 91.4%
- HTML 7.7%
- Nix 0.5%
- Dockerfile 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| src | ||
| tests | ||
| .env.example | ||
| .envrc | ||
| .gitignore | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
Exmatrikodil
AI College Study Companion Bot with Multi-Tier Memory & Campus Integrations (DHBW Karlsruhe)
Exmatrikodil is an intelligent study companion designed for university students. It runs seamlessly either 100% locally (via Ollama running Google Gemma 4 E4B and local embeddings) or connected to Cloud AI via OpenRouter (e.g. Google Gemini 2.5 Flash, Claude 3.5 Haiku, Llama 3.3). It combines a multi-tier cognitive memory architecture (Working Memory, Vector Store via sqlite-vec, and an Entity Knowledge Graph), an on-demand File Sub-Agent for deep document digestion, a DuckDuckGo Web Search Subagent, a secure URL Reader Tool, and real-time campus tooling (DHBW Rapla schedules, free room finder, Mensa menus, Nextcloud study notes). It interfaces directly with students through Discord and Signal.
Key Features
Hybrid AI & Sub-Agent Architecture
- Flexible LLM Provider (Local Ollama vs. OpenRouter Cloud):
- Local: 100% local execution via Ollama (
http://localhost:11434/v1) usinggemma4:e4bwith zero third-party API costs. - Cloud (OpenRouter): Switch to OpenRouter (
LLM_PROVIDER=openrouter) to use models likegoogle/gemini-2.5-flashormeta-llama/llama-3.3-70b-instructwith instant response times and function calling. - Native reasoning with optional thinking mode (
GEMMA_THINKING_ENABLED).
- Local: 100% local execution via Ollama (
- Local File Sub-Agent (
FileSubAgent):- Leverages 128K context window capacity.
- Ingests large Nextcloud lecture scripts, syllabi, past exams, or downloaded web pages directly on-device.
- Performs targeted extraction of definitions, formulas, and rules without overloading conversational context.
- Local Vector & Hybrid Retrieval:
- Embeddings generated locally (e.g.,
nomic-embed-text, 768 dimensions) with zero external network requests. - Dual-tier hybrid search combining
sqlite-vecKNN with SQLite FTS5 BM25 and Reciprocal Rank Fusion (RRF).
- Embeddings generated locally (e.g.,
- Automated Memory Decay & Consolidation:
- Ebbinghaus forgetting curve retention scoring and automated pruning.
- Background consolidation of repetitive facts into consolidated student profiles.
- Cross-Conversation Graph Visualizer:
- Built-in web dashboard (
http://localhost:3888) with interactive physics force-directed graph to inspect entities, relations, and memory decay.
- Built-in web dashboard (
Live Campus & Web Tooling
- Timetable & Lecture Schedule (
get_timetable): Direct iCal/ICS parsing for DHBW Rapla calendars with recurrence expansion and elective filtering. - Free Room Finder (
find_free_rooms): Scrapes real-time occupancy across DHBW campus buildings with smart room deduplication and availability time windows. - Mensa Meal Planner (
get_mensa_menu): Live cafeteria menus with dietary notes, prices, allergens, and additives. - Nextcloud Resource Finder & Reader (
search_lecture_notes): Browses and deeply extracts text from shared lecture notes and slides via the File Sub-Agent. - DuckDuckGo Web Search Subagent (
web_search): Zero-API-key search engine querying DuckDuckGo HTML, filtering snippets, and synthesizing cited web results. - URL Reading Tool (
read_url_content): Secure scraper with SSRF protection against private/internal IPs, HTML cleaning, and automated summarization via FileSubAgent for large pages. - Discord-Optimized Brevity: Built-in guardrails and prompt engineering keeping replies strictly concise, bulleted, and under Discord message boundaries.
Architecture Overview
┌──────────────────────────┐
│ Discord / Signal Bot │
└─────────────┬────────────┘
│
▼
┌──────────────────────────┐
│ Agent Orchestrator │
│ (Gemma 4 / Cloud Models) │
└───────┬───────────┬──────┘
│ │
┌─────────────────────┴──┐ ┌──┴─────────────────────────┐
│ Local Memory Engine │ │ Campus & Web Tools │
├────────────────────────┤ ├────────────────────────────┤
│ • Local Embeddings │ │ • DHBW Rapla Timetable │
│ • sqlite-vec + BM25 │ │ • Campus Free Rooms │
│ • Knowledge Graph │ │ • Mensa Menus │
│ • Background Extractor │ │ • Nextcloud + Sub-Agent │
└───────────┬────────────┘ │ • DuckDuckGo Web Search │
│ │ • URL Reader + SSRF Guard │
▼ └────────────────────────────┘
┌────────────────────────┐
│ SQLite (`sqlite-vec`) │
└────────────────────────┘
Getting Started
Local Development with Devenv
# Enter the devenv shell:
devenv shell
# Install dependencies:
pnpm install
# Start local background services (launches Ollama if using local mode):
devenv up -d
# Pull Gemma 4 and embedding models for local mode:
pull-models
# Start development bot with tsx watch:
pnpm dev
Quick Start with Docker Compose
Run the entire local stack with one command:
docker compose up -d
This starts Ollama, pulls gemma4:e4b and nomic-embed-text, and launches the bot and visualizer dashboard on http://localhost:3888.
Configuration (.env)
Copy .env.example to .env and configure your preferences:
| Variable | Description | Default / Example |
|---|---|---|
LLM_PROVIDER |
AI provider: 'local' (Ollama/vLLM/LM Studio), 'openrouter', 'openai', or 'custom' |
local |
LLM_BASE_URL |
Base endpoint URL for OpenAI-compatible LLM service | http://localhost:11434/v1 |
LLM_MODEL |
LLM model identifier (e.g. gemma4:e4b, google/gemini-2.5-flash, gpt-4o-mini) |
gemma4:e4b |
LLM_API_KEY |
API key required for cloud providers (OpenRouter, OpenAI) | (Optional) |
LLM_ENABLE_THINKING |
Enable thinking / reasoning extraction across models (<think>, `< |
thought |
EMBEDDING_MODEL |
Embedding model identifier | nomic-embed-text |
EMBEDDING_DIMENSIONS |
Embedding vector dimension for sqlite-vec |
768 |
DATABASE_PATH |
Path to local SQLite database file | ./data/exmatrikodil.db |
ENABLE_VISUALIZER |
Enable Knowledge Graph Visualizer web dashboard | true |
VISUALIZER_PORT |
HTTP port for the Visualizer dashboard | 3888 |
DISCORD_BOT_TOKEN |
Discord Bot Token from Discord Developer Portal | (Optional) |
DISCORD_CLIENT_ID |
Discord Application Client ID | (Optional) |
SIGNAL_PHONE_NUMBER |
Bot's phone number registered in signal-cli |
(Optional) |
SIGNAL_CLI_REST_API_URL |
Base URL of signal-cli-rest-api daemon |
http://localhost:8080 |
DHBW_CAMPUS |
Campus abbreviation for Mensa & tools | KA (Karlsruhe) |
RAPLA_ICAL_URL |
Public or secret iCal/ICS URL for your Rapla course | (Optional) |
NEXTCLOUD_URL |
WebDAV URL of your Nextcloud instance | (Optional) |
NEXTCLOUD_USERNAME |
WebDAV username / App password | (Optional) |
NEXTCLOUD_PASSWORD |
WebDAV password / token | (Optional) |
NEXTCLOUD_FOLDER |
Root folder path to search notes in | /DHBW_Share |
Usage & Scripts
Run commands directly or inside devenv shell:
# Start in development mode with live reload (tsx)
pnpm dev
# Build TypeScript to dist/
pnpm build
# Run production build
pnpm start
# Run all automated tests (Vitest)
pnpm test
# Run tests in watch mode
pnpm test:watch
Testing
Unit and integration tests are managed with Vitest under tests/:
tests/memory.test.ts: Working memory, vector store, and knowledge graph persistence.tests/orchestrator.test.ts: Agent reasoning loop, tool invocation, and mock extraction flows.tests/local-ai.test.ts: Local LLM message preparation, thinking tag sanitization, and embedding generation.tests/web-tools.test.ts: SSRF protection, HTML cleaner, DuckDuckGo search parser, and URL reader.tests/visualizer.test.ts: Visualizer HTTP endpoints (/,/api/graph,/api/memories,/api/consolidate).tests/tools.test.ts: Mensa menu parsing, Rapla calendar recurrence calculations, free room deduplication, and Nextcloud WebDAV XML parsing.
Run all tests:
devenv shell -- pnpm test
Project Structure
Exmatrikodil/
├── src/
│ ├── agent/ # Agent reasoning and LLM services
│ │ ├── embeddings.ts # Local nomic-embed-text embedding client
│ │ ├── file-subagent.ts # Targeted document extraction subagent
│ │ ├── local-llm.ts # Unified LLM client (Ollama & OpenRouter support)
│ │ ├── orchestrator.ts # Main tool loop, memory retrieval & orchestration
│ │ └── prompt.ts # System prompt, brevity guidelines & extraction schemas
│ ├── bot/ # Platform bot adapters
│ │ ├── discord/ # Discord.js client implementation
│ │ └── signal/ # Signal-cli REST API polling client
│ ├── memory/ # Multi-tier memory engine
│ │ ├── db.ts # SQLite connection & sqlite-vec loader
│ │ ├── extractor-worker.ts# Async background entity & fact extractor
│ │ ├── graph-store.ts # Entity-relation knowledge graph
│ │ ├── schema.ts # Relational, graph & vector schema definitions
│ │ ├── vector-store.ts # sqlite-vec vector similarity + FTS5 BM25 search
│ │ ├── working-memory.ts # Rolling session message store
│ │ └── consolidator.ts # Memory decay & profile consolidation
│ ├── tools/ # Tool registry, campus & web implementations
│ │ ├── campus/
│ │ │ ├── free-rooms.ts # DHBW room occupancy parser & deduplicator
│ │ │ ├── mensa.ts # DHBW cafeteria menu client
│ │ │ ├── nextcloud.ts # Nextcloud WebDAV lecture notes search
│ │ │ └── timetable.ts # Rapla iCal calendar parser & filter
│ │ ├── web/
│ │ │ ├── search-subagent.ts # DuckDuckGo HTML parser & search subagent
│ │ │ ├── search-tool.ts # web_search tool definition
│ │ │ └── url-reader.ts # read_url_content tool with SSRF guards
│ │ ├── registry.ts # Generic ToolDefinition and schema registry
│ │ └── index.ts # Tool registry factory
│ ├── visualizer/ # Knowledge graph web dashboard
│ │ ├── server.ts # Embedded HTTP server & APIs
│ │ └── index.html # Physics force-directed visualizer UI
│ ├── config.ts # Zod-validated environment config
│ └── index.ts # Application entrypoint
├── tests/ # Vitest test suites
├── data/ # Local SQLite database directory
├── devenv.nix # Devenv development environment configuration
├── package.json
└── tsconfig.json
Roadmap
Campus & LMS Integration
- Moodle Course & Resource Sync (
get_moodle_courses,get_moodle_assignments): Fetch lecture slides, course announcements, and homework deadlines directly from DHBW Moodle.
License
This project is licensed under the MIT License.