No description
  • TypeScript 91.4%
  • HTML 7.7%
  • Nix 0.5%
  • Dockerfile 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-13 12:29:51 +02:00
src fix task scheduler 2026-09-13 12:29:51 +02:00
tests more tools 2026-09-13 12:15:24 +02:00
.env.example updates 2026-09-12 23:32:02 +02:00
.envrc init 2026-09-12 12:47:16 +00:00
.gitignore init 2026-09-12 12:47:16 +00:00
devenv.lock init 2026-09-12 12:47:16 +00:00
devenv.nix updates 2026-09-12 23:32:02 +02:00
devenv.yaml init 2026-09-12 12:47:16 +00:00
docker-compose.yml updates 2026-09-12 23:32:02 +02:00
Dockerfile updates 2026-09-12 23:32:02 +02:00
package.json fix pdf extraction 2026-09-13 12:27:15 +02:00
pnpm-lock.yaml fix pdf extraction 2026-09-13 12:27:15 +02:00
pnpm-workspace.yaml init 2026-09-12 12:47:16 +00:00
README.md more tools 2026-09-13 12:15:24 +02:00
tsconfig.json init 2026-09-12 12:47:16 +00:00

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) using gemma4:e4b with zero third-party API costs.
    • Cloud (OpenRouter): Switch to OpenRouter (LLM_PROVIDER=openrouter) to use models like google/gemini-2.5-flash or meta-llama/llama-3.3-70b-instruct with instant response times and function calling.
    • Native reasoning with optional thinking mode (GEMMA_THINKING_ENABLED).
  • 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-vec KNN with SQLite FTS5 BM25 and Reciprocal Rank Fusion (RRF).
  • 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.

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.