Skip to content

Latest commit

Β 

History

History
551 lines (379 loc) Β· 15.3 KB

File metadata and controls

551 lines (379 loc) Β· 15.3 KB

AI-Thinking Simulator

A Next.js application that provides an interactive learning experience through AI-generated content with real-time streaming, fill-in-the-blank exercises, and contextual Q&A support.

🎯 Overview

This project creates an interactive learning experience where AI explanations are streamed character-by-character, with periodic fill-in-the-blank questions and contextual chat support. Students can ask questions about any part of the explanation through expandable accordions.

The current implementation focuses on coding explanations (specifically a Python function example), but the system is designed to be flexible for various educational content.

✨ Features

  • Real-time Text Streaming: AI explanations appear with a typewriter effect.
  • Interactive Blanks: Students fill in missing information during explanations.
  • Contextual Q&A: Chat system that understands the current explanation context.
  • Clean Architecture: Core streaming logic is separated into a reusable React hook (useTextStreamer).
  • Component-Based UI: The interface is broken down into modular, maintainable components.
  • User Authentication: Secure login system with session management.
  • Responsive Design: Clean, dark-themed interface optimized for learning.

πŸš€ Quick Start

Prerequisites

  • Node.js 18+
  • pnpm (recommended) or npm
  • PostgreSQL database
  • DeepSeek API key

Setup Instructions

  1. Install dependencies:

    pnpm install
  2. Configure environment variables: Create a .env.local file in the root directory:

    DEEPSEEK_API_KEY=your_deepseek_api_key_here
    DATABASE_URL=postgresql://username:password@localhost:5432/database_name
  3. Database Setup: Use a local or cloud-based PostgreSQL instance (e.g., Supabase, Neon). Update the DATABASE_URL with your connection string.

  4. Initialize Database: Generate and apply the database schema.

    npx drizzle-kit generate
    npx drizzle-kit push
  5. Start development server:

    pnpm dev
  6. Access the application:

πŸ“ Project Structure

The project follows a clean, feature-oriented structure.

Key Directories

  • app/: Contains all routes and API endpoints.
    • app/streaming/page.tsx: The main page component for the learning interface.
    • app/api/: Server-side logic for AI generation, authentication, and data access.
  • components/: Reusable React components.
    • components/streaming/: Components specific to the streaming interface.
  • hooks/: Custom React hooks for shared logic.
    • hooks/useTextStreamer.ts: The core hook managing the text streaming animation and state.
  • lib/: Shared utilities, like database connection and helpers.
  • drizzle/: Database migration files generated by Drizzle ORM.

Component Structure

components/ └── streaming/ # Streaming-specific components β”œβ”€β”€ ModernBlankInput.tsx # Fill-in-the-blank UI β”œβ”€β”€ ChatAccordion.tsx # Q&A chat interface β”œβ”€β”€ ModernAIOutputDisplay.tsx # Final AI answer display └── PerformanceSummary.tsx # Student progress tracking

πŸ”§ Key Implementation Details

Core Logic: The useTextStreamer Hook

All the complex, low-level logic for text streaming is encapsulated in the hooks/useTextStreamer.ts custom hook. This keeps the main page component clean and focused on high-level state management.

The hook is responsible for:

  • Processing the source text and detecting BLANK(...) and paragraph breaks.
  • Managing timers for the character-by-character "typing" animation.
  • Signaling to the parent component when user interaction (feedback or a blank input) is required.
  • Providing simple functions (injectIntoStream, completeParagraph, resetStream) for the parent to control the stream's flow.

Main Page: app/streaming/page.tsx

This file serves as the main controller for the learning experience. It uses the useTextStreamer hook and is responsible for:

  • Fetching question data from the API.
  • Managing high-level application state (current question, completed content, etc.).
  • Handling user events (e.g., submitting an answer, asking a question in the chat).
  • Rendering the appropriate UI components based on the state from the hook and the application.

API Integration

The app/api/generate/route.ts file handles all communication with the DeepSeek API for context-aware chat responses.

Content Format

AI explanations use BLANK(answer) placeholders for interactive elements:

The function should return BLANK(-1) if the value is not found. The difference between the max and min keys is BLANK(6).

Animation Configuration

Key timing constants are defined in hooks/useTextStreamer.ts:

const TYPING_INTERVAL_MS = 20;      // Time between typing intervals
const CHARS_PER_TYPE_INTERVAL = 3; // Characters rendered per interval

πŸ—„οΈ Database

The project uses Drizzle ORM to interact with a PostgreSQL database.

Schema: schema.ts - Defines the users, questions, and logs tables.

Database Client: lib/db.ts - Manages the database connection.

Migrations: Stored in the drizzle/ directory.

Available Commands

# Generate a new migration file based on schema changes
pnpm db:generate

# Push schema changes directly to the database (for development)
pnpm db:push

# Run all pending migrations
pnpm db:migrate

# Open Drizzle Studio to view and manage your data
pnpm db:studio

πŸš€ Deployment

Environment Variables for Production

Ensure these variables are set in your deployment environment:

DEEPSEEK_API_KEY=your_production_api_key
DATABASE_URL=your_production_database_url
NEXTAUTH_SECRET=your_secure_random_string # Generate with `openssl rand -base64 32`
NODE_ENV=production

πŸ” Development Notes

Adding New Questions

Insert a new row into the questions table in your database:

INSERT INTO questions (question, content) VALUES (
  'Your question title',
  'Your explanation content with BLANK(answer) placeholders...'
);

The new question will automatically be available in the application.

Customizing The Experience

To change the streaming speed, adjust the constants in hooks/useTextStreamer.ts.

To modify the UI, edit the components in components/streaming/.

To add new interactions, extend the useTextStreamer hook and the StreamingPage component.


Note: This project was developed by Avval Halani. Please feel free to contact me with any questions.

πŸš€ Quick Start

Prerequisites

  • Node.js 18+
  • pnpm (recommended) or npm
  • PostgreSQL database
  • DeepSeek API key

Setup Instructions

  1. Install dependencies:

    pnpm install
  2. Configure environment variables: Create .env.local in the root directory:

    DEEPSEEK_API_KEY=your_deepseek_api_key_here
    DATABASE_URL=postgresql://username:password@localhost:5432/database_name
  3. Database Setup:

    Option A: Local PostgreSQL Setup

    Install PostgreSQL locally and create a database:

    # Update DATABASE_URL in .env.local
    DATABASE_URL=postgresql://username:password@localhost:5432/streaming_app

    Option B: Cloud Database (Recommended)

    Use a cloud provider like:

    • Supabase (free tier available)
    • Neon (serverless postgres)

    Example with Supabase:

    1. Create account at supabase.com
    2. Create new project
    3. Copy connection string from Settings > Database
    4. Update .env.local:
    DATABASE_URL=postgresql://postgres:[password]@[host].supabase.co:5432/postgres
  4. Initialize Database:

    # Generate and run migrations
    npx drizzle-kit generate
    npx drizzle-kit push
    
    # Or use the migration command
    pnpm db:migrate
  5. Seed Database (Optional):

    Add sample questions to your database:

    # You can manually insert data or create a seed script
    # Example questions are provided in the schema comments
  6. Start development server:

    pnpm dev
  7. Access the application:

First-Time Setup Checklist

When setting up the project on a new machine:

  • Install PostgreSQL or setup cloud database
  • Create .env.local with correct DATABASE_URL
  • Run pnpm install to install dependencies
  • Run pnpm db:reset to create database tables
  • Create your first user account through the application
  • Add questions to the database
  • Start development with pnpm dev

πŸ—„οΈ Database Schema

The application uses the following database tables:

Users Table

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE,
  password TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT now()
);

Questions Table

CREATE TABLE questions (
  id SERIAL PRIMARY KEY,
  question TEXT NOT NULL,
  content TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT now()
);

Logs Table

CREATE TABLE logs (
  id SERIAL PRIMARY KEY,
  user_id TEXT,
  action TEXT NOT NULL,
  details JSONB DEFAULT '{}'::jsonb,
  level TEXT NOT NULL,
  timestamp TIMESTAMP WITH TIME ZONE DEFAULT now()
);

Sample Data

Example question entry:

INSERT INTO questions (question, content) VALUES (
  'Explain the identical function',
  'Let me walk you through this step by step...\n\nThe `identical` function takes two parameters: a dictionary `d` and a value `val`...'
);

πŸ”§ Database Management

Drizzle ORM Configuration

The project uses Drizzle ORM with the following configuration:

  • Schema: schema.ts - Database schema definitions
  • Database client: lib/db.ts - Database connection
  • Migrations: drizzle/ - Auto-generated migration files

Available Commands

# Generate new migration
pnpm db:generate

# Push schema changes to database
pnpm db:push

# Run migrations
pnpm db:migrate

# View database in Drizzle Studio
pnpm db:studio

# Reset database (drops all data and recreates tables)
pnpm db:reset

Database Reset

The reset command completely wipes your database and recreates all tables with the proper schema:

# Reset database - WARNING: This deletes ALL data
pnpm db:reset

What the reset does:

  • βœ… Drops all existing tables (users, questions, logs)
  • βœ… Recreates empty tables with proper schema
  • βœ… Creates necessary indexes for performance
  • ❌ Does NOT insert sample data - you start with clean, empty tables

When to use reset:

  • Setting up the project for the first time
  • Switching to a new database
  • During development when you need to start fresh
  • After major schema changes

⚠️ Warning: This command will delete ALL data in your database. Make sure you have backups of any important data before running it.

Switching Databases

To use a different database:

  1. Update environment variables:

    DATABASE_URL=postgresql://new_username:new_password@new_host:5432/new_database
  2. Run migrations:

    npx drizzle-kit push
  3. Seed with sample data (if needed)

πŸ“ Key File Locations

Core Application Files

Component Structure

components/
β”œβ”€β”€ streaming/          # Streaming-specific components
β”‚   β”œβ”€β”€ BlankInput      # Fill-in-the-blank interactions
β”‚   β”œβ”€β”€ ChatAccordion   # Q&A chat interface
β”‚   β”œβ”€β”€ ParagraphFeedback # Feedback collection
β”‚   β”œβ”€β”€ PerformanceSummary # Student progress tracking
β”‚   └── TextRenderer   # Markdown text display
└── ui/                # Reusable UI components (shadcn/ui)
    └── accordion.tsx  # Base accordion component

πŸ”§ Key Implementation Details

Main Logic Location

All core functionality is in app/streaming/page.tsx:

  • Text streaming with typewriter effect
  • Blank detection and handling (BLANK(answer) format)
  • Chat accordion management
  • Performance tracking
  • User authentication checks
  • Activity logging

API Integration

The app/api/generate/route.ts file handles:

  • DeepSeek API integration
  • Context-aware chat responses
  • User authentication verification
  • Request/response logging
  • Error handling and fallbacks

Authentication System

Logging System

The application logs all user interactions:

  • User actions: Question navigation, feedback, responses
  • AI interactions: Requests, responses, errors
  • Authentication: Login attempts, successes, failures
  • Performance: Response times, error rates

Content Format

AI explanations use BLANK(answer) placeholders for interactive elements:

The function should return BLANK(-1) if val is not found...
The difference between max and min keys is BLANK(6)...

Animation Configuration

Key timing constants in app/streaming/page.tsx:

const TYPING_INTERVAL_MS = 100; // Speed between typing intervals
const CHARS_PER_TYPE_INTERVAL = 30; // Characters per interval
const ANIMATION_CHARS_PER_SECOND = 30; // Animation speed
const FEEDBACK_DURATION_MS = 1500; // Feedback display time

πŸš€ Deployment

Environment Variables for Production

DEEPSEEK_API_KEY=your_production_api_key
DATABASE_URL=your_production_database_url
NEXTAUTH_SECRET=your_secure_random_string
NODE_ENV=production

πŸ” Development Notes

Adding New Questions

  1. Insert into database:

    INSERT INTO questions (question, content) VALUES (
      'Your question title',
      'Your explanation content with BLANK(answer) placeholders...'
    );
  2. Questions automatically appear in the application

Customizing Logging

Modify lib/logger.ts to:

  • Add new log levels
  • Change log format
  • Add custom fields
  • Integrate with external services

Performance Monitoring

Check the logs table for:

  • User engagement metrics
  • AI response performance
  • Error patterns
  • Feature usage statistics

Note: This project was developed by Avval Halani. Please feel free to contact me for any questions.