Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# AI-Tutor
AI-Tutor for Seattle DataAI Project


## Contributors

[@ahumblefool](https://github.com/ahumblefool)
[@utopianvision](https://github.com/utopianvision)
[@MeghaN28](https://github.com/MeghaN28)
[@Neharor](https://github.com/Neharor)
96 changes: 82 additions & 14 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@
from flask_cors import CORS
import os
from dotenv import load_dotenv
from services import tutor_session_service # Import the tutor session service module
from services import quiz_service # Import the quiz service module
from services import tutor_session_service # AI Tutoring
from services import quiz_service # Quiz System
from services import student_card_service # Student Card Service
import google.generativeai as genai

# Load API key from .env file
load_dotenv()
import google.generativeai as genai
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))

# Initialize Flask app
app = Flask(__name__)
CORS(app) # Allow frontend access

# Routes for Tutor Session
# === AI Model for Answer Validation ===
AI_VALIDATOR = genai.GenerativeModel('gemini-1.5-flash')

# In-memory storage for Peer Learning (Replace with a database in production)
peer_questions = []

# === Tutor Session Routes ===
@app.route("/upload", methods=["POST"])
def upload():
return tutor_session_service.upload_file(request)
Expand All @@ -31,46 +38,107 @@ def stream():
def index():
return jsonify({"message": "Tutoring system is running"})

# Routes for Quiz
# === Student Card Routes ===
@app.route("/student/<student_id>", methods=["GET"])
def get_student(student_id):
return student_card_service.get_student(student_id)

@app.route("/student/<student_id>/feedback", methods=["POST"])
def add_feedback(student_id):
return student_card_service.add_feedback(student_id, request)

@app.route("/student/<student_id>/progress", methods=["GET"])
def get_student_progress():
return student_card_service.get_progress(request)

@app.route("/api/student-insights", methods=["POST"])
def student_insights():
return student_card_service.get_student_insights(request)

# === Quiz Routes ===
@app.route("/quiz/subjects", methods=["GET"])
def get_subjects():
"""Returns a list of available quiz subjects."""
return quiz_service.get_subjects()

@app.route("/quiz", methods=["GET"])
def generate_quiz():
"""Generates 5 quiz questions for the selected subject."""
return quiz_service.generate_quiz(request)

@app.route("/quiz/submit", methods=["POST"])
def submit_quiz():
"""Validates a user's answer and updates their score."""
return quiz_service.submit_quiz(request)

@app.route("/quiz/stream_feedback", methods=["POST"])
def stream_feedback():
"""Streams AI-generated detailed feedback on the answer."""
return quiz_service.stream_feedback(request)

@app.route("/quiz/progress", methods=["GET"])
def get_progress():
"""Returns the user's quiz progress, including score and number of quizzes attempted."""
def get_quiz_progress():
return quiz_service.get_progress()

@app.route("/quiz/leaderboard", methods=["GET"])
def get_leaderboard():
"""Returns the leaderboard of top players."""
return quiz_service.get_leaderboard()

@app.route("/quiz/badges", methods=["GET"])
def get_badges():
"""Returns the badges earned by the user based on their quiz progress."""
return quiz_service.get_badges()

@app.route("/quiz/retry", methods=["POST"])
def retry_quiz():
"""Allows the user to retry the quiz for a selected subject."""
return quiz_service.retry_quiz(request)

# === Peer Learning Routes ===
@app.route('/ask_question', methods=['POST'])
def ask_question():
"""Students can post questions"""
data = request.json
question = data.get("question", "").strip()
student_name = data.get("student_name", "Anonymous")

if not question:
return jsonify(success=False, message="Question cannot be empty")

question_entry = {
"question": question,
"student": student_name,
"answers": []
}

peer_questions.append(question_entry)
return jsonify(success=True, message="Question posted successfully")

@app.route('/answer_question', methods=['POST'])
def answer_question():
"""Students can answer posted questions"""
data = request.json
question_text = data.get("question", "").strip()
answer = data.get("answer", "").strip()
student_name = data.get("student_name", "Anonymous")

if not question_text or not answer:
return jsonify(success=False, message="Both question and answer are required")

for question_entry in peer_questions:
if question_entry["question"] == question_text:
# AI validation of the answer
ai_feedback = AI_VALIDATOR.generate_content(
f"Validate Provide your answer: {answer}"
)
validated_answer = {
"student": student_name,
"answer": answer,
"ai_feedback": ai_feedback.text
}
question_entry["answers"].append(validated_answer)
return jsonify(success=True, message="Answer submitted successfully with AI feedback")

return jsonify(success=False, message="Question not found")

@app.route('/get_questions', methods=['GET'])
def get_questions():
"""Fetch all posted questions with answers"""
return jsonify(success=True, questions=peer_questions)

if __name__ == "__main__":
app.run(debug=True)
64 changes: 64 additions & 0 deletions backend/services/peer_learning_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from flask import Flask, request, jsonify
import google.generativeai as genai

app = Flask(__name__)

# AI Model for Validation
AI_VALIDATOR = genai.GenerativeModel('gemini-1.5-flash')

# In-memory storage (Replace with a database in production)
peer_questions = []

@app.route('/ask_question', methods=['POST'])
def ask_question():
"""Students can post questions"""
data = request.json
question = data.get("question", "").strip()
student_name = data.get("student_name", "Anonymous")

if not question:
return jsonify(success=False, message="Question cannot be empty")

question_entry = {
"question": question,
"student": student_name,
"answers": []
}

peer_questions.append(question_entry)
return jsonify(success=True, message="Question posted successfully")

@app.route('/answer_question', methods=['POST'])
def answer_question():
"""Students can answer posted questions"""
data = request.json
question_text = data.get("question", "").strip()
answer = data.get("answer", "").strip()
student_name = data.get("student_name", "Anonymous")

if not question_text or not answer:
return jsonify(success=False, message="Both question and answer are required")

for question_entry in peer_questions:
if question_entry["question"] == question_text:
# AI validation of the answer
ai_feedback = AI_VALIDATOR.generate_content(
f"Validate the following answer and provide improvement suggestions: {answer}"
)
validated_answer = {
"student": student_name,
"answer": answer,
"ai_feedback": ai_feedback.text
}
question_entry["answers"].append(validated_answer)
return jsonify(success=True, message="Answer submitted successfully with AI feedback")

return jsonify(success=False, message="Question not found")

@app.route('/get_questions', methods=['GET'])
def get_questions():
"""Fetch all posted questions with answers"""
return jsonify(success=True, questions=peer_questions)

if __name__ == '__main__':
app.run(debug=True)
1 change: 1 addition & 0 deletions backend/services/quiz_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,4 @@ def calculate_score(answers, correct_answers, quiz_data):
score += 1 # Increment score for each correct answer

return score

113 changes: 113 additions & 0 deletions backend/services/student_card_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
from flask import request, jsonify
import google.generativeai as genai
import os

# Dummy student database (Replace with a real database in production)
students = {
"123": {
"studentId": "123",
"name": "Alice",
"subjects": {
"math": 80,
"science": 75,
"history": 85
},
"feedback": [
{
"subject": "math",
"comment": "Great progress in algebra!",
"timestamp": "2025-04-01T10:00:00Z"
},
{
"subject": "science",
"comment": "Needs more practice with experiments.",
"timestamp": "2025-04-02T14:00:00Z"
}
],
"recentActivity": "Completed algebra problems",
"lastUpdated": "2025-04-03T09:00:00Z"
}
}

# Configure Gemini AI
AI_MODEL = genai.GenerativeModel('gemini-1.5-flash')

def get_student(student_id):
"""Fetch student details."""
student = students.get(student_id)
if student:
return jsonify(student)
return jsonify({"error": "Student not found"}), 404

def add_feedback(student_id, request):
"""Add feedback for a student."""
student = students.get(student_id)
if not student:
return jsonify({"error": "Student not found"}), 404

feedback = request.json.get("feedback", "")
if not feedback:
return jsonify({"error": "Feedback cannot be empty"}), 400

student["feedback"].append(feedback)
return jsonify({"success": True, "message": "Feedback added"})

def get_progress(student_id):
"""Retrieve a student's academic progress."""
student = students.get(student_id)
if not student:
return jsonify({"error": "Student not found"}), 404

return jsonify({"name": student["name"], "progress": student["subjects"]})

def get_gemini_feedback(student, subject, recent_activity):
"""Generate AI feedback based on student performance and activity."""
prompt = f"""
The student {student['name']} has been learning {subject}.
Their recent activity: {recent_activity}.
Current scores: {student['subjects']} in subjects.
Provide personalized feedback and improvement suggestions.
"""
try:
response = AI_MODEL.generate_content(prompt)
return response.text if response else "No AI feedback available."
except Exception as e:
return f"Error fetching feedback: {str(e)}"

def get_interdisciplinary_suggestions(subject, recent_activity):
"""Generate interdisciplinary suggestions dynamically using Gemini AI."""
prompt = f"""
The student is learning {subject} and recently engaged in {recent_activity}.
Suggest relevant interdisciplinary connections to enhance their learning.
"""
try:
response = AI_MODEL.generate_content(prompt)
return response.text if response else "No interdisciplinary insights available."
except Exception as e:
return f"Error fetching suggestions: {str(e)}"

def get_student_insights(request):
"""Fetch AI-generated student insights, feedback, and interdisciplinary suggestions."""
data = request.get_json()

print("Received Data:", data) # Debugging

student_id = str(data.get('studentId'))
subject = data.get('subject')
recent_activity = data.get('recentActivity')

if not student_id or not subject or not recent_activity:
return jsonify({"error": "Student ID, subject, and recent activity are required"}), 400

student = students.get(student_id)
if not student:
return jsonify({"error": "Student not found"}), 404

# Get AI-generated feedback and interdisciplinary suggestions
ai_feedback = get_gemini_feedback(student, subject, recent_activity)
interdisciplinary_suggestions = get_interdisciplinary_suggestions(subject, recent_activity)

return jsonify({
"aiFeedback": ai_feedback,
"interdisciplinarySuggestions": interdisciplinary_suggestions
})
Binary file added frontend/public/images/aitutor.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 17 additions & 5 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,31 @@ import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import NavBar from "./NavBar";
import TutorSession from "./TutorSession/TutorSession";
import StudentCard from "./StudentCard/StudentCard";
import Quiz from "./Quiz/Quiz";
import PeerLearning from "./PeerLearning/PeerLearning";
import Home from "./Home/Home";
import Instructor from "./Instructor/Instructor";

function App() {
// Dummy student data
const studentData = {
name: "Alice",
subject: "math",
progress: 80,
recentActivity: "Completed chapter on Algebra",
};

return (
<Router>
<NavBar />
<Routes>
<Route path="/" element={<h1>Home Page</h1>} />
<Route path="/instructor" element={<h1>Instructor Page</h1>} />
<Route path="/peer-learning" element={<h1>Peer Learning Page</h1>} />
{/* Use key based on the current location */}
<Route path="/" element={<Home/>} />
<Route path="/instructor" element={<Instructor></Instructor>} />
<Route path="/peer-learning" element={<PeerLearning></PeerLearning>} />
{/* Pass studentData as a prop to StudentCard */}
<Route path="/student-card" element={<StudentCard student={studentData} />} />
<Route path="/quiz" element={<Quiz key={window.location.pathname} />} />
<Route path="/student-card" element={<h1>Student Card Page</h1>} />
<Route path="/tutor" element={<TutorSession />} />
</Routes>
</Router>
Expand Down
Loading