cloapp / app.py
Tabrejmlkhan's picture
Update app.py
47f045f verified
from flask import Flask, request, render_template, redirect, url_for
from transformers import AutoTokenizer, AutoModel
import torch
import os
os.environ["TOKENIZERS_PARALLELISM"] = "false"
app = Flask(__name__)
# Dictionary to store programs and their courses
programs = {}
# Default model name
current_model_name = 'sentence-transformers/all-mpnet-base-v2'
# Function to load the tokenizer and model dynamically
def load_model_and_tokenizer(model_name):
try:
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
return tokenizer, model, None
except Exception as e:
return None, None, str(e)
# Load the initial model and tokenizer
tokenizer, model, error = load_model_and_tokenizer(current_model_name)
def mean_pooling(token_embeddings, mask):
"""Applies mean pooling to token embeddings, considering the mask."""
mask = mask.unsqueeze(-1).expand(token_embeddings.size())
sum_embeddings = torch.sum(token_embeddings * mask, dim=1)
sum_mask = torch.clamp(mask.sum(dim=1), min=1e-9) # Avoid division by zero
return sum_embeddings / sum_mask
def compute_plo_embeddings():
"""Computes embeddings for the predefined PLOs."""
tokens = tokenizer(plos, padding=True, truncation=True, return_tensors='pt')
mask = tokens['attention_mask']
with torch.no_grad():
outputs = model(**tokens)
return mean_pooling(outputs.last_hidden_state, mask)
plos = [
"Analyze a complex computing problem and apply principles of computing and other relevant disciplines to identify solutions.",
"Design, implement, and evaluate a computing-based solution to meet a given set of computing requirements.",
"Communicate effectively in a variety of professional contexts.",
"Recognize professional responsibilities and make informed judgments in computing practice based on legal and ethical principles.",
"Function effectively as a member or leader of a team engaged in activities appropriate to the program’s discipline.",
"Support the delivery, use, and management of information systems within an information systems environment."
]
# Compute PLO embeddings (once at startup)
plo_embeddings = compute_plo_embeddings()
def get_similarity(input_sentence):
"""Calculates the similarity between an input sentence and predefined PLOs."""
tokens = tokenizer(input_sentence, padding=True, truncation=True, return_tensors='pt')
mask = tokens['attention_mask']
with torch.no_grad():
outputs = model(**tokens)
input_embedding = mean_pooling(outputs.last_hidden_state, mask)
similarities = torch.nn.functional.cosine_similarity(input_embedding, plo_embeddings)
return similarities
@app.route('/')
def index():
"""Home page displaying current programs and model status."""
return render_template('index.html', programs=programs, model_name=current_model_name)
@app.route('/set_model', methods=['POST'])
def set_model():
"""Allows users to dynamically change the model."""
global tokenizer, model, plo_embeddings, current_model_name
model_name = request.form['model_name']
tokenizer, model, error = load_model_and_tokenizer(model_name)
if error:
return render_template('index.html', programs=programs, message=f"Error loading model: {error}")
# Update the global model name and recompute embeddings
current_model_name = model_name
plo_embeddings = compute_plo_embeddings()
return redirect(url_for('index'))
@app.route('/addprogram', methods=['GET', 'POST'])
def add_program():
"""Adds a new program."""
if request.method == 'POST':
program_name = request.form['program_name']
if program_name not in programs:
programs[program_name] = {} # Initialize an empty dictionary for courses
return redirect(url_for('index'))
return render_template('addprogram.html')
@app.route('/addcourse', methods=['GET', 'POST'])
def create_course():
"""Creates a new course under a specific program."""
if request.method == 'POST':
program_name = request.form['program']
course_name = request.form['course_name']
outcomes = request.form['course_outcomes'].split('\n')
if program_name in programs:
programs[program_name][course_name] = outcomes # Add course to the selected program
return redirect(url_for('index'))
return render_template('addcourse.html', programs=programs)
@app.route('/match', methods=['POST'])
def match_outcomes():
"""Matches course outcomes with predefined PLOs."""
program_outcomes = request.form['program_outcomes']
print(program_outcomes)
course_outcomes = request.form['course_outcomes'].split('\n')
results = []
for co in course_outcomes:
co = co.strip()
if co: # Ensure the outcome is not empty
similarities = get_similarity(co)
top_matches_indices = similarities.topk(3).indices.tolist()
results.append({
'course_outcome': co,
'program_outcomes' : program_outcomes,
'best_matches': top_matches_indices
})
return render_template('result.html', results=results)
if __name__ == '__main__':
app.run(debug=True)