'Complete Guide: Building a Personalized AI Learning System with Local LLMs, [post] deterministic
A comprehensive technical guide to building a self-hosted AI learning

[Github Link](https://github.com/kliewerdaniel/learn)
Building a Personalized AI Learning System with Local LLMs
Table of Contents - [1. Introduction](#1-introduction) - [2. System Architecture](#2-system-architecture) - [3. Tech Stack & Tools](#3-tech-stack--tools) - [4. Step-by-Step Implementation](#4-step-by-step-implementation) - [5. Optimization & Expansion](#5-optimization--expansion) - [6. Deployment & Hosting](#6-deployment--hosting) - [7. Next Steps](#7-next-steps)
1. Introduction
Why Build a Personalized AI Learning System?
Traditional e-learning platforms often rely on static content that doesn't adapt to individual learners. This guide presents a **fully AI-driven personalized learning system** that generates **entirely new lessons** for each interaction, making every session unique and context-aware.
The system dynamically adjusts content using **a knowledge graph and a local LLM**, ensuring learners receive increasingly relevant and challenging material based on their progress. This adaptive approach maximizes engagement and retention in ways traditional courses cannot.
Key Features
✅ **Self-Hosted & Private:** Everything runs locally without reliance on cloud APIs ✅ **Dynamic Lesson Generation:** Each lesson is uniquely tailored to the user's progress ✅ **Knowledge Graph-Driven:** Lessons structured on connected concept maps, not linear modules ✅ **Retrieval-Augmented Generation (RAG):** AI enhances lessons with relevant context ✅ **Scalable & Modular:** Built with modern tech for flexibility and growth
2. System Architecture
The system uses a modular three-layer architecture:
Frontend – Next.js + React
This provides the interface where users engage with AI-generated lessons:
- **User Dashboard:** Displays progress, completed lessons, and recommendations
- **Lesson UI:** Renders AI-generated content in an engaging format
- **Interactive Exercises:** Supports quizzes and challenges with real-time AI feedback
- **Progress Visualization:** Shows topic mastery through knowledge graph visualizations
- **AI Chat:** Provides on-demand explanations for concepts
Backend – FastAPI
Manages user data, lesson requests, and AI interactions:
- **Content Processing:** Handles markdown files and processes them for the AI
- **Progress Tracking:** Stores learning history to adapt future lessons
- **Knowledge Graph Management:** Maintains concept relationships
- **API Endpoints:** Connects frontend and AI layer
AI Layer – Local LLM + Knowledge Graph
The brain of the system:
- **Knowledge Graph:** Maps concepts and their relationships
- **RAG Implementation:** Enhances lesson quality with relevant context
- **Adaptive Generation:** Creates lessons based on user progress
- **Local Execution:** All AI runs on your hardware for privacy and control
Data Flow
1. User requests a lesson from the frontend 2. Backend queries knowledge graph and past progress 3. AI layer generates a personalized, non-repetitive lesson 4. Frontend displays the lesson with interactive elements 5. User interactions update the knowledge graph and progress data
3. Tech Stack & Tools
Frontend
- **Next.js (React):** For a responsive, server-rendered interface
- **TailwindCSS:** For utility-first styling
- **ShadCN UI:** For pre-built, customizable components
- **React-Flow:** For visualizing knowledge graphs
Backend
- **FastAPI:** Python-based API with async support
- **SQLAlchemy:** ORM for database interactions
- **Pydantic:** For data validation
Databases
- **PostgreSQL:** Stores structured data (user progress, lesson history)
- **ChromaDB:** Vector database for semantic search
AI Components
- **Ollama:** Framework for running local LLMs
- **Mistral or Llama 3:** High-quality open-source LLM
- **NetworkX:** Python library for knowledge graph implementation
- **Sentence-Transformers:** For generating text embeddings
4. Step-by-Step Implementation
Step 1: Environment Setup
First, let's set up our project structure and install dependencies:
```bash # Create project directory mkdir ai-learning-system cd ai-learning-system
Create subdirectories mkdir -p frontend backend ```
#### Backend Setup:
```bash cd backend
Create virtual environment python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
Install dependencies pip install fastapi uvicorn pydantic sqlalchemy psycopg2-binary chromadb sentence-transformers networkx python-multipart
Create basic directory structure mkdir -p app/api app/db app/models app/services ```
#### Frontend Setup:
```bash cd ../frontend
Initialize Next.js project npx create-next-app@latest . --typescript --tailwind --eslint --app
Install additional dependencies npm install react-flow-renderer react-markdown react-dropzone ```
Step 2: Database Setup
#### PostgreSQL Setup
Let's create our database models for user progress and lesson history:
```python # backend/app/models/database.py from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Boolean, Float from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship import datetime
Base = declarative_base()
class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String, unique=True, index=True) email = Column(String, unique=True, index=True) hashed_password = Column(String) created_at = Column(DateTime, default=datetime.datetime.utcnow) progress = relationship("UserProgress", back_populates="user") class Concept(Base): __tablename__ = "concepts" id = Column(Integer, primary_key=True, index=True) name = Column(String, unique=True, index=True) description = Column(Text) difficulty = Column(Integer) # 1-10 scale prerequisites = relationship( "ConceptRelationship", primaryjoin="Concept.id==ConceptRelationship.target_id", back_populates="target" ) followups = relationship( "ConceptRelationship", primaryjoin="Concept.id==ConceptRelationship.source_id", back_populates="source" )
class ConceptRelationship(Base): __tablename__ = "concept_relationships" id = Column(Integer, primary_key=True, index=True) source_id = Column(Integer, ForeignKey("concepts.id")) target_id = Column(Integer, ForeignKey("concepts.id")) relationship_type = Column(String) # e.g., "prerequisite", "related" strength = Column(Float) # 0-1 representing relationship strength source = relationship("Concept", foreign_keys=[source_id], back_populates="followups") target = relationship("Concept", foreign_keys=[target_id], back_populates="prerequisites")
class UserProgress(Base): __tablename__ = "user_progress" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id")) concept_id = Column(Integer, ForeignKey("concepts.id")) mastery_level = Column(Float) # 0-1 scale last_studied = Column(DateTime, default=datetime.datetime.utcnow) user = relationship("User", back_populates="progress") concept = relationship("Concept")
class Lesson(Base): __tablename__ = "lessons" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id")) concept_id = Column(Integer, ForeignKey("concepts.id")) content = Column(Text) generated_at = Column(DateTime, default=datetime.datetime.utcnow) exercises = relationship("Exercise", back_populates="lesson") class Exercise(Base): __tablename__ = "exercises" id = Column(Integer, primary_key=True, index=True) lesson_id = Column(Integer, ForeignKey("lessons.id")) question = Column(Text) answer = Column(Text) lesson = relationship("Lesson", back_populates="exercises") ```